Oracle 的 TX、TM、UL 锁对比

Oracle 的 TX、TM、UL 锁对比

Oracle 数据库中的这三种锁机制在并发控制中扮演着不同角色,以下是它们的对比分析:

一、基本特性对比

特性 TX (事务锁) TM (DML锁) UL (用户锁)
锁类型 行级锁 表级锁 应用级自定义锁
作用范围 保护数据行变更 保护表结构不被修改 保护用户定义的资源
自动性 事务自动获取/释放 DML语句自动获取/释放 需显式调用DBMS_LOCK获取
可见性 其他会话可见 其他会话可见 仅申请会话可见(默认)
冲突检测 通过等待或死锁检测 立即冲突报错(ORA-00054) 可配置等待或立即失败

二、技术实现对比

1. 数据结构差异

  • TX锁

    sql 复制代码
    -- 在v$lock中的表示
    TYPE='TX', ID1=USN.SLOT, ID2=WRAP#
    -- USN=undo段号,SLOT=槽位号,WRAP=序列号
  • TM锁

    sql 复制代码
    TYPE='TM', ID1=OBJECT_ID, ID2=0
    -- 直接关联数据字典对象ID
  • UL锁

    sql 复制代码
    TYPE='UL', ID1=<lock_id>, ID2=0
    -- lock_id由DBMS_LOCK.ALLOCATE_UNIQUE生成

2. 锁模式对比

模式 TX锁表现 TM锁表现 UL锁表现
共享(SS) SELECT...FOR UPDATE LOCK TABLE IN SHARE MODE DBMS_LOCK.REQUEST(mode=>'S')
排他(X) UPDATE/DELETE操作 LOCK TABLE IN EXCLUSIVE MODE DBMS_LOCK.REQUEST(mode=>'X')
空(N) 事务结束释放 语句结束释放 DBMS_LOCK.RELEASE调用

三、使用场景对比

1. TX锁典型场景

sql 复制代码
-- 案例1:行级更新冲突
UPDATE employees SET salary=salary*1.1 WHERE emp_id=100;
-- 此时会在emp_id=100的记录上获得TX锁

-- 案例2:死锁场景
-- 会话1: UPDATE tableA SET... WHERE id=1;
-- 会话2: UPDATE tableB SET... WHERE id=2;
-- 会话1: UPDATE tableB SET... WHERE id=2; -- 等待
-- 会话2: UPDATE tableA SET... WHERE id=1; -- 死锁检测

2. TM锁典型场景

sql 复制代码
-- 案例1:防止DDL与DML冲突
-- 会话1: SELECT * FROM orders FOR UPDATE;
-- 会话2: ALTER TABLE orders ADD column new_col NUMBER; -- 等待TM锁

-- 案例2:LOCK TABLE显式锁定
LOCK TABLE inventory IN EXCLUSIVE MODE;

3. UL锁典型场景

sql 复制代码
-- 案例1:应用级资源协调
DECLARE
  l_lockhandle VARCHAR2(128);
  l_status NUMBER;
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE('APP_CONFIG_LOCK', l_lockhandle);
  l_status := DBMS_LOCK.REQUEST(l_lockhandle, DBMS_LOCK.X_MODE);
  IF l_status = 0 THEN
    -- 执行需要互斥的操作
    DBMS_LOCK.RELEASE(l_lockhandle);
  END IF;
END;

四、诊断与问题处理

1. 锁等待分析

sql 复制代码
-- 查看所有锁等待
SELECT 
  l1.sid holding_sid,
  l2.sid waiting_sid,
  l1.type lock_type,
  CASE l1.type
    WHEN 'TX' THEN '行锁/事务锁'
    WHEN 'TM' THEN '表锁'
    WHEN 'UL' THEN '用户锁'
  END lock_desc,
  s1.username holder,
  s2.username waiter
FROM v$lock l1, v$lock l2, v$session s1, v$session s2
WHERE l1.block = 1 
AND l2.request > 0
AND l1.id1 = l2.id1
AND l1.id2 = l2.id2
AND l1.sid = s1.sid
AND l2.sid = s2.sid;

2. 特殊问题处理

  • TX锁堆积

    sql 复制代码
    -- 查找长事务
    SELECT s.sid, s.serial#, s.username, s.status,
           t.start_time, t.used_ublk
    FROM v$transaction t, v$session s
    WHERE t.ses_addr = s.saddr
    ORDER BY t.used_ublk DESC;
  • TM锁冲突

    sql 复制代码
    -- 查找被锁定的对象
    SELECT object_name, object_type 
    FROM dba_objects 
    WHERE object_id = (SELECT id1 FROM v$lock WHERE type='TM' AND sid=&sid);
  • UL锁泄漏

    sql 复制代码
    -- 检查未释放的用户锁
    SELECT * FROM dba_lock_internal 
    WHERE lock_type = 'UL' 
    AND owner <> 'SYS';

五、性能优化建议

  1. TX锁优化

    • 减少事务持续时间
    • 使用SELECT...FOR UPDATE NOWAIT避免等待
    • 适当增加_TRANSACTION_TABLE_SIZE参数
  2. TM锁优化

    • 避免业务高峰期执行DDL
    • 对大表DDL使用ONLINE选项
    • 考虑使用LOCK TABLE IN SHARE MODE替代排他模式
  3. UL锁最佳实践

    • 为锁命名使用前缀(如APPNAME_RESOURCE)
    • 设置超时参数:DBMS_LOCK.REQUEST(..., timeout=>10)
    • 在异常处理中确保锁释放

六、版本差异说明

版本 TX锁增强 TM锁变化 UL锁改进
11g 增加TX绑定特性 引入ONLINE DDL 增加锁超时精确控制
12c 支持IN_MEMORY事务 支持DDL等待超时 增加锁状态持久化选项
19c 自适应死锁检测算法 减少索引维护的TM锁 支持PL/SQL锁监控视图
21c 自动锁转换优化 分区表DDL锁粒度细化 增加全局UL锁命名空间

理解这三种锁的差异,可以帮助DBA更好地诊断并发问题并优化数据库性能。

相关推荐
虎头金猫10 小时前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
这个DBA有点耶11 小时前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
DBA_G11 小时前
从地面到云霄:GBase数据库在民航三大场景的落地实践
数据库
自由能燃气设备11 小时前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
科创致远12 小时前
科创致远 ESOP 系统核心效能与实战价值展示
大数据·数据库·人工智能·精益工程
AI职业加油站12 小时前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
此冬歌咏13 小时前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
2601_9622186113 小时前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法
-梅13 小时前
linux(8) 软硬链接
linux·运维·服务器
张洛闻Eren14 小时前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github