频繁提交直接触发LGWR强制刷重做日志,引发log file sync高等待、latch争用及I/O放大;判断依据是AWR中log file sync占比高且user commits远超业务所需;优化需批量提交(如每1000–10000行)、避免隐式提交,并厘清事务原子性边界。
频繁提交(commit)直接触发 lgwr 强制刷重做日志,每次都会带来可观的 i/o、锁和 latch 开销——这不是“慢一点”,而是把线性增长的操作变成了指数级放大。
每次 COMMIT 都在干啥?
表面只是确认事务,实际背后要同步完成:LGWR 把 redo buffer 中的日志写入磁盘;更新 undo segment 的事务状态;释放行锁和 ITL(Interested Transaction List)槽;刷新 SCN;通知其他会话该事务已结束。这些动作无法绕过,且不能批量合并。
- 哪怕只插入 1 行就
COMMIT,上述全套流程照走不误 - 高并发下,多个会话争抢
redo allocation latch和redo writing latch,出现latch: redo writing等待 - 小事务高频提交时,
log file sync等待时间会显著拉升平均响应
怎么判断是不是 COMMIT 拖慢了过程?
查 v$session_event 或 AWR 报告里 top 5 等待事件:log file sync 占比高(比如 >20%),且 commit 调用次数远大于业务逻辑所需(例如每循环一次就 COMMIT),基本可锁定。
- 用
SELECT sql_id, executions, elapsed_time/1000000 as sec FROM v$sql WHERE sql_text LIKE '%COMMIT%' ORDER BY elapsed_time DESC看 COMMIT 是否成了耗时大户 - 对比执行前后
v$sysstat中user commits和redo writes的增量比例——若前者远高于后者,说明大量 COMMIT 没带来有效吞吐
批量 COMMIT 怎么设才合理?
不是越大越好,得看 db_buffer_cache 大小、事务一致性要求、以及回滚段空间承受力。10000 是常见起点,但需验证:
- 先试
MOD(i, 1000) = 0提交,观察 AWR 中log file sync平均等待时间是否下降 50% 以上 - 确保
undo_retention足够支撑最长事务运行时间,否则中途ORA-01555 - 避免跨业务单元硬切分,比如“每 10000 条客户”没问题,但“每 10000 条订单+其关联明细”必须保证原子性,否则得用 SAVEPOINT
还有哪些隐形 COMMIT 坑?
容易被忽略的是隐式提交:DDL(如 CREATE INDEX)、某些自治事务(AUTONOMOUS_TRANSACTION)、甚至部分 DBMS_JOB 提交行为。它们会悄悄打断主事务流,导致后续 SQL 无法回滚。
- 检查存储过程中是否混用 DDL —— 尤其是动态建表或分析统计信息的语句
- 自治事务里调用
COMMIT后,主事务继续执行时,已无法回滚该自治事务所做修改 -
DBMS_SCHEDULER作业默认开启AUTOCOMMIT,若在里面跑 DML,务必显式控制


















