Destructive schema changes: DROP TABLE, DROP COLUMN, TRUNCATE
These statements are not slow — on 8.0.29+ DROP COLUMN is even instant. The risk is different: the data is gone, and MySQL DDL cannot be rolled back. A migration tool's "down" step cannot restore rows it never saved.
What the manual says
- DDL statements cause an implicit commit; they are not part of your transaction and cannot be rolled back after they complete.
- DROP TABLE removes the table definition and all data; TRUNCATE TABLE drops and re-creates the table (it is DDL, not a DELETE).
- Dropping a column: Instant Yes* (8.0.29+), rebuilds table, concurrent DML permitted (Column operations) — fast, and irreversible.
The safe pattern: expand / contract
- Stop writing the column or table in application code; deploy.
- Stop reading it; deploy; verify with query logs or metrics that nothing touches it.
- Only then drop it — in a later migration, with a verified backup if the data has any value.
How Presift flags it
✖ MG001 ERROR migration.sql:1
ALTER TABLE users DROP COLUMN legacy_flag permanently discards the column's data
Why: Dropping a column removes its data for every row; the migration tool cannot restore it. (On MySQL 8.0.29+ DROP COLUMN itself can be INSTANT; the risk here is data loss, not locking.)
Do: Prefer expand/contract: stop reading/writing the column in application code first, deploy, verify, then drop in a later migration. If intentional, annotate: -- presift: allow MG001 <reason>
✖ MG001 ERROR migration.sql:1
DROP TABLE sessions_old permanently removes the object and its data
Why: DROP TABLE cannot be rolled back; MySQL DDL is not transactional.
An intentional drop stays visible but no longer fails the check when annotated: -- presift: allow MG001 table unused since 2025-01, backup verified. The reason is recorded in the report, so the review trail lives in the migration itself.
Evaluate it on your own migrations — 30 days, whole product, no key to copy
Add the Action to a pull-request workflow and give the job id-token: write. On its first
run the client asks GitHub for the job's own identity token and exchanges it, in memory, for a
short-lived evaluation entitlement. There is no form, no account, no card and nothing to paste.
name: migration-safety
on: [pull_request]
permissions:
contents: read
id-token: write # lets Presift start your 30-day evaluation
jobs:
presift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nishu-sde/presift@v1
with:
paths: db/migrations
fail-on: error
One 30-day evaluation per GitHub owner — an organisation or a personal account.
Linux x86_64 runners with Python 3.9+ (GitHub-hosted ubuntu-* runners qualify). Fork pull
requests cannot evaluate, because GitHub issues them no identity token. Outside GitHub Actions the
evaluation is not available; a paid organisation key is.