根本原因是SQL线程单线程回放且执行环境劣于主库:从库无主键或缺失索引时UPDATE/DELETE需全表扫描,大事务串行阻塞,buffer_pool过小导致频繁磁盘IO。

SQL线程回放比主库执行慢,根本原因是执行环境不对等
主库写入时是“新鲜事务”,从库回放时是“重放旧日志”,两者面对的资源、锁、缓存、索引状态完全不同。这不是MySQL故意拖慢,而是复制链路天然带来的执行降级。
从库SQL线程卡在无主键或缺失索引的UPDATE/DELETE上
主库执行时可能已有热数据在innodb_buffer_pool里,且事务刚提交、行锁已释放;但从库回放时,同一张表若没主键或WHERE条件列没索引,就会触发全表扫描——尤其RBR模式下,每行变更都要定位再更新,I/O和CPU开销陡增。
- 典型现象:
SHOW PROCESSLIST里SQL线程长期显示Updating或Deleting,Exec_Master_Log_Pos几乎不动 - 快速验证:查
information_schema.TABLES确认表是否有PRIMARY KEY;用EXPLAIN跑一遍对应UPDATE语句看是否走索引 - 修复动作:给高频更新字段加索引,或强制业务层补主键;避免
ALTER TABLE ... DROP PRIMARY KEY这类操作
大事务在从库变成“单点阻塞”
主库可以并发执行多个事务,但默认单SQL线程的从库必须把一个大事务(比如DELETE FROM orders WHERE created_at )完整跑完,才能处理后续所有事件。期间其他库、其他表的变更全部排队等待。
- 延迟特征:
Seconds_Behind_Master突然跳涨几十分钟,Relay_Log_Space增长缓慢(IO已拉完),Slave_SQL_Running_State显示Executing event - 不要直接
STOP SLAVE; START SLAVE重启——它不会跳过,只会重试 - 真正有效的做法是:提前拆分(
LIMIT 1000+循环),或升级到MySQL 8.0启用WRITESET并行复制,让互不冲突的事务真正并发回放
从库硬件和负载干扰了SQL线程执行
很多团队把从库当“备胎”,配低规格机器,还顺手挂上报表查询、mysqldump备份、甚至log_slave_updates=ON开启二级复制——这些都会和SQL线程争抢CPU、内存、磁盘I/O。
- 关键指标:
iostat -x 1看%util是否持续>90%,top里mysqld进程%CPU是否被其他进程压制 -
FLUSH TABLES WITH READ LOCK这类备份命令会直接阻塞SQL线程,导致Seconds_Behind_Master飙升,但SHOW SLAVE STATUS里Slave_SQL_Running仍显示Yes——这是最隐蔽的坑 - 解决不是加参数,而是隔离:从库只做复制+读路由,备份走专用实例,报表走归档库
最常被忽略的一点:从库的innodb_buffer_pool_size如果远小于主库,哪怕同配置机器,热数据也大概率不在内存里——每次回放都得从磁盘捞页,速度直接掉一个数量级。


















