mysql 8.0 的 atomic ddl 首次实现数据库级原子性,innodb 表的 create/alter/drop/truncate 等操作默认自动原子执行,崩溃后无临时文件残留,binlog 与实际状态严格一致,但仅限官方标注“atomic ddl supported: yes”的语句且不支持非 innodb 引擎。

MySQL 8.0 的 Atomic DDL 不是为了“提高原子性”而推荐,而是它首次真正让 DDL 具备了数据库层面的原子性保障——此前版本压根没有这个能力。
Atomic DDL 不是可选项,而是 InnoDB 表 DDL 的默认行为
只要你的表用的是 InnoDB 引擎(默认),所有受支持的 DDL 操作(如 CREATE TABLE、ALTER TABLE、DROP TABLE、TRUNCATE TABLE)在 MySQL 8.0 中自动走原子流程。你不需要显式开启开关或加事务包裹。
- 不支持 Atomic DDL 的引擎(如
MyISAM、MEMORY)执行 DDL 时会直接报错:ERROR 1235 (42000): This version of MySQL doesn't yet support 'ALTER TABLE ...' for this storage engine -
mysql系统库下的所有表(如mysql.tables、mysql.columns)本身都是InnoDB表,因此用户管理类 DDL(CREATE USER、GRANT)也天然受保护 - 非 InnoDB 表无法参与原子流程,因为元数据变更必须写入事务型系统表,而只有
InnoDB能保证这些写入可回滚
崩溃后不会残留临时文件或半成品表结构
这是最直观的收益:MySQL 8.0 不再生成 #sql-ibXXXXX.ibd 或 #sql-XXXX.frm 这类中间文件。哪怕你在 ALTER TABLE 执行到 99% 时 kill -9 mysqld,重启后你也看不到任何残留。
- 原因在于物理文件操作(重命名、删除 .ibd)被推迟到
post-ddl阶段,且仅在数据字典事务成功提交后才执行 - 如果崩溃发生,
mysql.innodb_ddl_log表中记录的操作会被重放(replay)并清理,确保磁盘状态与字典一致 - 对比 MySQL 5.7:崩溃后常需手动清理
#sql-*.ibd、修复.frm和 InnoDB 字典不匹配,甚至要用innodb_force_recovery
Binlog 与实际状态严格对齐,主从复制更稳
Atomic DDL 把“更新字典 + 写 binlog + 修改存储引擎”三者绑进同一个内部事务。这意味着:
- binlog 中记录的 DDL 事件,必定对应一个已完全生效的元数据状态;不会出现“binlog 写了
DROP TABLE t,但从库报Table t doesn't exist” - 从库回放 DDL 时,不再需要猜测“这一步是否真的完成了”,因为 DDL 在主库要么全提交、要么全丢弃
- 注意:
binlog_format=STATEMENT下仍可能因函数/变量导致不一致,但 DDL 本身的原子性不受影响;推荐用ROW或MIXED
容易被忽略的关键限制:不是所有 DDL 都原子
官方文档明确标注了 Atomic DDL supported: Yes 的语句才受保护。常见陷阱包括:
-
INSTALL PLUGIN、UNINSTALL COMPONENT、CREATE SERVER等管理类语句不支持原子性 - 跨引擎操作(如
ALTER TABLE t ENGINE=MyISAM)不支持,因为 MyISAM 无法参与事务字典更新 -
RENAME TABLE是原子的,但RENAME DATABASE已被移除,不可用 - 即使语句支持原子性,若涉及锁等待超时(
Lock wait timeout exceeded),事务仍会回滚——这不是 bug,是 ACID 的正常体现
真正关键的不是“用了 Atomic DDL 就万事大吉”,而是理解哪些操作被覆盖、哪些仍需人工兜底。比如线上做大表 ALTER,仍要关注 MDL 锁阻塞、buffer pool 冲刷压力,原子性只管“失败后不脏”,不管“执行中不慢”。











