并行复制对大事务无效,因其在binlog中被标记为单一原子单元,无法拆分;确认启用需查performance_schema.replication_applier_status_by_worker及show slave status;解法唯有主库端安全拆事务。

为什么并行复制对大事务无效
MySQL的slave_parallel_workers参数只对“可并行事务组”起作用,而单个大事务在binlog中始终被标记为一个原子单元——无论你设成4还是16,SQL线程都只能等它执行完才能处理下一个。这不是配置没生效,是设计如此:LOGICAL_CLOCK依赖主库的binlog_group_commit,但一个未提交的大事务不会触发组提交,整个事务的全部event都打包在一个GTID下,从库worker根本无法拆分。
如何确认当前并行复制是否真正启用
光看slave_parallel_workers > 0没用,必须验证worker是否实际干活:
- 执行
SELECT * FROM performance_schema.replication_applier_status_by_worker;,检查WORKER_ID列是否有多个非空记录,且LAST_APPLIED_TRANSACTION在持续更新 - 查
SHOW SLAVE STATUS\G,确认Slave_SQL_Running_State显示类似Worker 1 running而非Waiting for dependent transaction to commit - 主库必须满足:
binlog_format = ROW、binlog_order_commits = ON(默认)、transaction_write_set_extraction = XXHASH64(8.0+)
长连接堆积的本质是SQL线程卡死,不是并发数不够
当大事务正在回放时,SHOW PROCESSLIST里SQL线程状态常为Updating或Deleting,此时所有worker都在等待该事务释放逻辑时钟锁。连接堆积表现是:
-
Threads_connected持续上涨,但Threads_running始终为1(仅SQL线程活跃) -
information_schema.PROCESSLIST中大量连接状态为Sleep,Time值不断增大 - 监控发现
Seconds_Behind_Master不降反升,而Exec_Master_Log_Pos几乎不动
这不是连接池配置问题,是SQL线程被单点阻塞导致后续所有客户端连接排队等待结果返回。
唯一有效的解法:在主库端拆事务,而不是调高worker数
别再折腾slave_parallel_workers = 32了——只要事务没拆,worker再多也闲置。安全拆分必须满足三个硬约束:
- 基于主键/时间字段分段:
WHERE id BETWEEN ? AND ?,避免LIMIT+ORDER BY created_at引发幻读和漏数据 - 每批显式
START TRANSACTION+COMMIT,确保每个批次生成独立GTID,才能被worker并行消费 - 记录断点:每次成功后把最大
id写入replica_split_checkpoint表,支持中断续跑,否则网络抖动一次就得重扫全表
最容易被忽略的是:拆分脚本本身必须带超时(如单次UPDATE超过5秒就报错退出)和重试(最多3次),否则某一批卡住,整个流程挂死,反而加剧延迟。











