给大表加字段加索引,结果库卡死了——Online DDL怎么做?
先说结论
MySQL 5.6+支持Online DDL,大多数ALTER TABLE操作不会锁表。但有些操作仍然危险,尤其是大表。生产环境推荐用pt-online-schema-change或gh-ost工具。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
给生产环境的大表加字段或加索引,是最容易引发生产事故的操作之一。我见过因为一条ALTER TABLE导致整个服务不可用半小时的事故。今天把原因和正确做法讲清楚。
为什么直接ALTER TABLE会卡死?
问题一:长时间持有MDL锁
ALTER TABLE会获取元数据锁(MDL锁)。如果有长事务在运行(比如一个没有提交的SELECT),ALTER TABLE会等待这个事务结束。更糟糕的是,ALTER TABLE的MDL锁请求会阻塞后续所有的DML和SELECT,导致雪崩。
问题二:大表重建时间长
有些DDL操作(比如修改列类型)需要重建B+树,几千万行的表可能要跑几十分钟。这期间表虽然可读写,但IO压力巨大,影响其他查询性能。
正确做法:pt-online-schema-change
原理是:
1. 创建一张新表(已经是修改后的结构)
2. 慢慢把旧表数据复制到新表(分批复制,不影响线上服务)
3. 通过触发器同步复制期间的增量变更
4. 复制完成后,原子地重命名表(旧表改名、新表改为原名)
# pt-online-schema-change 示例
pt-online-schema-change \
--alter "ADD INDEX idx_status (status)" \
--execute \
--chunk-size=1000 \
--max-lag=1 \
D=mydb,t=orders
--max-lag=1表示如果主从延迟超过1秒就暂停复制,避免影响业务。这个细节很重要。
实战踩坑:一次生产事故
我在元宇宙社交App时,有个同事直接在生产环境执行了ALTER TABLE给一张2000万行的表加字段。刚好有一个长事务没有提交,ALTER TABLE被 MDL锁阻塞,后续所有查询都被堵住。服务不可用了20分钟,直到kill掉那个长事务才恢复。
从那以后我们的规矩是:生产环境禁止直接执行ALTER TABLE,必须用pt-osc或gh-ost。
总结
生产环境给大表做DDL,一定要用pt-online-schema-change或gh-ost。直接ALTER TABLE的风险在于MDL锁和重建时间。面试时能说清楚“为什么危险”和“正确做法”,再加一个踩坑故事,非常有说服力。
下一篇聊一个每个后端开发都会遇到的问题:连接池参数怎么配?“Too many connections”怎么解决?
你们生产环境怎么做DDL的?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长