Oracle 事务与锁机制
Oracle 事务与锁机制
适用版本:Oracle Database 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
事务(Transaction) 是数据库操作的最小逻辑单元[1],锁(Lock) 保证并发数据一致性。
2. 事务 ACID
| 属性 | 说明 | Oracle 实现 |
|---|---|---|
| 原子性 | 全做或全不做 | undo 段回滚 |
| 一致性 | 一致状态转换 | 约束+触发器 |
| 隔离性 | 并发互不干扰 | 锁+多版本 |
| 持久性 | 提交不丢失 | redo 日志 |
3. 事务控制
3.1 基本语句
-- 开始(隐式)
INSERT INTO ...;
-- 提交
COMMIT;
-- 回滚
ROLLBACK;
-- 保存点
SAVEPOINT sp1;
...
ROLLBACK TO sp1;
-- 只读事务
SET TRANSACTION READ ONLY;
-- 读写事务
SET TRANSACTION READ WRITE;
-- 隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3.2 自治事务
CREATE OR REPLACE PROCEDURE log_action(
p_msg VARCHAR2
) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO log_table VALUES (p_msg, SYSDATE);
COMMIT; -- 仅提交此事务
END;
/
4. 隔离级别
4.1 READ COMMITTED(默认)
-- 读取已提交数据
-- 可能不可重复读、幻读
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
4.2 SERIALIZABLE
-- 完全隔离
-- 可能 ORA-08177 错误
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
4.3 READ ONLY
-- 只读
SET TRANSACTION READ ONLY;
5. 锁类型
5.1 DML 锁
| 锁 | 说明 | 模式 |
|---|---|---|
| TX | 事务锁 | 排他 |
| TM | 表锁 | RS/RX/S/SRX/X |
5.2 表锁模式
| 模式 | 说明 | 兼容 |
|---|---|---|
| RS(Row Share) | 行共享 | 大部分 |
| RX(Row Exclusive) | 行排他 | RS/RX |
| S(Share) | 共享 | RS/S |
| SRX(Share Row Exclusive) | 共享行排他 | RS |
| X(Exclusive) | 排他 | 无 |
5.3 行锁
-- SELECT FOR UPDATE 加行锁
SELECT * FROM employees
WHERE employee_id = 100
FOR UPDATE;
-- 等待
SELECT * FROM employees WHERE employee_id = 100 FOR UPDATE WAIT 10;
-- 不等待
SELECT * FROM employees WHERE employee_id = 100 FOR UPDATE NOWAIT;
-- 跳过锁定行
SELECT * FROM employees WHERE dept_id = 10 FOR UPDATE SKIP LOCKED;
5.4 手动加表锁
LOCK TABLE employees IN ROW EXCLUSIVE MODE;
LOCK TABLE employees IN SHARE MODE;
LOCK TABLE employees IN EXCLUSIVE MODE;
6. 锁视图
6.1 查看锁
SELECT
s.sid,
s.serial#,
s.username,
l.type,
l.lmode,
l.request,
l.id1,
l.id2
FROM v$lock l, v$session s
WHERE l.sid = s.sid;
6.2 锁等待
SELECT
blocking_session,
session_id,
lock_type,
mode_held,
mode_requested,
blocking_username
FROM dba_waiters;
6.3 阻塞链
SELECT
LEVEL,
s.sid,
s.username,
s.program,
s.event
FROM v$session s
START WITH s.blocking_session IS NULL
CONNECT BY PRIOR s.sid = s.blocking_session;
7. 死锁
7.1 死锁示例
会话 1:UPDATE emp SET sal=100 WHERE id=1;
会话 2:UPDATE emp SET sal=200 WHERE id=2;
会话 1:UPDATE emp SET sal=300 WHERE id=2; -- 等待会话 2
会话 2:UPDATE emp SET sal=400 WHERE id=1; -- 等待会话 1
-- 死锁!
7.2 Oracle 自动检测
- 自动检测死锁
- 回滚一个事务
- 抛 ORA-00060
7.3 死锁日志
# 查找死锁 trace
$ORACLE_BASE/diag/rdbms/$DB_UNIQUE_NAME/$ORACLE_SID/trace/*ora*.trc
7.4 预防死锁
- 固定加锁顺序
- 缩短事务
- 使用 NOWAIT
- 批量操作
8. 闩锁(Latch)与 Mutex
8.1 Latch
- 轻量级锁
- 保护内存结构
- 短时间持有
8.2 Mutex
- 替代部分 Latch
- 更高效
- pin 共享
8.3 查看
SELECT name, gets, misses, spin_gets FROM v$latch WHERE misses > 0;
SELECT * FROM v$mutex_sleep_history;
9. 并发问题
9.1 脏读
- Oracle 不存在(READ COMMITTED 避免)
9.2 不可重复读
-- READ COMMITTED 下可能
SELECT salary FROM emp WHERE id = 100; -- 5000
-- 其他会话 UPDATE 并 COMMIT
SELECT salary FROM emp WHERE id = 100; -- 6000
9.3 幻读
-- READ COMMITTED 下可能
SELECT COUNT(*) FROM emp WHERE dept_id = 10; -- 5
-- 其他会话 INSERT 并 COMMIT
SELECT COUNT(*) FROM emp WHERE dept_id = 10; -- 6
9.4 隔离级别对比
| 隔离级别 | 脏读 | 不可重复 | 幻读 |
|---|---|---|---|
| READ COMMITTED | 无 | 有 | 有 |
| SERIALIZABLE | 无 | 无 | 无 |
| READ ONLY | 无 | 无 | 无 |
10. 常见坑与排错
10.1 ORA-00060: 死锁
修复:
-- 1. 查看 trace
-- 2. 调整加锁顺序
-- 3. 缩短事务
10.2 ORA-00054: 资源忙
-- NOWAIT 立即失败
SELECT * FROM emp WHERE id=100 FOR UPDATE NOWAIT;
-- 修复:等待或查找阻塞会话
SELECT blocking_session, sid FROM v$session WHERE blocking_session IS NOT NULL;
10.3 阻塞链
-- 查找阻塞源
SELECT
s.sid,
s.serial#,
s.username,
s.program,
s.event,
s.seconds_in_wait
FROM v$session s
WHERE s.sid IN (SELECT blocking_session FROM v$session WHERE blocking_session IS NOT NULL);
-- 杀掉阻塞会话
ALTER SYSTEM KILL SESSION 'sid,serial#';
10.4 锁等待长
-- 1. 缩短事务
-- 2. 优化 SQL
-- 3. 加索引
-- 4. 调整业务逻辑
11. 最佳实践
- 事务尽量短:减少锁持有
- 按固定顺序加锁:避免死锁
- 使用 FOR UPDATE 显式锁定:明确意图
- NOWAIT/SKIP LOCKED:避免阻塞
- 合理隔离级别:READ COMMITTED 够用
- 批量提交:平衡性能
- 监控锁等待:及时发现
- 加索引:减少锁范围
- 避免长事务:影响并发
- 自治事务记日志:避免主事务回滚
12. 参考资料
[1] Oracle Database Concepts 19c, “Data Concurrency and Consistency” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/data-concurrency-and-consistency.html