
redo_log_buffer太小导致频繁刷盘
MySQL写入时先写内存中的 redo_log_buffer,满或事务提交时才刷到磁盘。默认仅16MB,高并发小事务下容易每秒刷多次,成为瓶颈。
- 查当前值:
SHOW VARIABLES LIKE 'innodb_log_buffer_size'; - 调大建议:从16MB起步,视单次写入量调整;若常有大BLOB/TEXT插入,可设为64MB~128MB
- 注意:该值只影响未提交事务的缓冲,不改变日志文件大小,也不会放大崩溃丢失风险
- 别盲目设过大——超过128MB后收益递减,且会占用更多InnoDB内存池
innodb_flush_log_at_trx_commit=1 的真实代价
这是“双1配置”里最重的一环:innodb_flush_log_at_trx_commit=1 表示每次事务提交都强制 fsync() 刷Redo Log到磁盘。它保安全,但代价是IOPS直线上升。
- SSD上典型延迟约0.3~1ms,HDD可能达5~15ms;每秒1000次提交 = 每秒1000次磁盘强制刷写
- 若业务允许短暂断电丢最多1秒数据(如日志、监控类),可改用
innodb_flush_log_at_trx_commit=2:日志写OS缓存即返回,由后台线程每秒刷一次 -
=0风险极高,仅限压测或临时导入场景;崩溃可能丢失1秒内所有事务 - 应用层批量提交比调参数更有效:把100个单行INSERT合并成1个批量语句,刷盘次数从100降到1
log_file_size 和 checkpoint 频率强相关
innodb_log_file_size 不只是“日志文件多大”,它直接决定checkpoint触发频率。设太小会导致频繁刷脏页,间接加剧Redo Log压力。
- 观察指标:
SHOW ENGINE INNODB STATUS里看Log sequence number和Last checkpoint at差值;差值长期接近innodb_log_file_size × 2就说明快撑不住了 - 经验值:总Redo容量(
innodb_log_file_size × innodb_log_files_in_group)建议 ≥ 1小时正常写入量的Redo日志量 - 调大需停机:修改
innodb_log_file_size后必须关闭MySQL、删除旧log文件、再重启,否则报错InnoDB: Error: log file ./ib_logfile0 is of different size - 常见误配:设了64MB但保留默认2个文件(共128MB),却没意识到checkpoint窗口其实只有64MB可用空间(因InnoDB循环覆盖)
sync_binlog 和 redo_log 的协同陷阱
当开启binlog(如主从复制),sync_binlog=1 和 innodb_flush_log_at_trx_commit=1 组合会触发“两阶段提交+两次fsync”,实际刷盘次数翻倍,但很多人以为只是“多一个日志同步”。
- 现象:TPS上不去、iowait高、
show processlist里大量线程卡在query end状态 - 折中方案:设
sync_binlog=1000+innodb_flush_log_at_trx_commit=1,牺牲最多1000个事务的binlog持久性,换Redo刷盘压力下降99% - 真正安全的组合只有两个:
(1,1)(全同步,最慢)或(2,1)(Redo落盘但binlog暂存OS缓存,崩溃后靠crash recovery对齐) - 别信“
innodb_flush_method=O_DIRECT能加速fsync”——它绕过OS缓存,对Redo Log反而有害,因Redo必须经过page cache才能被fsync()正确落盘
Redo Log刷新不是孤立参数,它和binlog策略、buffer分配、IO栈特性咬合极紧。最容易被忽略的是:应用提交节奏本身,往往比调参更能左右实际刷盘频率。











