writeset模式下仍串行执行,是因为事务修改同一行时写集必然重合,从库强制串行回放;这不是配置失效,而是数据变更逻辑天然存在依赖,调大slave_parallel_workers无效。

并行复制本身不消除逻辑锁冲突,它只决定从库 SQL 线程能否并发回放——而冲突是否发生,取决于事务修改的行是否重叠。想靠调大 slave_parallel_workers 解决“多个事务更新同一行导致卡住”,方向就错了。
为什么 WRITESET 模式下仍会串行执行
WRITESET 判断可并行的依据是事务修改的主键/唯一键哈希值是否相交。只要两个事务改的是同一张表的同一行(比如都 UPDATE user SET balance = balance + 1 WHERE id = 1001),它们的写集必然重合,从库就会强制串行回放。
- 这不是配置没生效,而是数据变更逻辑天然存在依赖
-
binlog_transaction_dependency_tracking=WRITESET开启后,主库会在 binlog 中记录每条事务影响的主键集合;从库据此判断冲突,不是凭空猜测 - 即使表有主键、
slave_parallel_type='LOGICAL_CLOCK'、slave_parallel_workers>0全部满足,只要写集交集非空,就退化为单线程 - DDL 语句(如
ALTER TABLE)永远阻塞后续所有事务,无论 WRITESET 是否启用
如何确认冲突真实存在而非配置失效
别只盯着 Seconds_Behind_Master 是否下降。真正要看的是底层执行状态:
- 查
performance_schema.replication_applier_status_by_coordinator,重点看WORKERS_PROCESSED是否持续增长——恒为 0 或缓慢爬升,说明根本没并行起来 - 查
performance_schema.replication_applier_status_by_worker,观察各WORKER_ID的LAST_APPLIED_TRANSACTION是否分散在不同 GTID 上;若全部集中在同一个 GTID,说明全在排队 - 运行
SHOW PROCESSLIST,应看到多个Worker thread状态为Waiting for an event from Coordinator或Executing event;如果只有 Coordinator 在动,就是逻辑冲突卡死 - 配合
SHOW ENGINE INNODB STATUS\G查LATEST DETECTED DEADLOCK区块,确认 trx_query 是否含UPDATE/DELETE且涉及相同主键值
绕过逻辑锁冲突的实操路径
既然冲突来自“多事务争同一行”,解法只能是避免争——不是加速争。
- 用
INSERT ... ON DUPLICATE KEY UPDATE替代先SELECT FOR UPDATE再UPDATE:跳过加锁读,靠唯一键冲突触发原子更新,适用于计数类场景 - 把单行热点拆成 N 个逻辑桶,例如原表
counter改为counter_shard_0到counter_shard_7,应用层按user_id % 8路由,汇总时SUM() - 高频写走 Redis 原子操作(
INCRBY),再由异步消费者批量落库,MySQL 写频次从每秒上千压到每秒几笔 - 检查事务内是否有冗余操作:比如在更新前执行了无意义的
SELECT *或跨库 JOIN,这些都会延长锁持有时间
最易被忽略的一点:从库上任何用户连接的写操作(哪怕只是监控脚本里的 UPDATE)都可能和 SQL Thread 形成真实死锁。务必设 read_only = ON 和 super_read_only = ON,否则所有并行优化都是空中楼阁。











