mysql 5.7在线加索引不直接锁表但会放大资源瓶颈,核心是innodb_online_alter_log_max_size默认128mb易触发db_online_log_too_big错误,导致ddl失败和dml回滚;需调大该参数并配合pt-online-schema-change的chunk-size、max-load等限流配置,同时优化索引数量与io策略。

因为在线加索引本身不锁表,但会放大已有资源瓶颈——日志溢出、锁等待、IO饱和三者叠加,直接拖垮写入链路。
innodb_online_alter_log_max_size太小触发DB_ONLINE_LOG_TOO_BIG
MySQL 5.7 在线 DDL 用 row log 记录并发 DML 变更,这个日志大小上限由 innodb_online_alter_log_max_size 控制,默认仅 128MB。对 100GB 级别表,几秒高并发写入就能撑爆它。
- 报错后整个 DDL 失败,且未提交的 DML 全部回滚,业务感知为批量超时
- 该参数不能动态修改,必须写进
my.cnf并重启 MySQL;大表场景建议设为512M或1G(需评估磁盘剩余空间) - 调大只是延长容忍窗口,不是根治方案——它掩盖了流量没控住的事实
pt-online-schema-change 默认参数加剧锁等待
很多人转向 pt-online-schema-change 避免锁表,但它的默认行为在高负载下反而更容易引发超时。
-
--chunk-size=1000(默认)导致事务太碎,频繁刷盘+锁持有次数翻倍,容易被innodb_lock_wait_timeout中断 - 必须显式加大:例如
--chunk-size=10000,具体值要看单行大小和innodb_buffer_pool_size -
--max-load="Threads_running=50"是硬性限流开关,不设就等于放任工具在系统已过载时继续切块 - 务必配
--set-vars='innodb_lock_wait_timeout=60,lock_wait_timeout=50',否则工具自身可能先被超时 kill
索引维护 + redo 刷盘双重 IO 压力爆发
你看到的 INSERT 变慢、连接卡在 updating 状态,本质是两个机制同时生效:
- InnoDB 必须为每条新记录同步更新所有二级索引,B+ 树插入 + 页分裂开销随索引数量非线性增长
-
innodb_flush_log_at_trx_commit=1(默认)强制每次 COMMIT 都fsyncredo 日志,建索引期间 DML 密集,IO 瓶颈被彻底暴露 - 临时缓解可设为
2,但要同步调大innodb_log_buffer_size和innodb_log_file_size,且不可用于强一致性场景
真正容易被忽略的是:加索引变慢从来不是“加索引”这一步的问题,而是它把原本就存在的资源争抢(锁、IO、日志空间)一次性全点爆了。查 sys.schema_unused_indexes 删掉长期不用的索引,比硬扛参数调优更有效。











