Oracle AskTOM Commit 提交机制详解
Oracle AskTOM Commit 提交机制详解
来源:AskTOM (asktom.oracle.com) 适用版本:Oracle Database 全版本 文档版本:v1.0 / 2026-07-22
1. 概述
Commit 机制是 Tom Kyte 反复强调的话题[1]。
详细见:Oracle Redo Log 机制详解、Oracle 事务 ACID 深度解析。
2. Commit 做了什么
2.1 LGWR 写 Redo
- Redo Buffer → Redo Log
- 保证持久性
- 同步
2.2 释放锁
- 行锁释放
- 资源释放
- 其他会话可继续
2.3 清理 Undo
- Undo 段标记
- 提交 SCN
- 后续读一致性
2.4 通知
- 提交完成
- 后台清理
3. COMMIT 选项
3.1 默认
- WAIT:等待 LGWR
- 同步
- 持久
3.2 NOWAIT
COMMIT WRITE WAIT; -- 默认
COMMIT WRITE NOWAIT; -- 不等待 LGWR
3.3 BATCH
COMMIT WRITE BATCH; -- 批量写
COMMIT WRITE IMMEDIATE; -- 立即写
3.4 选项对比
| 选项 | 性能 | 持久性 | 风险 |
|---|---|---|---|
| WAIT | 慢 | 强 | 低 |
| NOWAIT | 快 | 弱 | 实例故障丢 |
| BATCH | 快 | 弱 | 批量丢 |
| IMMEDIATE | 慢 | 强 | 低 |
4. 频繁 COMMIT 问题
4.1 Tom Kyte 观点
- 不要在循环里 COMMIT
- 每次提交:
- LGWR 同步写
- 性能差
- 应该事务级
4.2 反例
CREATE OR REPLACE PROCEDURE bad_commit IS
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO emp VALUES (i, 'Name'||i);
COMMIT; -- 错误!
END LOOP;
END;
/
4.3 正例
CREATE OR REPLACE PROCEDURE good_commit IS
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO emp VALUES (i, 'Name'||i);
END LOOP;
COMMIT; -- 事务级
END;
/
4.4 性能对比
- bad_commit: 10 分钟
- good_commit: 1 分钟
- 差距 10 倍
5. LOG_BUFFER
5.1 作用
- Redo 缓存
- LGWR 异步写
- 减少磁盘 I/O
5.2 大小
ALTER SYSTEM SET log_buffer=64M SCOPE=SPFILE;
5.3 触发 LGWR
- 1/3 满
- 1MB
- COMMIT
- 3 秒
6. SCN
6.1 提交 SCN
- COMMIT 时分配
- 系统变更号
- 一致性基础
6.2 查询
SELECT current_scn FROM v$database;
6.3 依赖
- 事务依赖
- 一致性读
- MVCC
7. FAST=TRUE 神话
7.1 Tom Kyte 名言
"COMMIT = FAST=TRUE 是神话"
7.2 真相
- COMMIT 有代价
- LGWR 同步写
- 不能消除
8. 长事务
8.1 问题
- Undo 增长
- ORA-01555
- 性能下降
8.2 监控
SELECT sid, serial#, used_ublk
FROM v$transaction t, v$session s
WHERE t.addr = s.taddr
ORDER BY used_ublk DESC;
8.3 优化
- 分批 commit
- 10k-100k 行
- 平衡
9. 分布式事务
9.1 两阶段
- Prepare
- Commit
- 协调者
9.2 2PC
- 一致性
- 性能差
- 慎用
9.3 XA
- 跨资源
- 协议
- 风险
10. COMMIT 性能优化
10.1 Redo Log
- 大小足够
- 多组
- 高速磁盘
10.2 LOG_BUFFER
- 适当大小
- 64M+
10.3 NOWAIT/BATCH
- 评估风险
- 性能
- 一致性
10.4 应用
- 事务级 COMMIT
- 批量
- 不要循环 COMMIT
11. 监控
11.1 Redo 速率
SELECT value FROM v$sysstat WHERE name='redo writes';
SELECT value FROM v$sysstat WHERE name='redo sync time';
11.2 Commit 等待
SELECT event, time_waited
FROM v$system_event
WHERE event IN ('log file sync', 'log file parallel write');
11.3 LGWR
SELECT * FROM v$bgprocess WHERE name='LGWR';
12. 常见问题
12.1 log file sync
- COMMIT 等待
- LGWR 慢
- Redo Log 优化
12.2 ORA-01555
- 长事务
- Undo 不足
- 分批 commit
12.3 数据丢失
- NOWAIT/BATCH
- 实例故障
- 评估风险
13. 最佳实践
- 事务级:COMMIT
- 不要循环:COMMIT
- Redo Log:足够大
- LOG_BUFFER:适当
- 高速磁盘:Redo
- 监控:log file sync
- NOWAIT:慎用
- 长事务:分批
- 测试:性能
- 原理:理解
14. 参考资料
[1] AskTOM, “Commit Frequency”, https://asktom.oracle.com [2] Tom Kyte, “Expert Oracle Database Architecture”, Chapter 9