大家好,我是小耶,写功课只是为了我踩过的坑,你们别再踩了!
凌晨两点,业务低峰期。
你准备给一张8000万行的订单表加一个字段。按照计划,停机窗口30分钟,应该够了吧?
结果ALTER TABLE跑了47分钟还没结束。业务方电话打过来了:“系统怎么打不开了?”
——因为DDL锁表了。
MySQL 5.6之前,加字段、加索引这种操作,全程锁表,写操作全部阻塞。8000万行的表,DDL跑几个小时,业务就停几个小时。
MySQL 5.6引入了Online DDL,5.7和8.0持续增强。但很多人只知道“Online DDL不锁表”,却不清楚什么场景真的不锁、什么场景照样锁。
今天把Online DDL彻底拆开讲清楚。
一、Online DDL的三种算法
MySQL执行DDL时,会根据操作类型和参数选择不同的算法。理解这三种算法,是理解Online DDL的基础。
算法一:COPY
最原始的方式。MySQL创建一个新的临时表,把原表数据逐行复制到新表,复制完成后删除原表、重命名新表。
全程锁写——复制期间,原表的写操作全部阻塞。8000万行的表,COPY算法可能要跑几个小时。
算法二:INPLACE
MySQL 5.6引入。不需要复制整张表的数据,直接在原表上修改。但不一定完全不锁表——某些INPLACE操作仍然需要短暂的锁(比如修改表结构时)。
INPLACE的核心是:尽量在原有数据文件上直接操作,减少数据复制。
算法三:INSTANT
MySQL 8.0.12引入。只修改数据字典中的元数据,不触碰实际数据文件。加字段这种操作,INSTANT算法几乎瞬间完成——因为只是在表的元数据里加了一条记录,已有的数据行根本不需要动。
INSTANT是Online DDL的终极形态:真正的零锁表、秒级完成。
二、不同DDL操作,分别用什么算法?
加字段(ADD COLUMN)
MySQL 5.6:INPLACE,但需要重建表(实际上类似COPY)
MySQL 5.7:INPLACE,支持在线操作
MySQL 8.0.12+:INSTANT,秒级完成(仅限在表末尾加字段)
MySQL 8.0.29+:支持在任意位置加字段,但可能降级为INPLACE
加索引(ADD INDEX)
MySQL 5.6+:INPLACE,支持在线操作
加索引期间,读操作不阻塞,写操作可以并发进行
但加索引的耗时与数据量成正比——8000万行的表,加索引可能需要几十分钟
修改字段类型(MODIFY COLUMN)
大部分情况:COPY,需要重建表
修改
VARCHAR长度(增大):INPLACE可能支持修改
INT到BIGINT:COPY,需要重建表
删除字段(DROP COLUMN)
MySQL 8.0.29+:INSTANT
更早版本:INPLACE或COPY
修改字符集(CONVERT TO CHARACTER SET)
- COPY,全程锁写,大表慎用
三、怎么判断DDL会不会锁表?
方法一:看ALGORITHM和LOCK参数
执行DDL时可以显式指定算法和锁级别:
-- 指定使用INPLACE算法,允许并发读写
ALTER TABLE orders ADD COLUMN remark VARCHAR(200),
ALGORITHM=INPLACE, LOCK=NONE;
如果MySQL不支持指定的算法或锁级别,会直接报错——这是好事,至少你知道这个操作不安全。
方法二:查看INFORMATION_SCHEMA.INNODB_TABLES
MySQL 8.0可以查询表的DDL执行历史,了解之前的操作使用了什么算法。
方法三:看官方文档的Online DDL支持矩阵
MySQL官方文档有一张详细的表格,列出了每种DDL操作支持的算法和锁级别。做DDL之前先查一下,比盲目执行靠谱得多。
四、大表DDL实战避坑方案
避坑1:别在业务高峰期做DDL
即使是Online DDL,加索引、修改字段类型等操作仍然会消耗大量I/O和CPU。业务高峰期做DDL,可能拖慢整个数据库的响应时间。
避坑2:优先用INSTANT算法
MySQL 8.0.12+加字段(末尾)用INSTANT,秒级完成。升级到8.0是解决大表DDL最直接的办法。
避坑3:用pt-online-schema-change或gh-ost
如果MySQL版本不支持INSTANT,或者DDL操作必须用COPY算法,可以用Percona的pt-online-schema-change或GitHub的gh-ost。原理是:创建新表 → 复制数据 → 增量同步 → 原子切换。整个过程对业务透明,但需要额外的磁盘空间和更长的执行时间。
避坑4:DDL前先备份
不管用什么方案,DDL之前先备份。DDL失败可能导致数据不一致,有备份才有退路。
避坑5:控制单次DDL的规模
一次DDL只做一个操作。加字段和加索引分开做,避免一个DDL语句同时触发多种算法。
五、小结
Online DDL不是“所有DDL都不锁表”,而是“在特定条件下不锁表”。COPY算法全程锁写,INPLACE算法大部分场景不锁写但可能短暂锁,INSTANT算法才是真正的秒级零锁表。做DDL之前,先确认三件事:MySQL版本支持什么算法?你的DDL操作属于哪种类型?业务能不能接受短暂的锁?搞清楚这些,比盲目执行安全得多。
小耶在手,SQL 不愁
还有什么想了解的,欢迎留言!小耶一定知无不言言无不尽……我们下次见~