一、如何评估并行复制能力是否需要调整?

1.1 核心思路

MySQL 并行复制(MTS,Multi-Threaded Slave)的并行粒度由 last_committed 决定:

  • last_committed 相同的事务,可以并行回放
  • sequence_number 是事务的全局递增序号

1.2 解析 binlog 查看并行度

1
2
# 解析 binlog,查看 last_committed 和 sequence_number
mysqlbinlog --no-defaults -v /var/lib/mysql/binlog.000052 | grep -E "last_committed|sequence_number" | head -40

输出示例:

#250101 10:00:01 server id 1  end_log_pos 256  GTID  last_committed=10  sequence_number=11
#250101 10:00:01 server id 1  end_log_pos 512  GTID  last_committed=10  sequence_number=12
#250101 10:00:01 server id 1  end_log_pos 768  GTID  last_committed=10  sequence_number=13
#250101 10:00:01 server id 1  end_log_pos 1024 GTID  last_committed=10  sequence_number=14

上面 4 个事务 last_committed 都是 10,说明这 4 个事务可以并行回放。

1.3 判断标准

统计每个 last_committed 值下的事务数量:

1
2
3
4
mysqlbinlog --no-defaults -v /var/lib/mysql/binlog.000052 \
  | grep "last_committed" \
  | awk '{print $NF}' \
  | sort | uniq -c | sort -rn | head -20

判断逻辑:

情况说明建议
大量 last_committed 相同且组内事务数 > slave_parallel_workers并行度高,但 worker 不够用调大 slave_parallel_workers
大多数 last_committed 不同(每组只有 1 个事务)主库事务并发度低,并行复制无法发挥调整主库 group commit 参数
last_committed 相同数量 ≤ slave_parallel_workers当前 worker 数量够用无需调整

1.4 推荐配置

1
2
3
4
5
6
7
-- 查看当前值
SHOW VARIABLES LIKE 'slave_parallel_workers';
SHOW VARIABLES LIKE 'slave_parallel_type';

-- 推荐设置
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';  -- 必须,否则并行无效
SET GLOBAL slave_parallel_workers = 8;              -- 根据 CPU 核数和并行度评估结果调整

注意: slave_parallel_type 必须设置为 LOGICAL_CLOCK,默认的 DATABASE 模式只能同库串行,无法利用 last_committed 并行。


二、binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 对 Group Commit 的影响

2.1 Group Commit 机制回顾

MySQL InnoDB 的事务提交分为三个阶段(三阶段提交):

Flush 阶段  →  Sync 阶段  →  Commit 阶段

Group Commit 的核心价值:

  • 多个事务在 Sync 阶段合并为一次 fsync() 调用
  • 同一批次(同一个 group)提交的事务,拥有相同的 last_committed
  • last_committed 相同 → 从库可以并行回放

组越大(一次 fsync 包含的事务越多)→ last_committed 相同的事务越多 → 从库并行度越高。


2.2 binlog_group_commit_sync_delay

定义

1
2
SHOW VARIABLES LIKE 'binlog_group_commit_sync_delay';
-- 单位:微秒(μs),默认值:0

作用机制

在 Sync 阶段,MySQL 故意等待指定的微秒数,让更多事务加入当前 group,再统一 fsync。

事务A提交 ──┐
事务B提交 ──┤  等待 sync_delay 微秒  →  一次 fsync  →  同一个 last_committed
事务C提交 ──┘

效果对比

参数值效果
0(默认)不等待,来一个提交一个,group 小,从库并行度低
1000(1ms)等待 1ms,聚集更多事务,group 大,从库并行度高
过大(如 100ms)主库写入延迟明显增加,影响业务响应时间

副作用

  • 增大主库事务的提交延迟(RT 变高)
  • 适合写入并发高、对延迟不敏感的场景(如批量导入、日志类业务)
  • 不适合OLTP 低延迟场景

2.3 binlog_group_commit_sync_no_delay_count

定义

1
2
SHOW VARIABLES LIKE 'binlog_group_commit_sync_no_delay_count';
-- 单位:个,默认值:0(不限制)

作用机制

binlog_group_commit_sync_delay 配合使用,设定一个事务数量上限

当 group 内等待的事务数量达到此值时,立即 fsync,不再等待剩余的 delay 时间

设置:sync_delay=5000μs,no_delay_count=10

情况1:等了 3000μs,已有 10 个事务 → 立即 fsync(不等满 5000μs)
情况2:等了 5000μs,只有 3 个事务  → 时间到,立即 fsync

两个参数的组合逻辑

满足任意一个条件即触发 fsync:
  条件1:等待时间 ≥ binlog_group_commit_sync_delay
  条件2:group 内事务数 ≥ binlog_group_commit_sync_no_delay_count

no_delay_count 本质是一个安全阀,防止高并发时事务堆积太多、延迟过高。

推荐配置组合

1
2
3
-- 场景:高并发写入,希望提升从库并行度,同时控制延迟
SET GLOBAL binlog_group_commit_sync_delay = 1000;        -- 最多等 1ms
SET GLOBAL binlog_group_commit_sync_no_delay_count = 20; -- 凑够 20 个事务就提交

2.4 两个参数对从库并行度的完整影响链路

主库调大 sync_delay / no_delay_count
        ↓
每次 fsync 包含的事务更多(group 更大)
        ↓
同一批事务拥有相同的 last_committed
        ↓
从库 SQL thread 识别到 last_committed 相同
        ↓
多个 worker 线程并行回放
        ↓
从库复制延迟降低

三、总结对比

参数作用调大的代价适用场景
slave_parallel_workers从库并行 worker 数量CPU 消耗增加从库复制延迟高时
binlog_group_commit_sync_delay主库 fsync 等待时间主库写入延迟增加主库并发写入高时
binlog_group_commit_sync_no_delay_countgroup 事务数上限无明显代价配合 sync_delay 使用

调优优先级建议:

  1. 先确认 slave_parallel_type = LOGICAL_CLOCK
  2. 解析 binlog 评估实际并行度
  3. 如果 group 内事务数少,调整主库 sync_delay
  4. 根据 worker 利用率决定是否调大 slave_parallel_workers