千万级大表加索引不敢动?Online DDL和pt-online-schema-change实测

来源:互联网 时间:2026-08-31

大表加索引是站长的经典恐惧:ALTER TABLE一执行,表被锁住,网站瞬间打不开,KILL掉还要回滚几小时。以前确实是这样,MySQL 5.6之后Online DDL成熟了,加索引这类操作可以在线做,执行期间允许并发读写。但“可以在线”不等于“随便什么时候都行”,坑还是有的。

Online DDL的原理:操作分三阶段,准备阶段拿元数据锁(很快),执行阶段在InnoDB内部建临时索引文件同时记录增量变更,最后提交阶段短暂拿锁把增量应用进去。绝大部分时间不阻塞业务,坑就在最后那个提交锁——如果有长事务一直占着表,DDL会在收尾时一直等,而它一等,后面所有查询全排队,现象就是“加索引把站锁死了”。

-- 1. 动手前先查有没有长事务
SELECT * FROM information_schema.INNODB_TRX
ORDER BY trx_started LIMIT 5;
-- trx_started超过几秒的,先处理掉再DDL

-- 2. 加索引(InnoDB在线操作)
ALTER TABLE articles ADD INDEX idx_status_time (status, created_at), ALGORITHM=INPLACE, LOCK=NONE;
-- ALGORITHM=INPLACE LOCK=NONE:明确要求不锁表
-- 如果MySQL说做不到会直接报错,而不是悄悄降级锁表

ALGORITHM和LOCK这两个显式参数我建议必写。不写的话,MySQL遇到不支持在线的操作会自动降级成锁表执行,命令照样跑,表照样锁,你以为没事其实站已经挂了。显式写上,不支持就直接报错终止,把选择权留给自己。

注意不是所有操作都能在线:加索引、加列、删列都是INPLACE;改列类型是COPY(锁表);5.6加全文索引也是COPY。执行前拿ALTER TABLE ... , ALGORITHM=INPLACE, LOCK=NONE试一下,报不报错一试便知。

pt-online-schema-change是另一条路:它建一张影子表,用触发器同步增量,最后原子改名切换。优点是各版本通用、可以限速(--max-load控制负载)、失败可以安全重试;缺点是要占双倍磁盘、有触发器开销。表特别大或者MySQL版本老,用它更稳。

pt-online-schema-change \
--alter "ADD INDEX idx_status_time (status, created_at)" \
D=mydb,t=articles,u=root,p=密码 \
--max-load Threads_running=50 \ # 超过50并发就暂停复制
--chunk-time 1.0 \ # 控制批处理节奏
--execute

不管哪种方式,都请在低峰期执行,并且执行时盯两样东西:SHOW PROCESSLIST看DDL进度,业务监控看错误率。事后EXPLAIN验证索引真的被用上了,别加完索引优化器不认,白忙一场。

数据来源:MySQL官方手册

相关文章

标签:

A5创业网 版权所有

返回顶部