Repository navigation
MySQL migration lock is skipped by void db reset and by Better Auth migrations #415
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Problem
PR #413 adds one lock per MySQL database for migrations. CLI runs hold GET_LOCK. Deploys to the Void platform write a lease row in _void_migration_lock. Two paths still change the database outside that lock:
void db reset / void db seed (MySQL)
drop every base table <- no lock; drops _void_migration_lock and _void_migrations too
applyMySqlMigrations <- takes the lock
hosted migration handler (void deploy)
runMySqlMigrations <- lease held
lease.release()
runAuthMigrations <- no lease
vp dev (migration plugin)
runMySqlMigrations <- GET_LOCK, released when it returns
runLocalVoidAuthMigrations <- no lock
What can go wrong:
- Reset during a deploy.
void db resetdrops the lease table while a deploy holds a lease. The deploy's next renew fails ("expired before this run finished"), or its next statement fails on a missing table. Reset then applies the files again under its own lock, so both runs can apply the same file. - Better Auth migrations at the same time. They read
information_schema, thenCREATE TABLE IF NOT EXISTSorALTER TABLE ... ADD COLUMN. MySQL has noADD COLUMN IF NOT EXISTS, so two runs at once can fail with "Duplicate column name".
void db reset asks for confirmation on a non-local host. The risk is highest when a shared database is reset during a deploy.
Repro
From the code (not run):
- Start a
void deploywhose MySQL migrations take a while, so it holds the lease. - Run
void db reset --yesagainst the same database. - Reset drops
_void_migration_lock. The deploy loses its lease.
For Better Auth: run two deploys of different projects on one database, both with Better Auth and a new auth column.
Cause
packages/void/src/cli/db.ts:599-611drops every table with no lock. The lock is taken only later, inapplyMySqlMigrations(:616).void db seedcalls the same function (:647).packages/void/src/runtime/migration-handler-mysql.ts:25-28runsrunAuthMigrations()afterrunMySqlMigrationsreturned. That function released the lease in itsfinally(:113).packages/void/src/plugin-migration.ts:75runs the SQL migrations (lock released on return), then:108-111runs the auth migrations.packages/void/src/runtime/auth-migrations.ts:346onward reads the tables, then creates or alters them;:198-199adds noIF NOT EXISTSfor MySQL.
Suggested fix
- Reset: take the same lock (
GET_LOCKplus the lease check) before it drops tables, and keep it until the migrations are applied. - Run Better Auth migrations before the lock or lease is released, in both runners.
Evidence
- Code read at the head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413. Not run.
- The lock is new in fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413 (
02d9e9b49). On main there is no lock at all, so these are gaps in the new lock, not regressions.
🤖 Generated with Claude Code
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Type
Fields
Priority
None yet
Activity
fix(void): split MySQL migration files and hold the migration lock th…
fix(void): split MySQL migration files and hold the migration lock th…