innodb_flush_log_at_trx_commit=1 是组提交的硬前提,设为0或2会禁用组提交;需配合足够大的innodb_log_file_size(256M~1G)、sync_binlog=1、O_DIRECT刷盘及充足IO线程才能发挥最大效能。

innodb_flush_log_at_trx_commit=1 是组提交的硬前提
MySQL 5.7 的组提交(group commit)机制依赖于 innodb_flush_log_at_trx_commit 设置为 1。设成 0 或 2 会绕过 redo 日志刷盘的同步控制,直接禁用组提交能力——哪怕并发再高,事务日志也按单条或批次异步落盘,无法形成真正的组提交队列。
常见错误是:为了“提升性能”盲目改成 2,结果发现 TPS 没涨多少,反而丢失了组提交带来的批量刷盘收益,还牺牲了崩溃安全性。
-
1:每次事务提交都调用fsync(),但 InnoDB 内部会把同一时刻等待刷盘的多个事务日志合并成一次物理写入(即组提交) -
2:只写入 OS cache,不fsync,完全脱离组提交调度逻辑 -
0:连 OS cache 都不保证,由后台线程异步刷,彻底无序
必须配合 innodb_log_file_size 足够大
组提交效果受 innodb_log_file_size 制约。如果日志文件太小(比如默认的 48MB),redo log 循环写很快填满,触发 checkpoint 频繁刷脏页,导致 I/O 压力分散、组提交窗口被压缩甚至失效。
实测中,当每小时 redo 写入量超 2GB,而 innodb_log_file_size 仍为 128MB 时,Innodb_os_log_written 增速剧烈波动,log_waits 显著上升——说明组提交排队被日志空间不足打断。
- 推荐值:取
innodb_log_file_size = 256M ~ 1G,具体看业务写入强度;可用SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written';每 30 秒采样一次,估算每秒平均写入量 × 60 × 10(留出 10 秒缓冲) - 调整该参数需停机:先停 MySQL,删除旧
ib_logfile*,再启动(确保innodb_fast_shutdown=0) - 切勿设得比
innodb_buffer_pool_size还大,通常不超过其 25%
sync_binlog 和 binlog_group_commit 启用与否影响最终吞吐
如果开了 binlog(主从/恢复必需),sync_binlog 和 binlog_group_commit 会与 InnoDB 组提交协同工作。MySQL 5.7 默认启用 binlog_group_commit,但若 sync_binlog=1,则 binlog 也会参与两阶段提交的组刷盘流程。
此时真正生效的是「二进制日志 + redo 日志」联合组提交:多个事务在 prepare 阶段攒批,在 commit 阶段统一刷 binlog + redo。若 sync_binlog=0 或 =1000,这个协同就断了,TPS 提升上限被拉低。
- 高负载 OLTP 场景建议:
sync_binlog=1+innodb_flush_log_at_trx_commit=1,二者配对才能释放组提交最大效能 - 注意:这要求磁盘 I/O 能力足够,否则
fsync成瓶颈;SSD/NVMe 是刚需,HDD 上容易卡住 - 可通过
SHOW ENGINE INNODB STATUS\G查看Log sequence number和Last checkpoint at差值是否稳定,突增说明刷盘滞后
别忽略并发线程和 IO 线程的配套设置
组提交只是日志刷盘环节的优化,上游事务提交速度还受限于并发处理能力。若 innodb_thread_concurrency 设为 0(默认不限制),但实际 CPU 核数少、IO 线程不足,事务会在进入组提交队列前就排队阻塞。
例如在 24 核服务器上跑 5.7,默认 innodb_read_io_threads=4、innodb_write_io_threads=4,面对高写入压力时 IO 线程打满,redo 日志生成跟不上,组提交“等不到人来组”。
- 建议按核数匹配:24 核可设
innodb_read_io_threads=8、innodb_write_io_threads=8,并观察innodb_data_pending_reads/writes是否持续非零 -
innodb_thread_concurrency不建议硬限(设为 0),除非出现明显线程争抢;5.7 对高并发调度已较成熟 - 确认
innodb_flush_method=O_DIRECT,避免 double buffering 导致内核缓存干扰组提交的 I/O 时序
innodb_flush_log_at_trx_commit=1 的严格语义、足够大的日志文件空间、binlog 协同策略,以及底层 IO 处理能力的支撑。最容易被跳过的其实是磁盘 I/O 能力验证——哪怕参数全对,一块饱和的 SATA SSD 也会让组提交变成“假排队”。


















