Repository navigation
Managed MySQL deploys send a migration without breakpoints as one multi-statement query, which Hyperdrive does not support #414
Description
Problem
A MySQL app deploys to the Void platform with void deploy. The platform applies pending migrations through the app Worker's migration handler. That handler reaches MySQL through Hyperdrive.
A migration file can have several statements and no --> statement-breakpoint lines. A hand-written file is the usual case; void db generate adds the lines. The handler sends such a file as one query, on a connection opened with multipleStatements: true.
Cloudflare's Hyperdrive docs list "Multi-statement queries" as an unsupported MySQL feature. So this file will probably fail on a real Hyperdrive, and the deploy stops. We have not run this against a real Hyperdrive. Miniflare's local Hyperdrive is a plain TCP proxy, so local runs pass.
| Path | Connects through | File with several statements and no breakpoints |
|---|---|---|
void db migrate, void deploy --platform cloudflare |
DATABASE_URL, direct |
sent as one query; MySQL accepts it |
void deploy (Void platform) |
Hyperdrive | sent as one query; unsupported per Cloudflare docs |
Two related gaps for the same files:
-
No partial-apply note. When a file fails partway,
void db migrateadds a note: "MySQL commits schema changes immediately, so earlier statements in<file>may already be applied...". The note shows only when at least one statement finished. A file without breakpoints is one query, so the count stays 0 and the note never shows, even when its firstCREATE TABLEwas committed. On MySQL 8.4:■ migration 0002_comments.sql failed: Key column 'nope' doesn't exist in tableThe table
commentsnow exists, but the file is not recorded. The next run fails withTable 'comments' already exists. The same SQL with a breakpoint line shows the note. -
Sharded Vitess. Each file runs between
BEGINandCOMMIT. On a sharded Vitess keyspace (for example PlanetScale MySQL), the default transaction mode isMULTI. A commit that fails on one shard does not roll back the shards that already committed (Vitess docs, shard isolation and atomicity). So a data-only file that writes to several shards can partly apply.docs/guide/database/mysql.md:58says "a failed file that only changes data leaves the database unchanged". Not run on a sharded keyspace.
Repro
Hyperdrive (not confirmed live):
- In a MySQL app, add
db/migrations/0002_two.sql(and its journal entry) with no breakpoint line:CREATE TABLE comments (id int primary key); CREATE TABLE tags (id int primary key);
- Run
void deployto the Void platform. - Per Cloudflare's docs, Hyperdrive rejects the multi-statement query and the migration fails.
Missing note (seen on MySQL 8.4):
- Add
0002_comments.sqlwith no breakpoint line:CREATE TABLE comments (id int primary key); ALTER TABLE counters ADD CONSTRAINT bad FOREIGN KEY (nope) REFERENCES comments(id);
- Run
void db migrate. The error has no note, andcommentsexists. - Run it again:
Table 'comments' already exists.
Cause
packages/void/src/runtime/migration-handler-mysql.ts:53-57opens the Hyperdrive connection withmultipleStatements: true;:88-91sends each piece fromsplitMigrationSql. On main::51-54and:71-73.packages/void/src/runtime/migration-handler.ts:714-720:splitMigrationSqlreturns the whole file as one piece when it has no breakpoint line.packages/void/src/migrations/runner-mysql.ts:148-167:rancounts finished queries, and the note needsran > 0(:163-164, message at:115-126).
Suggested fix
- For MySQL, reject a file with several statements and no breakpoint lines when Void plans migrations, with a clear message ("add
--> statement-breakpointafter each statement"). Then dropmultipleStatementsfrom the Hyperdrive connection. A SQL-aware splitter is the other option, but it must respect strings, comments andBEGIN ... ENDbodies. - Show the note for a failed file without breakpoints when the file has more than one statement and the transaction is no longer open.
- Docs: say that on sharded Vitess a file that writes to several shards is not atomic.
- Check the behavior once against a real Hyperdrive.
Evidence
- Code read at origin/main and at the head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413.
- Cloudflare docs, Hyperdrive "Supported databases and features", "Unsupported MySQL features": "Multi-statement queries".
void db migrateon MySQL 8.4 with the head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413: the output above, thenTable 'comments' already existson rerun.- Vitess docs on shard isolation and atomicity (default
MULTImode). - fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413 does not change the multi-statement send. It adds the per-file transaction and the note, and the note does not cover these files. On main there is no note at all.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
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…