alter table等ddl操作必定强制中断当前事务,立即隐式提交此前所有dml,后续语句属新事务;autocommit=0无效,事务状态在ddl后变为0,无法回滚已提交操作。

ALTER TABLE 等 DDL 操作会强制中断当前事务,无论你是否显式 START TRANSACTION 或设了 autocommit=0 —— 所以“在事务里执行 DDL”这个动作本身就没有意义,还容易引发数据不一致。
DDL 会立即隐式提交,不是“可能”,是“必定”
MySQL 规定所有 DDL 语句(CREATE、DROP、ALTER、RENAME、ANALYZE TABLE、LOCK TABLES 等)执行时,会先提交当前事务,再执行 DDL,最后自动开启一个新事务。这意味着:
-
INSERT+ALTER TABLE+INSERT的组合中,第一个INSERT已提交,不可回滚;第二个INSERT属于新事务,ROLLBACK 对它无效 -
SET autocommit = 0完全无法阻止该行为——DDL 前 MySQL 会强制提交 - 错误日志里看不到显式 COMMIT,但
SELECT @@in_transaction在 DDL 后会返回0,说明事务已断
大事务 + DDL = 风险叠加,不是 1+1,是爆炸式放大
如果你在一个长事务里塞进 DDL,实际效果是:前半段业务逻辑已落地(但你误以为还能回滚),后半段逻辑运行在全新事务上下文中,且锁状态、隔离快照、undo log 都重置。典型问题包括:
- 业务层认为“整个操作原子”,结果只有一半生效,比如订单创建成功但优惠券绑定失败,且无法统一回滚
- DDL 触发元数据锁(
MDL),而大事务又长期持有行锁或间隙锁,二者叠加极易造成阻塞雪崩 - 大事务本就堆积大量 undo log,DDL 强制提交后,这部分 undo 不会被及时清理,反而延长 purge 压力
哪些 DDL 看似安全,实则一样危险?
别被“只读”表象骗了。以下语句同样触发隐式提交,常被忽略:
-
ANALYZE TABLE:统计信息更新,但会中断事务 -
OPTIMIZE TABLE:本质是重建表,等价于COPY算法 DDL -
SET PASSWORD(MySQL 8.0+)、SET DEFAULT ROLE:账户管理类语句也属 DDL 范畴 -
CREATE VIEW/DROP PROCEDURE:哪怕不碰数据,只要改元数据,就中断事务
真正安全的 DDL 执行方式是什么?
放弃“用事务包裹 DDL”的幻想,转为流程级保障:
- 把 DDL 从应用代码里彻底剥离,作为独立部署步骤,在低峰期或停写窗口执行
- 必须动态执行时(如 SaaS 多租户),先查
INFORMATION_SCHEMA.COLUMNS判断字段是否存在,再决定是否执行ALTER TABLE - 对大表,优先用
pt-online-schema-change或 MySQL 8.0+ 的ALGORITHM=INSTANT,它们不进事务,但靠影子表/元数据切换模拟原子性 - 监控必须覆盖 DDL 前后:
SELECT @@in_transaction、SHOW PROCESSLIST中的State字段(如Waiting for table metadata lock)











