MySQL主动降级为单线程回放,因事务存在逻辑依赖;必须主库binlog_format=ROW、binlog_transaction_dependency_tracking=WRITESET且表有主键,从库slave_parallel_type=LOGICAL_CLOCK并合理设置slave_parallel_workers与slave_preserve_commit_order。

设了 slave_parallel_workers 却没提速?不是参数没生效,而是 MySQL 主动退回到单线程回放——这是最常见也最容易被误判的问题。
为什么 slave_parallel_workers > 0 却还是单线程回放
根本原因不是配置漏了,而是事务之间存在逻辑依赖,MySQL 自动降级保障一致性。典型现象包括:
-
SHOW SLAVE STATUS\G中Slave_SQL_Running_State长期卡在Waiting for preceding transaction to commit -
performance_schema.replication_applier_status_by_worker里多数 worker 状态是Waiting for an event from Coordinator,WORKERS_PROCESSED几乎不增长 - 主库写入集中在一张表、且该表无主键或唯一键 → 写集(writeset)提取失败,直接 fallback 到
COMMIT_ORDER,甚至进一步退化
关键验证点:查主库 SELECT @@binlog_format, @@binlog_transaction_dependency_tracking, @@transaction_write_set_extraction;若 binlog_format 不是 ROW,或 binlog_transaction_dependency_tracking 不是 WRITESET,并行复制就不可能真正启用。
必须同时满足的三端配置清单
缺一不可,且顺序不能颠倒。主库侧最容易被忽略,但它是并行能力的源头:
-
主库必须执行(持久化推荐):
SET PERSIST binlog_transaction_dependency_tracking = 'WRITESET';SET PERSIST transaction_write_set_extraction = 'XXHASH64';SET PERSIST binlog_row_image = 'FULL';(MINIMAL会导致写集为空) -
主库结构约束:所有参与复制的表必须有
PRIMARY KEY或NOT NULL UNIQUE KEY;否则 writeset 无法生成,自动降级 -
从库运行时设置:
STOP SLAVE;SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';(8.0 默认已是,但需确认非DATABASE)SET GLOBAL slave_parallel_workers = 12;(建议为 CPU 核数 × 1.5,如 8 核设 12)START SLAVE;
slave_preserve_commit_order 是双刃剑
这个参数在 8.0.27+ 默认开启,但它会强制 worker 按主库提交顺序完成提交——即使事务 A 和 B 写集完全不重叠,B 也得等 A 提交完才能提交。结果就是:
- worker 线程大量空转,
WORKERS_WAITING_GROUPS远高于WORKERS_PROCESSED_GROUPS - 延迟没降,CPU 利用率反而偏低
- 仅在需要级联复制或强 GTID 连续性时才必须开启;普通读写分离场景可考虑关掉:
SET GLOBAL slave_preserve_commit_order = OFF;
注意:关掉后要确保下游不依赖严格 commit order,比如不做级联复制或不将该从库再作为其他实例的主库。
如何验证是否真正在并行
别只看参数值,盯住实时运行态:
- 查活跃 worker:
SELECT * FROM performance_schema.replication_applier_status_by_worker;
→PROCESS_ID应有多个非空值,LAST_APPLIED_TRANSACTION应有不同 GTID - 查 coordinator 分发效率:
SELECT * FROM performance_schema.replication_applier_status_by_coordinator\G;
→ 关注WORKERS_PROCESSED_GROUPS是否持续增长;若长期为 0,大概率是表缺失主键或主库未开WRITESET - 查复制线程列表:
SHOW PROCESSLIST;
→ 应看到多个Slave_worker线程,状态不是全在等待
真正的瓶颈往往不在并发线程数本身,而在主库能否稳定输出可并行的 writeset —— 所以调优第一优先级永远是主库配置和表结构,而不是盲目加大 slave_parallel_workers 的值。


















