Transactional Migrations vs. Disabling Transactions: Which Knex Strategy Avoids ALTER TABLE Errors on MySQL 5.7+?
0 reputation · 11 Jun 2024, 02:35 UTC
0 reputation · 11 Jun 2024, 02:35 UTC
The goal is to deploy schema changes in a small application without downtime. Knex runs migrations inside a transaction by default, ensuring atomicity, but MySQL 5.7+ rejects certain ALTER TABLE statements that cannot be executed transactionally. Setting migrations: { transaction: false } allows those ALTERs to run, but the migration loses atomic rollback, risking a partially applied schema if the script fails mid‑run.
Constraints:
Unresolved decision: How to balance atomicity with compatibility, and what safeguards are necessary when disabling transactions?
Questions:
transaction: false aborts after some ALTER statements?MySQL 5.7+ does not reject ALTER TABLE inside a transaction — it executes the statement and issues an implicit commit. MySQL simply has no transactional DDL. So Knex's default per-migration transaction never gave you atomic rollback on MySQL in the first place; it only provides real atomicity on PostgreSQL. The choice isn't "transactions vs. no transactions" on MySQL — both paths leave partial DDL applied on failure. Disabling transactions mainly makes the bookkeeping honest and matches behavior across both databases.
knex_migrations table may not record the batch as complete, so Knex considers the migration pending.No. Knex has no compensation or automatic retry mechanism for partial DDL. Recovery is manual: either write idempotent migrations using schema.hasTable() / schema.hasColumn() guards, or clean up the half-applied objects before re-running.
Use expand-and-contract, which sidesteps atomicity entirely by making every step individually safe:
Each migration stays small, so a failure leaves a resume point rather than a broken schema. For big table rewrites, prefer ALGORITHM=INPLACE where your MySQL version supports it, or run pt-online-schema-change / gh-ost outside Knex — Knex doesn't orchestrate online schema changes, and COPY-algorithm ALTERs can hold metadata locks for a long time.
Knex's config keys (disableTransactions vs. per-migration options) have shifted across versions, so check your installed version's docs. Then confirm the behavior empirically: create a test migration with two ALTERs where the second intentionally fails, run it against MySQL with default settings, and inspect whether the first ALTER persisted and what knex_migrations recorded. Rehearse the expand-and-contract sequence on staging with production-like data volume to measure lock duration per ALTER.
One detail that could change this advice: your actual table sizes. If your largest tables are small (under a few GB), plain ALTERs with expand-and-contract are enough; the external online-schema-change tooling only becomes necessary at scale.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.