不能无脑信任ALGORITHM=INPLACE跳过锁表,仅对添加/删除普通二级索引、末尾加NULL列、改DEFAULT值等少数操作支持LOCK=NONE;加NOT NULL列、改类型等会触发COPY或短暂排他锁。

MySQL 8.0+ 直接用 ALGORITHM=INPLACE 能否跳过锁表?
能,但只对部分操作有效,不能无脑信任。比如 ADD COLUMN col VARCHAR(255) NULL 在 8.0 中大概率走 INPLACE、LOCK=NONE,不锁表;但加 NOT NULL DEFAULT 'x' 就会触发全表扫描填充默认值,哪怕版本再新也得锁——因为数据必须写进去。
关键看执行计划:跑完 ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE 后,查 INFORMATION_SCHEMA.INNODB_TRX 或 SHOW PROCESSLIST,如果看到 altering table 状态卡住、TRX_ROWS_LOCKED 暴涨,说明降级成 COPY 了。
- 优先测试:在从库或影子库上先跑一遍,观察
Performance Schema里的events_statements_history_long记录实际用了哪种算法 - 别信文档写的“支持”,要看
INFORMATION_SCHEMA.INNODB_METRICS中ddl_background_drop_table和ddl_background_create_table的计数是否为 0 —— 非零说明走了后台线程,大概率没锁,但仍有风险 - MySQL 5.7 不建议依赖
INPLACE,很多看似轻量的操作(比如改列类型)仍会隐式升级为COPY
为什么 pt-online-schema-change 还是生产首选?
它不依赖 MySQL 版本或 DDL 实现细节,靠的是“绕开原生 DDL 流程”:建 _new 表 → 加触发器捕获变更 → 分批拷贝 → 原子切换。整个过程原表始终可读写,MDL 写锁只在最后 rename 那一瞬间持有(毫秒级)。
但容易踩的坑比想象中多:
-
--chunk-size设太大(比如 50000),单次拷贝时间长,主从延迟拉高,binlog 大量堆积 - 没关
innodb_autoinc_lock_mode=2,高并发 INSERT 下触发器可能和自增锁冲突,导致死锁 - 原表有外键或全文索引,
pt-osc默认不处理,得加--foreign-key-index或手动删重建 - 切换前没检查
SHOW SLAVE STATUS的Seconds_Behind_Master,切完发现从库落后十几分钟
UPDATE/DELETE 大表时,分批逻辑为什么不能用 LIMIT OFFSET?
因为 OFFSET 越往后扫描行数越多,MySQL 得跳过前面所有行才能定位,实际是全表扫描 + 全表加锁。你看到的“卡住”,往往是 INNODB_TRX.TRX_ROWS_LOCKED 达到百万级,不是真锁表,而是行锁堆积 + MVCC 版本链爆炸。
正确做法是基于主键范围驱动:
- 必须确保
WHERE条件走主键或唯一索引,EXPLAIN显示type=range,不是ALL - 用
WHERE id > ? AND id 切片,每次取 <code>MAX(id)当终点,避免漏数据 - 每批控制在 500–1000 行(视单行大小而定),
ROW_COUNT()返回 0 就停 - 批次间加
SLEEP(0.05),缓解 purge 线程压力,否则旧版本堆积导致ibdata1暴涨
没权限装 pt-osc,又不敢直接 ALTER,还有啥轻量方案?
可以手写双写迁移逻辑,比工具重但可控性强。核心是三阶段:新建空表 → 应用双写(老表写完立刻同步新表)→ 数据追平后切流量。
难点不在代码,在一致性保障:
- 双写必须用同一事务包裹,否则中间失败会导致数据分裂;Java 里用
@Transactional+DataSourceTransactionManager控制 - 追平阶段要对比
CHECKSUM TABLE,不是简单比行数——InnoDB 的CHECKSUM有精度限制,千万级表建议用pt-table-checksum - 切流不能只改 DAO 层,得配合配置中心灰度开关,先切 1% 流量,观察
SHOW ENGINE INNODB STATUS里的SEMAPHORES是否异常 - 别忘了清理旧表的 binlog,否则
expire_logs_days不生效,磁盘悄悄爆掉
真正麻烦的从来不是“怎么改结构”,而是改完之后没人盯着 INNODB_METRICS 里 buffer_pool_read_requests 和 buffer_pool_wait_free 的突变——那才是锁问题开始发酵的地方。


















