Skip to content

fix(migrations): serialize concurrent migrator runs - #8474

Open
itisrmk wants to merge 1 commit into
mikro-orm:masterfrom
itisrmk:cursor/serialize-migrator-up
Open

itisrmk wants to merge 1 commit into
mikro-orm:masterfrom
itisrmk:cursor/serialize-migrator-up

Conversation

@itisrmk

@itisrmk itisrmk commented Oct 18, 2026 •

Copy link
Copy Markdown

Concurrent migrator.up() / migrator.down() calls could both apply the same data migration. Each run now takes a lock for the whole call, then reads the executed set, so the waiter applies nothing that the first run already logged.

  • PostgreSQL (and PGlite): session pg_advisory_lock, held on a pinned connection. lock_timeout and statement_timeout are cleared only while waiting, then restored.
  • MySQL and MariaDB: GET_LOCK with a large positive timeout. MariaDB treats a negative timeout as invalid and would not lock.
  • SQL Server: session sp_getapplock.
  • File-backed SQLite: a lock file beside the database. BEGIN IMMEDIATE on a second connection would block the migration's own writes.

The lock name is the migrations table (schema + table). In-memory SQLite is not shared across connections. Oracle has no unprivileged session lock, so two Oracle processes can still race.

Closes #8456

Prepared with an AI coding agent.

Hold a session lock across migrator.up() and down() so a second replica
waits and then applies only migrations that are still pending. PostgreSQL
uses an advisory lock, MySQL and MariaDB use GET_LOCK, SQL Server uses
sp_getapplock, and file-backed SQLite uses a lock file.

Co-authored-by: Rahul Kashyap <itisrmk@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrator: concurrent migrator.up() runs are not serialised (no lock) — data migrations can apply twice

2 participants