是的,但仅保证redo log刷至磁盘日志文件,不保证绕过os/磁盘缓存;需配合sync_binlog=1等才能实现强一致。

innodb_flush_log_at_trx_commit=1 真的保证“每次提交都落盘”吗?
是的,但只限于 log buffer 刷到 OS cache 并调用 fsync() 写入磁盘日志文件(ib_logfile0 等)——不是刷数据页,也不是刷 binlog。它不保证操作系统或磁盘固件没缓存,也不绕过存储栈的写缓存(比如 RAID 卡、NVMe 的 write cache)。如果磁盘掉电且未禁用写缓存,仍可能丢最后几条事务。
- 必须配合
sync_binlog=1+binlog_format=ROW才能支撑主从强一致或崩溃恢复后 binlog 与 InnoDB 一致 - 若使用云盘(如 AWS gp3、阿里云 ESSD),需确认其提供“持久化写入语义”,部分共享型存储会延迟透传
fsync() - 某些 SSD 在断电保护失效时(电容老化),
fsync()返回成功但实际未落盘
为什么设成 2 或 0 后写性能明显提升?
因为跳过了每事务一次的 fsync() 系统调用:设为 2 是刷到 OS cache(异步、快),设为 0 连 OS cache 都不刷(只留内存 log buffer,最危险)。瓶颈不在 MySQL,而在磁盘 I/O 调度和物理写入延迟 —— 尤其高并发小事务场景下,fsync() 成为串行点。
-
innodb_flush_log_at_trx_commit=1下,TPS 常被压在 100–500(普通 SATA SSD),而=2可达 3000+,差距来自系统调用开销和磁盘队列竞争 -
=0虽快,但 MySQL 崩溃会导致最近 1 秒所有事务丢失(log buffer 每秒刷一次),不适合任何生产 OLTP - 注意:即使
=2,MySQL 崩溃不会丢事务,但主机断电仍可能丢 OS cache 中未刷盘的日志
什么时候可以安全地调低这个值?
仅当业务可接受“主机断电丢失最多 1 秒事务”的场景,且已放弃单机强耐久性目标。典型如日志类、埋点、实时推荐特征缓存等最终一致性系统。
- 不能用于支付、账务、库存扣减等需要 ACID 强保障的模块
- 若用 MGR 或基于 GTID 的异步复制,
=2会导致主库崩溃后从库多出未提交事务(因 binlog 已写但 redo 未落盘),引发数据不一致 - 监控上要盯住
Innodb_os_log_pending_fsyncs:该值持续 > 0 表示fsync()被阻塞,可能是磁盘过载,此时降级=2只是掩盖问题,不是解法
如何验证当前配置是否真正在起作用?
别只看 SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit',得测行为。最直接方式是模拟事务提交后立刻 kill -9 mysqld,再重启看数据是否回滚。
- 用
strace -e trace=fsync,write -p $(pidof mysqld)观察是否每个COMMIT都触发fsync()(=1时应高频出现;=2时几乎不出现) - 检查
/proc/sys/vm/dirty_ratio和/proc/sys/vm/dirty_expire_centisecs:Linux 回写策略会影响=2下日志在 OS cache 中停留时间 - 云环境务必查文档:AWS RDS 默认强制
=1且不可改;阿里云 PolarDB 允许改但底层用共享存储,fsync()行为与本地盘不同










