delete批量日志暴增根本原因是长事务下三重日志(binlog/redo/undo)叠加放大:每行删一行即记整行旧值、页变更及快照,行数×行宽×索引数呈指数级增长,且三者互不共享、不压缩、不同步清理。

DELETE 批量操作导致日志暴增,根本不是“删得多”,而是数据库把整批操作塞进一个长事务里——每删一行,就记一份完整镜像(旧值),日志体积直接和行数 × 行宽 × 索引数量挂钩,三者叠加呈指数级放大。
MySQL 的 binlog + redo + undo 三重日志全开
ROW 格式下 binlog_row_image=FULL 是默认值:哪怕只改一个字段,DELETE 也得记整行旧值;redo log 要记录页分裂/合并的物理变更;undo log 则必须存每行删除前的完整快照,主键或变长字段更新还会触发 DELETE+INSERT 模式,undo 体积翻倍。10 万行、平均 200 字节的表,光 binlog 就可能超 400MB,undo 再加 300MB+,redo 因页操作再涨 100MB——三者互不共享、不压缩、不同步清理。
SQL Server 的 tempdb 版本存储 + ldf 锁死
当 READ_COMMITTED_SNAPSHOT=ON 或 ALLOW_SNAPSHOT_ISOLATION=ON 时,每次 DELETE 都在 tempdb 中保留旧版本行;只要事务没提交,或有长查询依赖该快照,这些版本就无法清理。单事务删 50 万行 → tempdb 瞬间暴涨数 GB;同时事务日志(.ldf)因 log_reuse_wait_desc = 'ACTIVE_TRANSACTION' 无法截断,持续撑满。
PostgreSQL 的 WAL + pg_xact 占用不释放
DELETE 生成大量 WAL 记录,且每行都写入 pg_xact 和 pg_commit_ts(尤其开启 track_commit_timestamp=on 时)。大事务未结束,这些系统表里的事务状态就一直被钉住,WAL 归档速率飙升,pg_wal 目录迅速膨胀。VACUUM 还不能立刻执行——它得等事务结束后才能回收空间,中间空档期就是日志暴增窗口。
所有数据库共通的索引放大效应
每多一个二级索引,单行 DELETE 的日志量就接近翻倍:不仅要删主键行,还要逐个更新索引项,每个索引变更都单独记日志。一张表有 5 个二级索引,删 100 万行 ≈ 600 万次日志写入。这不是配置问题,是设计使然——MVCC、崩溃恢复、可重复读隔离级别,全靠这些日志活着。最容易被忽略的是:你删的不是数据,是“可逆性”本身;而数据库必须为这份可逆性,一字不落地记账。










