必须设binlog_transaction_dependency_tracking='writeset',否则从库无法收到可并行事务组;主库未启用该参数、binlog_format非row、gtid_mode未开启、表无主键或唯一键、binlog_row_image非full等任一缺失均导致退化为单线程。

必须设 binlog_transaction_dependency_tracking = 'WRITESET',否则从库开再多线程也白搭——它根本收不到可并行的事务组。
为什么改了 slave_parallel_workers 却还是单线程回放?
常见错误现象:SHOW PROCESSLIST 里只看到一个 Slave_worker 在跑,其余全是 Waiting for an event from Coordinator;Seconds_Behind_Master 持续上涨,但从库 CPU 利用率很低。
- 最直接原因:主库没生成有效的
last_committed,所有事务的该字段都是 0,Coordinator 只能全扔给一个 worker - 根源在于主库未启用
binlog_transaction_dependency_tracking = 'WRITESET'(默认是'COMMIT_ORDER') -
COMMIT_ORDER只看提交时间戳,对高并发单 session 场景几乎无法并行;WRITESET才能基于行级写集判断冲突 - 别漏前提:
binlog_format = ROW且gtid_mode = ON,否则WRITESET直接失效
binlog_transaction_dependency_tracking = 'WRITESET' 怎么配才真正生效?
这个参数只在主库起作用,且必须配合三项基础配置,缺一不可:
-
binlog_format = ROW:STATEMENT 或 MIXED 下 WRITESET 不计算写集,直接退化 -
gtid_mode = ON且enforce_gtid_consistency = ON:WRITESET 依赖 GTID 定位事务边界 -
transaction_write_set_extraction = 'XXHASH64':必须显式设置,否则 WRITESET 计算不启用(MySQL 8.0.22+ 推荐)
执行命令(主库):
SET PERSIST binlog_transaction_dependency_tracking = 'WRITESET'; SET PERSIST transaction_write_set_extraction = 'XXHASH64'; SET PERSIST binlog_transaction_dependency_history_size = 25000;
注意:binlog_transaction_dependency_history_size 控制写集哈希缓存大小,太小会导致旧事务写集被挤出,误判为有冲突。
为什么开了 WRITESET 还是 fallback 到单线程?
常见但容易被忽略的硬性限制:
- 表没有
PRIMARY KEY或NOT NULL UNIQUE KEY:WRITESET 无法提取写集,自动降级为COMMIT_ORDER,且不报错 - 主库
binlog_row_image != 'FULL':默认是FULL,但如果被显式改成MINIMAL或NOBLOB,写集信息缺失,WRITESET 失效 - 存在 DDL 语句(如
ALTER TABLE):它强制串行,会阻塞后续所有事务,哪怕其他事务之间无冲突 - 从库
slave_preserve_commit_order = ON(MySQL 8.0.27+ 默认开启):保序逻辑会让 worker 实际串行等待提交,吞吐下降明显
验证是否真生效:查 performance_schema.replication_applier_status_by_coordinator,看 WORKERS_PROCESSED 是否持续增长;若长期为 0,优先检查表主键和 binlog_row_image。
WRITESET 并不是万能加速器
它只解决“多个事务之间”的并行调度问题,对单个大事务完全无效:
- 一个
DELETE FROM orders WHERE id 事务,无论多大,仍被当作原子单元排队 - 这种事务内部的 100 万行变更,不会被拆开分发到多个 worker;并行复制不等于事务内部分片
- 真正卡住从库的,往往是这类大事务 + 缺少主键的组合:既无法并行,又因全表扫描导致回放极慢
所以调参前先确认业务 SQL 和表结构——WRITESET 的有效性,一半靠配置,一半靠数据模型是否干净。











