Skip to main content

MY.L6.DEFAULT_STORAGE_ENGINE_NOT_INNODB — a table with no transactions and no foreign keys

  • Category: safety
  • Level: 6
  • Confidence: deterministic
  • Downtime class: none
  • Stability: stable
  • Suites: audit
  • Applies to: MySQL 8.4
  • Not transferable to MariaDB: this page describes MySQL 8.4 behavior. MariaDB answers the same driver and does not share these semantics, so SQLens refuses it outright rather than reasoning about it — see drivers/unsupported.

A table created without an explicit ENGINE takes the server default.

Under MyISAM that table has no transactions, no foreign keys and no crash recovery — and none of those absences raise anything:

  • a migration wrapped in a transaction simply does not roll back,
  • a foreign key is silently not enforced,
  • an unclean shutdown leaves the table needing repair.

Laravel's schema builder emits ENGINE only when database.connections.mysql.engine is configured, which is not the default. So the server value usually decides.

Flagged

SET GLOBAL default_storage_engine = MyISAM;

Preferred

SET GLOBAL default_storage_engine = InnoDB;

The one rule here that says pass out loud

A server can have default_storage_engine = MyISAM while disabled_storage_engines names MyISAM. The setting then looks wrong and cannot bite: no table can be created under an engine the server refuses to load.

Reporting nothing there would be indistinguishable from a rule that never ran. Reporting a failure would send somebody to change a setting that is already harmless. So this case is reported as a pass with its reason stated — one of the very few places in SQLens where a pass is a finding rather than silence.

Correcting the default is still worth doing. It removes a trap for whoever later shortens that refusal list.

What is read, and what is not

Only the server's value; the variable is settable per session, and a connection that set its own says nothing about what the next CREATE TABLE from somewhere else will inherit.

The comparison folds case — a my.cnf saying default_storage_engine=innodb produces the same behavior, and flagging it would be a pure spelling false positive. The refusal list is matched per entry, never as a substring.

If disabled_storage_engines could not be read at all, the rule reports undetermined rather than assuming nothing is disabled: "we could not ask" and "nothing is refused" are different sentences.

When this is expected

A deliberately mixed engine landscape. It is rare, and it belongs on the ignore list with the reason recorded there.

Sources