{"record":{"id":"9cb6f2f7edca7e33","repo":"symfony/http-foundation","slug":"advisory-locks-are-currently-not-implemented-for-pdo-driver","errorCode":null,"errorMessage":"Advisory locks are currently not implemented for PDO driver \"%s\".","messagePattern":"Advisory locks are currently not implemented for PDO driver \"(.+?)\"\\.","errorType":"exception","errorClass":"DomainException","httpStatus":null,"severity":"error","filePath":"Session/Storage/Handler/PdoSessionHandler.php","lineNumber":807,"sourceCode":"                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)');\n                    $releaseStmt->bindValue(':key1', $sessionInt1, \\PDO::PARAM_INT);\n                    $releaseStmt->bindValue(':key2', $sessionInt2, \\PDO::PARAM_INT);\n                } else {\n                    $sessionBigInt = $this->convertStringToInt($sessionId);\n\n                    $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');\n                    $stmt->bindValue(':key', $sessionBigInt, \\PDO::PARAM_INT);\n                    $stmt->execute();\n\n                    $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)');\n                    $releaseStmt->bindValue(':key', $sessionBigInt, \\PDO::PARAM_INT);\n                }\n\n                return $releaseStmt;\n            case 'sqlite':\n                throw new \\DomainException('SQLite does not support advisory locks.');\n            default:\n                throw new \\DomainException(\\sprintf('Advisory locks are currently not implemented for PDO driver \"%s\".', $this->driver));\n        }\n    }\n\n    /**\n     * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.\n     *\n     * Keep in mind, PHP integers are signed.\n     */\n    private function convertStringToInt(string $string): int\n    {\n        if (4 === \\PHP_INT_SIZE) {\n            return (\\ord($string[3]) << 24) + (\\ord($string[2]) << 16) + (\\ord($string[1]) << 8) + \\ord($string[0]);\n        }\n\n        $int1 = (\\ord($string[7]) << 24) + (\\ord($string[6]) << 16) + (\\ord($string[5]) << 8) + \\ord($string[4]);\n        $int2 = (\\ord($string[3]) << 24) + (\\ord($string[2]) << 16) + (\\ord($string[1]) << 8) + \\ord($string[0]);\n\n        return $int2 + ($int1 << 32);","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/symfony/http-foundation/blob/5aea19cd678fa4140f6108406f1096de5e9ed6e4/Session/Storage/Handler/PdoSessionHandler.php#L789-L825","documentation":"This DomainException is the default branch of PdoSessionHandler::doAdvisoryLock(): advisory (application-level) locking is only implemented for the 'mysql' (GET_LOCK) and 'pgsql' (pg_advisory_lock) drivers. Any other PDO driver — e.g. oci, sqlsrv, dblib — hits this branch when doRead() requests LOCK_ADVISORY mode. The class docblock also notes oci (DBMS_LOCK.REQUEST) and sqlsrv (sp_getapplock) implementations are still a TODO.","triggerScenarios":"PdoSessionHandler constructed with ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY] on a PDO connection whose ->getAttribute(PDO::ATTR_DRIVER_NAME) is not 'mysql' or 'pgsql' (e.g. oci:, sqlsrv:, dblib:), then any session read triggers doAdvisoryLock() and throws.","commonSituations":"Running Symfony sessions on Oracle or SQL Server with a lock_mode copied from a MySQL/Postgres configuration; custom PDO wrappers reporting unusual driver names; switching production databases without revisiting session handler options.","solutions":["Use PdoSessionHandler::LOCK_TRANSACTIONAL instead of LOCK_ADVISORY — transactional locking is implemented for mysql, pgsql, oci and sqlsrv (via SELECT ... FOR UPDATE / WITH (UPDLOCK, ROWLOCK)).","Remove the 'lock_mode' option entirely to use the default transactional locking.","If advisory locking on sqlsrv/oci is required, implement sp_getapplock / DBMS_LOCK.REQUEST yourself in a subclass overriding the locking strategy (upstream has it as a @todo).","Only set LOCK_ADVISORY when the DSN driver is mysql or pgsql; guard the option per environment."],"exampleFix":"// before\nnew PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_ADVISORY]); // oci/sqlsrv\n\n// after\nnew PdoSessionHandler($pdo, ['lock_mode' => PdoSessionHandler::LOCK_TRANSACTIONAL]);","handlingStrategy":"validation","validationCode":"$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);\nif (!in_array($driver, ['mysql', 'pgsql'], true) && ($options['lock_mode'] ?? null) === PdoSessionHandler::LOCK_ADVISORY) {\n    $options['lock_mode'] = PdoSessionHandler::LOCK_TRANSACTIONAL;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $session->start();\n} catch (\\DomainException $e) {\n    if (str_contains($e->getMessage(), 'Advisory locks are currently not implemented')) {\n        // reconfigure handler with LOCK_TRANSACTIONAL for this driver\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Only use LOCK_ADVISORY on mysql/pgsql connections","Prefer the default LOCK_TRANSACTIONAL, which has per-driver SQL for mysql, pgsql, oci, sqlsrv and sqlite","Check PDO::ATTR_DRIVER_NAME (not the DSN string) to decide lock mode"],"tags":["sessions","pdo","database","configuration","locking"],"backgroundTag":"method-not-implemented","analyzedSha":"5aea19cd678fa4140f6108406f1096de5e9ed6e4","analyzedAt":"2026-09-13T01:52:22.855Z","contentChangedAt":"2026-09-13T01:52:22.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}