Oracle 事务与并发控制详解
Oracle 事务与并发控制详解
适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
事务与并发控制是数据库核心[1]:
详细见:Oracle 事务与锁机制。
2. ACID
- Atomicity(原子性)
- Consistency(一致性)
- Isolation(隔离性)
- Durability(持久性)
3. 事务
3.1 开始
- 隐式:第一条 DML
- 显式:SET TRANSACTION
3.2 结束
- COMMIT
- ROLLBACK
- DDL(自动提交)
- 异常退出(回滚)
3.3 控制
-- 提交
COMMIT;
COMMIT WORK;
COMMIT COMMENT 'msg';
-- 回滚
ROLLBACK;
ROLLBACK TO savepoint;
-- 保存点
SAVEPOINT sp1;
...
ROLLBACK TO sp1;
4. 隔离级别
4.1 支持
- READ COMMITTED(默认)
- SERIALIZABLE
- READ ONLY
4.2 设置
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION READ ONLY;
ALTER SESSION SET ISOLATION_LEVEL = SERIALIZABLE;
4.3 现象
| 级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ COMMITTED | 无 | 有 | 有 |
| SERIALIZABLE | 无 | 无 | 无 |
| READ ONLY | 无 | 无 | 无 |
5. 锁
5.1 类型
- DML 锁:TM(表)、TX(行)
- DDL 锁:独占、共享、断
- Latch:内部
- Mutex:内部
5.2 DML 锁
-- 行锁(TX)
UPDATE employees SET salary = 5000 WHERE id = 100;
-- 表锁(TM)
5.3 锁模式
| 模式 | 说明 |
|---|---|
| RS | Row Share |
| RX | Row Exclusive |
| S | Share |
| SRX | Share Row Exclusive |
| X | Exclusive |
5.4 加锁
-- 显式
LOCK TABLE employees IN ROW EXCLUSIVE MODE;
LOCK TABLE employees IN EXCLUSIVE MODE;
-- FOR UPDATE
SELECT * FROM employees WHERE id = 100 FOR UPDATE;
SELECT * FROM employees WHERE id = 100 FOR UPDATE NOWAIT;
SELECT * FROM employees WHERE id = 100 FOR UPDATE WAIT 10;
SELECT * FROM employees FOR UPDATE SKIP LOCKED;
5.5 查看
SELECT sid, type, lmode, request, id1, id2
FROM v$lock
WHERE sid = ...;
SELECT sid, serial#, username, blocking_session
FROM v$session
WHERE blocking_session IS NOT NULL;
详细见:Oracle 锁与闩锁诊断。
6. 一致性读
6.1 MVCC
- 多版本
- UNDO 段
- SCN
6.2 查询
- 一致性点
- 当前 + UNDO
- 无阻塞读
6.3 ORA-01555
- Snapshot too old
- UNDO 不足
- 增大 UNDO
7. 死锁
7.1 触发
- 循环等待
- Oracle 自动检测
- ORA-00060
7.2 避免
- 一致顺序
- 短事务
- 索引(避免全表锁)
- 索引外键
7.3 诊断
-- trace 文件
SELECT * FROM v$diag_info WHERE name = 'Default Trace File';
-- 查看死锁
SHOW PARAMETER deadlock;
8. 自治事务
8.1 定义
CREATE OR REPLACE PROCEDURE log_msg(p_msg VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO log VALUES (p_msg, SYSTIMESTAMP);
COMMIT;
END;
/
8.2 用途
- 日志
- 审计
- 独立提交
- 不影响主事务
详细见:Oracle 存储过程与函数详解。
9. 分布式事务
9.1 两阶段提交
1. PREPARE
2. COMMIT
9.2 处理
-- 强制提交/回滚
COMMIT FORCE 'trans_id';
ROLLBACK FORCE 'trans_id';
-- 查看悬挂
SELECT * FROM dba_2pc_pending;
9.3 XA
- Java JTA
- 跨资源
- 协调
10. 提交
10.1 选项
-- 快速
COMMIT FAST; -- 默认(不写redo)
-- 批处理
COMMIT BATCH; -- 批量
-- 等待
COMMIT WAIT; -- 等待LGWR
-- 立即
COMMIT IMMEDIATE; -- 立即
10.2 COMMIT_WRITE
ALTER SESSION SET COMMIT_WRITE = 'BATCH,NOWAIT';
11. 并发问题
11.1 丢失更新
- 行锁
- FOR UPDATE
- 乐观锁
11.2 不可重复读
- SERIALIZABLE
- 行锁
11.3 幻读
- SERIALIZABLE
- 范围锁
11.4 脏读
- READ COMMITTED 已避免
- 不可脏读
12. 乐观锁
12.1 版本号
CREATE TABLE t (id NUMBER, data VARCHAR2(100), version NUMBER);
UPDATE t SET data = 'new', version = version + 1
WHERE id = 1 AND version = :old_version;
12.2 时间戳
CREATE TABLE t (id NUMBER, data VARCHAR2(100), updated_at TIMESTAMP);
UPDATE t SET data = 'new', updated_at = SYSTIMESTAMP
WHERE id = 1 AND updated_at = :old_ts;
12.3 校验和
- 数据哈希
- 校验
13. 悲观锁
-- 查询并锁定
SELECT * FROM employees WHERE id = 100 FOR UPDATE;
-- 处理
UPDATE employees SET salary = 5000 WHERE id = 100;
COMMIT;
14. 应用场景
14.1 OLTP
- 短事务
- 行锁
- 乐观/悲观
- 一致顺序
14.2 批处理
- 大事务
- 批量提交
- 性能
14.3 报表
- READ ONLY
- 一致性
- 长查询
15. 监控
15.1 锁等待
SELECT sid, serial#, username, blocking_session, event, wait_class
FROM v$session
WHERE blocking_session IS NOT NULL;
SELECT sid, type, lmode, request, block
FROM v$lock
WHERE block > 0 OR request > 0;
15.2 等待事件
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event LIKE '%enq%'
ORDER BY time_waited DESC;
详细见:Oracle 等待事件详解。
16. 常见坑与排错
16.1 ORA-00060
- 死锁
- trace
- 顺序
16.2 ORA-01555
- UNDO 不足
- 增大
- 优化长查询
16.3 ORA-02049
- 分布式超时
- 调整
16.4 阻塞
- 长事务
- 锁等待
- 终止会话
17. 最佳实践
- 短事务:性能
- 绑定变量:减少解析
- 一致顺序:避免死锁
- 索引外键:避免全表锁
- 行锁:并发
- 乐观锁:低冲突
- 悲观锁:高冲突
- 隔离级别:需求
- 监控:锁等待
- 测试:并发
18. 参考资料
[1] Oracle Database Concepts 19c, “Transactions” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/transactions.html