slave_parallel_workers设了却没提速,是因为事务依赖阻断并行回放:主库无主键/唯一索引、非唯一条件更新、大事务、auto_increment锁模式等导致writeset失效,退化为串行;需主库开启writeset依赖追踪、row格式、repeatable-read隔离级,并配合主库减负与从库调优。

为什么 slave_parallel_workers 设了却没提速?
设了 4 个并行线程,但 SHOW SLAVE STATUS 里 Seconds_Behind_Master 还是涨得飞快,甚至 Slave_SQL_Running_State 长期卡在 “Waiting for dependent transaction to commit”——这不是并行没生效,而是事务依赖阻断了并行回放。
InnoDB 并行复制(基于 LOGICAL_CLOCK)只对“无写集冲突”的事务才真正并发执行。如果主库上多个事务更新同一行或同一张表的同一索引范围,从库会按提交顺序串行回放,哪怕开了 16 个 slave_parallel_workers 也白搭。
-
slave_parallel_type = LOGICAL_CLOCK是前提,DATABASE类型已淘汰,别用 - 主库必须开启
binlog_transaction_dependency_tracking = WRITESET(MySQL 8.0.22+),否则从库无法精准识别事务间是否真正独立 - 主库
binlog_row_image = FULL,否则 WriteSet 计算不完整,导致误判依赖 - 检查
SHOW SLAVE STATUS\G中Retrieved_Gtid_Set和Executed_Gtid_Set差距是否持续扩大——若差距大但Seconds_Behind_Master不涨,说明是网络/IO 拉取慢;若两者接近但延迟高,才是 SQL 线程回放瓶颈
WRITESET 依赖计算失效的常见原因
WriteSet 不是万能的。它靠解析 binlog event 中的主键/唯一键值来标记“被修改的记录集合”,一旦碰到以下情况,就会退化为保守模式(按 GTID 顺序串行):
- 表没有主键或唯一索引:WriteSet 无法定位具体行,直接放弃并行,所有事务排队
- UPDATE/DELETE 语句使用非唯一条件(如
WHERE status=1):WriteSet 只能标记整张表,造成大面积假依赖 - 大事务混杂小事务:一个更新 10 万行的事务会生成超大 WriteSet,拖慢整个队列调度,且容易触发
slave_preserve_commit_order=ON强制串行 - 主库用了
innodb_autoinc_lock_mode = 0(传统锁模式):AUTO_INCREMENT 分配不可预测,WriteSet 无法安全推断冲突
验证方法:SELECT * FROM performance_schema.replication_applier_status_by_worker; 查看各 worker 的 LAST_SEEN_TRANSACTION 和 WORKING_ON_TRANSACTION 是否长期为空——空意味着没活干,大概率是依赖阻塞或没事务可分发。
从库回放加速的实操组合拳
单靠调大 slave_parallel_workers 解决不了根本问题。真实有效的做法是“主库减负 + 从库适配 + 架构兜底”:
- 主库侧:给高频写表补全主键或添加唯一索引;把批量 UPDATE 拆成带主键 IN 的小批次(如
WHERE id IN (1,2,3,...));禁用INSERT ... SELECT大表操作,改用分页导出+LOAD DATA - 从库侧:设
slave_parallel_workers = 8~16(不超过 CPU 核数的 1.5 倍);关闭slave_preserve_commit_order(仅当业务能容忍轻微因果乱序时);增大slave_checkpoint_period(如 60)减少刷 checkpoint 开销 - 架构层:对延迟敏感业务,读从库前先查
SELECT MASTER_POS_WAIT(...)或用WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS等待指定 GTID 执行完;核心表单独拆出专用从库,避免被其他业务写入拖累
别忽略 binlog format 和隔离级别的隐性影响
即使参数全开,binlog_format = STATEMENT 或 READ-COMMITTED 隔离级别也会让 WriteSet 彻底失效。
-
STATEMENT格式下没有行级变更记录,WriteSet 无从计算——必须是ROW -
READ-COMMITTED下 InnoDB 不保留前镜像(undo log 被快速清理),导致从库无法重建事务写集;生产环境务必用REPEATABLE-READ - 主库
innodb_flush_log_at_trx_commit = 1和sync_binlog = 1是强一致性保障,但会增加主库写延迟;若允许短暂不一致,可折中为innodb_flush_log_at_trx_commit = 2+sync_binlog = 1000,降低主库压力间接缓解从库追赶压力
延迟不是单纯“从库慢”,而是主从链路上任何一环的瓶颈放大。WriteSet 并行只是其中一环,调参前先确认主库 binlog 写入节奏、网络传输稳定性、从库磁盘 IO 能力是否匹配——否则再高的 slave_parallel_workers 值,也只是在等 I/O 完成。











