MySQL 5.7中slave_parallel_workers>0仍单线程回放,根本原因是slave_parallel_type默认为DATABASE(仅跨库并行),必须显式设为LOGICAL_CLOCK并配合主库ROW格式binlog、组提交及从库元数据存表(TABLE)才生效。

slave_parallel_workers > 0 但仍是单线程回放
设了 slave_parallel_workers = 4 却没效果,大概率是因为 slave_parallel_type 还是默认的 'DATABASE'。这个值在单库场景下完全无效——哪怕你设成 32,所有事务都落在同一个库(比如 app_db),就只用 1 个 worker。
必须显式执行:
STOP SLAVE;SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';START SLAVE;
验证是否生效:SELECT @@slave_parallel_type; 返回必须是 'LOGICAL_CLOCK',不是 'DATABASE';再查 SHOW PROCESSLIST; 应看到多个 system user 开头的 Worker N 线程,而非仅一个 SQL Thread。
主库没配组提交或 binlog_format 不对
LOGICAL_CLOCK 模式依赖主库 binlog 中的 last_committed 和 sequence_number 字段分组事务。这两个字段由主库组提交机制生成,缺一不可:
- 主库
binlog_format必须为'ROW'(MIXED在非确定性语句下会退化为STATEMENT,丢掉依赖信息) - 主库
binlog_order_commits = ON(默认开启,但建议显式确认) - 主库不能用
NOW()、UUID()等非确定性函数,否则事务会被降级为单线程回放
检查主库配置:SHOW VARIABLES LIKE 'binlog_format'; 和 SHOW VARIABLES LIKE 'binlog_order_commits';。
从库元数据存储方式不兼容
MySQL 5.7 的并行复制要求从库元数据必须存表,否则 coordinator 无法正确调度 worker,会静默退回到单线程:
SET GLOBAL master_info_repository = 'TABLE';SET GLOBAL relay_log_info_repository = 'TABLE';SET GLOBAL relay_log_recovery = ON;
这三个设置必须同时生效,且需在 STOP SLAVE 后执行。如果仍用文件存储(FILE),即使其他条件全满足,并行也会中断或根本不起作用。
worker 数设得过高反而拖慢吞吐
slave_parallel_workers 不是越大越好。实测中:
- 4~8 是多数 OLTP 场景合理起点,建议从 4 开始调优
- 超过 CPU 核心数后,上下文切换、锁竞争开销会吃掉收益,甚至导致
Seconds_Behind_Master波动更大 - 观察
top -H -p $(pgrep mysqld):如果只有 1–2 个 worker 跑满、其余闲置,瓶颈不在并发度,而在磁盘 I/O 或 SQL 回放本身(比如大UPDATE缺索引)
跨机房同步时(如北京⇄广州),RTT 20–50ms 就会让网络和磁盘成为真正瓶颈,调 slave_parallel_workers 基本白忙。
真正卡住的地方往往不是参数没开,而是主库 binlog 依赖缺失、从库元数据未切表、或者 worker 被大事务/锁等待/慢查询拖住。别只盯着 Seconds_Behind_Master,它在并行模式下已失真;要看 performance_schema.replication_applier_status_by_worker 里每个 worker 的 LAST_SEEN_TRANSACTION 和 APPLYING_TRANSACTION,才能知道谁真在干活、谁在等锁、谁压根没分到活。


















