MySQL单线程复制时SQL线程无法并行执行,因其5.6之前及默认配置下强制串行回放relay log,必须满足slave_parallel_type=LOGICAL_CLOCK且slave_parallel_workers>0才启用多线程,并依赖主库ROW格式与WRITESET依赖追踪保障并行安全。

MySQL单线程复制时SQL线程无法并行执行
因为MySQL 5.6之前(及默认配置下),从库的SQL线程是**单一线程串行回放relay log**,所有事务必须按binlog顺序依次执行,哪怕服务器有32核CPU,也只用到1个逻辑核。这不是“没启用多核”,而是架构上不允许并发应用——事务间存在依赖关系(如同一行的UPDATE+DELETE),乱序执行会破坏数据一致性。
slave_parallel_workers=0 是默认值且不生效
即使你手动设置了slave_parallel_workers=8,若未同时启用并行复制模式,该参数完全无效。MySQL要求两个前提同时满足才会启动工作线程:
-
slave_parallel_type必须设为LOGICAL_CLOCK(推荐)或DATABASE -
slave_parallel_workers必须 > 0 - (可选但关键)
slave_preserve_commit_order=1保证事务提交顺序不被破坏
漏掉任一条件,SHOW PROCESSLIST里永远只看到一个SQL thread,SHOW SLAVE STATUS中Slave_SQL_Running_State也始终显示Reading event from the relay log而非Worker thread...。
LOGICAL_CLOCK 并行不是无条件的
启用LOGICAL_CLOCK后,并行度仍受限于主库的事务分组能力。主库需在binlog中打上last_committed和sequence_number标记,这依赖于:
- 主库
binlog_format=ROW(STATEMENT格式下无法准确判断事务独立性) - 主库
binlog_transaction_dependency_tracking=WRITESET(比默认的COMMIT_ORDER更激进,能提升并行粒度) - 事务本身不跨库、不跨表锁、不显式加锁(如
SELECT ... FOR UPDATE会强制串行)
如果主库大量执行单表批量更新(如UPDATE orders SET status=2 WHERE created_at ),这些事务会被归入同一<code>last_committed组,从库仍只能用1个worker串行处理。
监控并行是否真起效的关键指标
别只看slave_parallel_workers数值,要验证实际效果:
- 查
SHOW PROCESSLIST:应看到多个Worker thread状态,而不仅是SQL thread - 看
SHOW SLAVE STATUS\G中的Seconds_Behind_Master是否明显下降,且波动变小 - 检查
performance_schema.replication_applier_status_by_worker表:各worker的LAST_SEEN_TRANSACTION应持续推进,且APPLYING_EVENT状态不长期卡住
最容易被忽略的是:即使并行开启,若从库innodb_buffer_pool_size过小,worker线程会频繁等待页加载,CPU利用率虚高但实际吞吐没提升——这时瓶颈已从“串行”转移到“I/O争抢”。



















