在 Oracle 数据库的七条事务控制语句里,COMMIT 与 ROLLBACK 是最核心、也最容易被“日用而不知”的两条。它们一个负责把事务的变更永久化,一个负责把变更原路撤回,看似黑白对立,却在内部实现、性能影响、锁行为、分布式场景、与业务应用的耦合方式上,有着大量共生细节。理解这两条语句,就是理解 Oracle 事务模型的钥匙。下文从语义、内部机制、锁与一致性、性能、分布式、常见误区六个角度,对 COMMIT 与 ROLLBACK 做一份系统梳理。
一、语义与语法
1. COMMIT
结束当前事务,把事务所产生的所有数据变更、索引变更、序列递增、触发器副作用等持久化到磁盘,并释放事务所持有的所有锁(行锁、表锁、分区锁、TM、TX、SSX 等)。语法:
COMMIT [WORK] [COMMENT 'text'] [FORCE 'xid'] [WRITE [WAIT | NOWAIT] [IMMEDIATE | BATCH]];
WORK 为可省略关键字;COMMENT 供分布式事务查错;FORCE 用于手工提交 in-doubt 分布式事务;WRITE 子句控制 Redo 刷盘方式,11g 起支持。
2. ROLLBACK
终止当前事务,撤销所有未提交的变更,并释放锁。语法:
ROLLBACK [WORK] [TO [SAVEPOINT] sp_name] [FORCE 'xid'];
若指定保存点,则只回滚到该点;FORCE 同样用于分布式。
3. 隐式提交/回滚
DDL、DCL(GRANT、REVOKE)、部分 DBMS 包调用会触发隐式提交;会话异常断开时 PMON 会隐式回滚。
二、内部实现原理
1. Redo 与 Undo 的双轨制
Oracle 把“前映像”写在 Undo 表空间,把“后映像”写在 Redo 日志。COMMIT 时,LGWR 只需把 Redo 日志刷盘,DBWR 异步写数据块;ROLLBACK 时,服务器进程从 Undo 段读取前映像,把数据块、索引块、LOB 段、嵌套表、物化视图日志等全部回退,并清理 Undo 头。
2. 快速提交(Fast Commit)
只要 Redo 日志落盘,事务即算提交成功,数据块可以稍后写;因此 Commit 极快,通常在 1~3 ms 内返回。
3. 延迟块清除(Delayed Block Cleanout)
高并发场景下,Oracle 为了降低 Commit 开销,允许把块头上的事务标志(ITL)延迟清除;下一次查询时若发现 SCN 已提交,则自动补清,这也是“ORA-01555 快照过旧”最常见的诱因之一。
4. 回滚段循环使用
Undo 表空间以 Extent 为单位循环覆盖,若长事务或长查询未及时提交,可能导致“Snapshot too old”或“Undo 空间不足”。
5. 序列与临时表
Commit 后序列值永久递增,不会回退;临时表(ON COMMIT PRESERVE ROWS)在事务级提交后仍保留数据,会话级提交后清空。
三、锁与并发控制
1. TX 锁
事务开始时,Oracle 为每个事务分配一个 TX 锁(行级排他),挂在回滚段头;Commit 立即释放,Rollback 同样释放。
2. TM 锁
对表执行 DML 时,会加表级共享 TM 锁(模式 3),防止在事务进行时有 DDL 修改表结构;Commit/Rollback 后释放。
3. 分布式锁
分布式事务中,Oracle 使用 DBLINK 上的 IN-DOUBT 会话表记录分支状态,Commit 需经历 Prepare-Commit 两阶段,Rollback 只需本地回滚。
4. 串行化隔离
在 SERIALIZABLE 隔离级别下,Commit 前任何“不可重复读”都会报错;Rollback 可以安全撤销,不产生不一致。
四、性能与可观测性
1. Log File Sync 等待
Commit 时 LGWR 刷盘,若 Redo 文件 I/O 慢,会出现“log file sync”等待;可通过批量提交、Redo 条带、SSD、增大 LOG_BUFFER 等手段缓解。
2. 批量 DML 与 Commit
循环里逐条 Commit 会产生大量 Redo、Undo、递归调用,性能下降 1~2 个数量级;应改为批量处理,一次 Commit。
3. 观测视图
v$transaction.used_ublk / used_urec 可看 Undo 使用量;v$session.event='log file sync' 可看 Commit 等待;v$sysstat 中的 “user commits” 与 “user rollbacks” 可统计系统级事务量。
4. AWR 报告
AWR 中的 “% of Blocks Changed per Read” 与 “Rollback per transaction %” 可衡量业务回滚比例,过高说明业务异常或代码异常处理不当。
五、分布式与 XA 场景
1. 两阶段提交(2PC)
当事务跨越多个 DBLINK 或 XA 资源时,Oracle 作为 RM(Resource Manager)会经历 Prepare→Commit 两阶段。Prepare 阶段把分布式锁、SCN、XID 写入 dba_2pc_pending;Commit 阶段再真正落地。
2. In-Doubt 事务
若 Prepare 后数据库崩溃,重启后事务处于 “prepared” 状态,需 DBA 手动 COMMIT FORCE 'xid' 或 ROLLBACK FORCE 'xid'。
3. 与 WebLogic、Tuxedo 集成
中间件通过 XA 接口调用,Oracle 内部仍是 2PC;若中间件超时重试,可能出现 ORA-02051、ORA-02054,需要检查 dba_2pc_pending。
4. 限制
分布式事务不支持保存点;一旦进入 Prepare,就不能再 Rollback to Savepoint。
六、常见误区与最佳实践
1. “Commit 越频繁越安全”
频繁 Commit 并不能减少锁等待,反而放大 Redo 同步开销;正确做法是按业务边界批量提交,异常时整体回滚。
2. “Rollback 会释放序列”
序列一旦 NEXTVAL,即永久递增,Rollback 无法回退;若业务要求连续,应改用表序列或自定义锁表。
3. “DDL 可以回滚”
除少数 CREATE TABLE AS SELECT 外,绝大多数 DDL 会隐式提交,Rollback 无效;应在 DDL 前手动提交或备份数据。
4. “临时表数据总是会话结束才清”
ON COMMIT PRESERVE ROWS 的临时表在事务提交后仍保留,会话断开才清;ON COMMIT DELETE ROWS 的临时表在 Commit 后立即清空。
5. 异常模板
PL/SQL 统一异常块:
BEGIN
… business …
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
log_error();
RAISE;
END;
避免漏回滚导致脏数据。
6. 监控阈值
对核心库设置“长事务”告警:v$transaction.start_time > 30 min 或 used_ublk > 1 GB 即短信通知;Rollback 段争用高时,可在线扩容 Undo 表空间或启用自动扩展。
7. 日志与审计
打开 AUDIT SESSION 可记录每次 Commit/Rollback 时间戳,结合 AWR 可分析业务高峰事务量;对金融系统,可额外写应用日志,实现业务凭证与数据库事务的一一对应。
七、结语
COMMIT 与 ROLLBACK 是 Oracle 事务的两极:一个把变更写进永恒,一个把错误拉回原点。它们背后共享着 Redo 与 Undo 的双轨制、共享着锁与 SCN 的并发框架,也共同决定了系统的吞吐量、可恢复性与一致性。掌握 Commit 的快速提交、延迟块清除、分布式两阶段,明白 Rollback 的逆向恢复、空间循环、锁释放,就能在开发中写出既高效又安全的事务边界;在运维中,也能通过 AWR、等待事件、Undo 监控,及时发现“log file sync”过慢、长事务膨胀、In-Doubt 悬而未决等问题。唯有把“提交”与“回滚”这对看似简单的动词,放到并发、性能、可用性、分布式的大图景里去理解,才能真正让 Oracle 的事务引擎成为业务可靠的基石。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




