MY.L4.DROP_WITHOUT_DEPLOY_WINDOW — A drop breaks whoever is still reading
- Category: safety
- Level: 4
- Confidence: heuristic
- Downtime class:
online - Stability: stable
- Suites: lint
- Applies to: MySQL 8.4
Dropping an object breaks any still-running old application version that references it, the instant the migration lands. Level 1 asks whether the data is expendable; this level asks whether anyone is still reading.
The safe shape is expand/contract
A drop is safe as the second half of a two-deploy sequence:
- Deploy 1 ships code that no longer uses the object. The object stays.
- Deploy 2 — a later one — runs the drop.
Between them, both versions of the application can be running at once, and neither breaks.
Why this rule reads like its PostgreSQL sibling
Its level-1 neighbors deliberately do not: on MySQL, DDL is not transactional, so a drop commits itself and no transaction takes it back — a reader given PostgreSQL's wording there would believe they are protected.
This rule is the opposite case. The deploy window is not a property of the database. It is a property of what is still running in front of it, and that does not change with the engine. Writing a MySQL-flavored difference here would be inventing a distinction that does not exist.
Not transferable to MariaDB
The rule is registered for MySQL 8.4, and SQLens refuses a MariaDB connection outright rather than applying MySQL-shaped reasoning to another product. That the concern here happens to be engine-neutral does not make the connection supported.
Flagged
Schema::drop('legacy_events');
Preferred
// Deploy 1: ship code that no longer reads legacy_events. Nothing here.
// Deploy 2 (a LATER migration): the drop, once no running version references it.
Saying yes on purpose
#[SqlensAllowDestructive('the reads were retired in 2.4; this is the contract half')]
final class DropLegacyEventsTable extends Migration { /* … */ }
The annotation records a review. The finding is still produced and shown.
What the rule does not claim
It is heuristic, and deliberately so: SQLens reads the SQL, not your application code. It cannot prove an old version is gone — only that nothing in this migration says it is. Treat the finding as a prompt to confirm the window, never as proof it is missing.
It stays silent when the object is created in the same migration: something that never existed for a prior deploy cannot break one.
Sources
- MySQL 8.4 — online DDL operations — what a drop costs the server; the deploy-window question is about the application in front of it
The fix material this rule carries
A finding from this rule carries machine-readable fix material, using this sequence:
deploy_window_drop— Drop across two deploy windows so a rollback in between still finds what it needs.
The payload is material for you or an agent to apply. SQLens writes no migration and runs no DDL. See the remediation payload for every field, the placeholder semantics, and the version rules a consumer has to follow.