应拆分大事务而非调大binlog_cache_size:因超限会强制刷盘生成临时文件(如mysql-bin.000001-#sql-xxx),占用磁盘且不被PURGE清理;调参仅延迟问题,拆事务才能避免锁竞争、主从延迟与OOM风险。

因为 MySQL 必须在事务提交前完整记录所有变更,而大事务超出 binlog_cache_size 时,会落盘生成临时 binlog cache 文件(如 mysql-bin.000001-#sql-xxx),不是“暂存”,而是强制刷盘的中间产物。
binlog_cache_size 不够导致落盘写临时文件
MySQL 为每个事务分配内存缓存来暂存 binlog 内容,大小由 binlog_cache_size 控制(默认 32KB)。当单个事务产生的 binlog 数据超过该值,MySQL 会把溢出部分写入磁盘临时文件,路径通常在 datadir 下,文件名类似 mysql-bin.000001-#sql-xxxxx —— 这类文件不是日志轮转产生,而是事务执行中实时落盘的中间缓存。
-
binlog_cache_size只作用于事务内,非全局累积;max_binlog_cache_size是单事务上限,超限直接报错ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes - ROW 格式下一条大
INSERT ... SELECT或批量INSERT很容易突破缓存,尤其涉及宽表或多列更新时 - 临时文件不会自动清理,事务提交或回滚后才被删除;若 mysqld 异常退出,这些残留文件可能卡住后续 binlog 切换
为什么不能靠调大 binlog_cache_size 解决问题
单纯增大 binlog_cache_size 只是延迟落盘,不改变根本瓶颈:大事务本身带来锁竞争、主从延迟、OOM 风险和恢复时间拉长。实际生产中,它常掩盖更严重的设计缺陷。
- 设为 2MB 可能撑住 10 万行插入,但事务持有 MDL 锁和行锁时间同步延长,阻塞其他 DDL/DML
- 内存缓存放大后,若并发高,多个大事务同时申请,极易触发
max_binlog_cache_size限制或物理内存耗尽 - binlog 临时文件写入本身也是磁盘 IO,反而加剧磁盘压力,尤其在 SSD 寿命敏感或 IOPS 有限环境
真正有效的应对方式:拆事务 + 控制单次写入量
比调参更可靠的是从源头控制事务粒度。只要保证单事务生成的 binlog 数据稳定低于 binlog_cache_size,就能完全避免临时文件产生。
- 用
INSERT ... VALUES (...), (...), ...批量插入时,每 1000–5000 行提交一次(具体视平均行大小调整) - 对
INSERT INTO t SELECT ... FROM big_table类操作,改用分页 + LIMIT/OFFSET 或按主键范围拆解,例如WHERE id BETWEEN ? AND ? - 应用层加幂等标识(如业务单号+状态机),确保拆分后某批次失败可安全重试,不依赖单一大事务原子性
- 确认
autocommit=1开启,避免意外隐式开启长事务
临时文件本身不可见、不计入 SHOW BINARY LOGS,但会真实占用磁盘空间并干扰 df 统计——最容易被忽略的是:它们不随 PURGE BINARY LOGS 清理,只能靠正常事务结束或重启 mysqld 触发回收。线上若发现磁盘空间“莫名缓慢增长”且 SHOW MASTER STATUS 显示当前 binlog 文件大小远小于磁盘占用,大概率就是这类临时文件堆积所致。


















