不一定安全。ALGORITHM=INPLACE仅保证不重建主表,但ADD INDEX等操作仍可能加锁,LOCK=NONE才是无锁关键;MODIFY/CHANGE COLUMN、加NOT NULL等易退化为COPY;pt-osc仍是兜底方案,但需严控触发器与磁盘风险。

ALTER TABLE 加 ALGORITHM=INPLACE 真的就安全吗
不一定。MySQL 5.6+ 支持 Online DDL,但是否真正“不锁表”取决于具体操作类型和存储引擎。InnoDB 表上 ADD COLUMN 默认可 inplace,但 ADD INDEX 在某些版本或配置下仍可能触发临时表重建。
-
ALGORITHM=INPLACE只表示不重建主表,不代表完全无锁——ADD FULLTEXT INDEX仍需短暂的MDL_WRITE锁,阻塞写入 -
ALGORITHM=COPY一定全表拷贝+锁表,必须避开业务高峰 - MySQL 8.0.12+ 引入
ALGORITHM=INSTANT,仅限加列(ADD COLUMN)且不能是首列、不能带默认值(除非DEFAULT NULL),速度最快、真正无锁 - 执行前务必查
INFORMATION_SCHEMA.INNODB_TRX和SHOW PROCESSLIST,确认没有长事务,否则 Online DDL 会被卡住等锁
如何判断某条 ALTER 是否走 Online DDL
别猜,用 EXPLAIN FORMAT=JSON 配合 ALTER 的预估语句(MySQL 8.0.23+ 支持 EXPLAIN ANALYZE,但更推荐直接看 performance_schema.table_io_waits_summary_by_table 或开启 innodb_print_ddl_logs=ON)。
- 最简单方式:加
ALGORITHM=INPLACE, LOCK=NONE执行,如果报错ERROR 1846 (HY000): ALGORITHM=INPLACE is not supported...,说明该操作不支持 Online -
LOCK=NONE是硬门槛——即使ALGORITHM=INPLACE成功,若没显式声明LOCK=NONE,MySQL 默认可能降级为LOCK=SHARED(阻塞写入) - 常见“看似安全实则危险”的操作:
MODIFY COLUMN类型变更(如VARCHAR(255) → VARCHAR(500)在 utf8mb4 下可能涉及行格式重写)、CHANGE COLUMN改名+改类型、加NOT NULL且字段有 NULL 值——这些都会 fallback 到 COPY
pt-online-schema-change 还有必要用吗
在 MySQL 5.7/8.0 主流版本中,纯 Online DDL 覆盖大部分场景,pt-online-schema-change(简称 pt-osc)已非首选,但它仍是兜底方案。
- 适合场景:
ADD COLUMN带非空默认值(如DEFAULT '2024-01-01')、大表加唯一索引、跨版本升级后 Online DDL 行为不一致时 - 关键风险点:pt-osc 依赖触发器,高并发写入下触发器延迟会导致从库延迟飙升;同时它会持续占用磁盘空间(影子表 + 日志表),
_old表残留是线上事故高频原因 - 必须做:
--dry-run测试流程、--max-load控制复制压力、--critical-load设置熔断阈值,上线前检查information_schema.TRIGGERS是否清理干净
修改过程中监控什么才真正有用
别只盯着 SHOW PROCESSLIST 里的 altering table 状态——那只是开始,真正要盯的是锁等待和复制延迟。
- 实时查锁:
SELECT * FROM performance_schema.data_locks WHERE OBJECT_NAME = 'your_table';,重点关注LOCK_MODE是否为X或IX,以及LOCK_STATUS是否为PENDING - 检查复制:
SHOW SLAVE STATUS\G中的Seconds_Behind_Master和SQL_Delay,Online DDL 在从库也是串行执行,大表操作极易堆积 - 磁盘 IO 压力:
iostat -x 1观察%util和await,尤其注意pt-osc期间tmpdir所在磁盘是否打满 - 一个容易被忽略的点:MySQL 8.0 开启
binlog_row_image=MINIMAL后,某些 Online DDL 操作产生的 binlog 体积剧增,可能撑爆磁盘或拖慢从库重放
事情说清了就结束


















