单靠group commit不解决问题,因其依赖事务提交的时间重叠才能打包;若事务间隔远大于延迟阈值(如>10ms)或单线程压测,队列始终只有1个事务,无法形成组,innodb_os_log_fsyncs仍≈tps。

直接改 innodb_flush_log_at_trx_commit=2,再配好 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count,是见效最快、风险可控的 IOPS 优化路径。
为什么单靠 Group Commit 本身不解决问题?
Group Commit 是机制,不是开关——它依赖事务到达的“时间重叠”才能打包。如果应用是单线程压测、或事务提交间隔远大于 10ms,log 队列里永远只有 1 个事务,leader 没人可带,照样每笔都刷盘。
- 现象:监控
Innodb_os_log_fsyncs每秒值 ≈ TPS,没下降 - 根本原因:不是 Group Commit 失效,而是没凑够“组”;得先让事务提交节奏更密集(比如批量 insert + commit,而非逐条 commit)
- 别指望纯调参绕过物理规律:磁盘 fsync 有最小延迟(通常 1–5ms),1000 TPS 意味着每毫秒就要处理 1 笔,必须靠合并来摊薄
如何确认 Group Commit 正在起作用?
不能只看参数开了没开,得盯三个实时指标:
-
Innodb_os_log_fsyncs:从“每事务一次”变成“每秒几次”,波动范围建议在 1–10 次/秒(取决于并发密度) -
Innodb_log_waits:应长期为 0;若持续增长,说明 log buffer 不够大(innodb_log_file_size还是默认 48MB),导致频繁 checkpoint,IO 压力转嫁到 data file -
SHOW ENGINE INNODB STATUS的 LOG 段中:Log sequence number和Log flushed up to差值稳定在几 MB 内,不持续拉大
开启 binlog 时,redo 和 binlog 的组提交怎么协同?
MySQL 5.6+ 后,redo 和 binlog 都支持组提交,但必须用二阶段提交(2PC)串起来,否则主从可能不一致。关键点在配置解耦:
- 设
innodb_flush_log_at_trx_commit=2(每秒刷 redo),同时设sync_binlog=100(每 100 个事务刷 binlog),避免双 “1” 叠加两次 fsync - 启用
binlog_group_commit_sync_delay=10000(单位微秒,即最多等 10ms)和binlog_group_commit_sync_no_delay_count=10(凑够 10 个就发),二者满足其一即触发刷盘 - 注意:
sync_binlog优先级高于 delay/no_delay_count,所以设成 100 时,delay 参数实际不会生效——要真正用上 delay,sync_binlog必须设为 0 或大于预期组大小
最容易被忽略的配置陷阱
改完 innodb_flush_log_at_trx_commit 后,老连接仍按旧值执行;且 innodb_log_file_size 若未同步调大,瓶颈会从 redo 刷盘悄悄转移到脏页刷新。
- 必须滚动重启或等连接池自然更新,否则
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit'看的是新值,但业务 SQL 还在走旧路径 -
innodb_log_file_size建议调至 512MB 或 1GB(需停库重建),否则 checkpoint 频繁触发,Innodb_buffer_pool_pages_dirty持续高位,IO 压力从 log file 转移到 ibdata1 - 别设
innodb_flush_log_at_trx_commit=0:OS 崩溃时整个 log buffer(默认 16MB)全丢,丢失量不可控,比设为 2 风险高得多











