达梦数据库v$lock事务锁视图详解
达梦数据库 V$LOCK 视图详解
一、视图概述
V$LOCK 是达梦数据库(DM8)中用于监控和管理数据库锁的核心动态性能视图。它实时显示了当前数据库中所有会话持有或等待的锁信息,是诊断并发问题、性能调优和故障排除的关键工具。
二、视图完整结构
| 字段名 | 数据类型 | 说明 | 重要性 |
|---|---|---|---|
| ADDR | VARCHAR | 锁结构在内存中的地址 | 高 |
| SID | INTEGER | 会话标识符,对应V$SESSIONS.SESS_ID | 高 |
| TYPE | VARCHAR(2) | 锁类型标识符 | 最高 |
| ID1 | INTEGER | 锁标识符1(含义随TYPE变化) | 高 |
| ID2 | INTEGER | 锁标识符2(含义随TYPE变化) | 高 |
| LMODE | INTEGER | 当前持有的锁模式 | 最高 |
| REQUEST | INTEGER | 请求的锁模式(0表示无请求) | 最高 |
| BLOCK | INTEGER | 阻塞标志:0-无阻塞,1-阻塞他人,2-被阻塞 | 最高 |
| CTIME | INTEGER | 锁已持有或等待的时间(秒) | 中 |
| BLKED_TRX | INTEGER | 被阻塞的事务ID | 中 |
| TABLE_ID | INTEGER | 表对象ID(达梦DM8新增) | 中 |
| ROW_ID | BIGINT | 行标识符(达梦DM8新增) | 中 |
| PART_ID | INTEGER | 分区ID(如适用) | 低 |
| INDEX_ID | INTEGER | 索引ID(如适用) | 低 |
三、核心字段详解
1. TYPE(锁类型)
锁类型决定了锁的粒度和用途:
| 类型值 | 名称 | 说明 | 常见场景 |
|---|---|---|---|
| TAB | 表锁 | 对整个表的锁 | DDL操作、表级操作 |
| ROW | 行锁 | 对单行记录的锁 | DML操作(UPDATE/DELETE) |
| PAG | 页锁 | 对数据页的锁 | 早期版本使用,现较少 |
| IX | 意向排他锁 | 表级锁,表示事务打算在行上加X锁 | 行级X锁的先导锁 |
| IS | 意向共享锁 | 表级锁,表示事务打算在行上加S锁 | 行级S锁的先导锁 |
| S | 系统锁 | 系统内部使用的锁 | 字典缓存、内存结构等 |
| TS | 表空间锁 | 表空间级锁 | 表空间维护操作 |
| FS | 文件锁 | 文件级锁 | 文件操作 |
2. LMODE 和 REQUEST(锁模式)
锁模式用数字表示锁的强度:
| 值 | 名称 | 符号 | 说明 | 兼容性 |
|---|---|---|---|---|
| 0 | 无锁 | NULL | 无锁状态 | - |
| 1 | 共享锁 | S | 读锁,允许多个会话同时读取 | 与S兼容,与X冲突 |
| 2 | 更新锁 | U | 更新锁,准备更新时的中间状态 | 有限兼容 |
| 3 | 排他锁 | X | 写锁,独占访问 | 与所有锁都冲突 |
| 4 | 共享排他锁 | SX | 共享意向排他锁 | 特殊场景使用 |
| 5 | 意向共享锁 | IS | 表级意向锁 | 行级S锁的先导 |
| 6 | 意向排他锁 | IX | 表级意向锁 | 行级X锁的先导 |
关键规则:
-
LMODE > 0:会话已持有该锁 -
REQUEST > 0:会话正在等待该锁 -
当
LMODE=3 (X)且REQUEST=0:会话持有排他锁 -
当
LMODE=0且REQUEST=3:会话正在等待排他锁
3. BLOCK(阻塞标志)
这是诊断阻塞问题的关键字段:
| 值 | 状态 | 含义 | 处理建议 |
|---|---|---|---|
| 0 | 正常 | 既不阻塞别人,也不被阻塞 | 无需处理 |
| 1 | 阻塞者 | 当前锁阻塞了其他会话 | 需要关注,可能需提交/回滚 |
| 2 | 被阻塞者 | 当前会话被其他锁阻塞 | 需要等待或排查阻塞源 |
4. ID1 和 ID2(锁标识符)
根据TYPE不同,ID1和ID2的含义不同:
TYPE='TAB'(表锁)
-
ID1:表的对象ID(OBJECT_ID) -
ID2:通常为0 -
查找表名:
sql
SELECT OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_ID = <ID1>;
TYPE='ROW'(行锁)
-
ID1:段号 + 文件号(高位) -
ID2:页号 + 槽号(低位) -
定位具体行(需要内部转换):
sql
-- 使用DBMS_ROWID包或系统函数
SELECT
DBMS_ROWID.ROWID_TO_ABSOLUTE_FNO(ROWID) as file_no,
DBMS_ROWID.ROWID_TO_BLOCK_NUMBER(ROWID) as block_no,
DBMS_ROWID.ROWID_TO_ROW_NUMBER(ROWID) as row_no
FROM your_table WHERE rowid = <行标识>;
TYPE='IX'/'IS'(意向锁)
-
ID1:表的对象ID -
ID2:通常为0
四、锁的兼容性矩阵
| 请求模式持有模式 | NULL(0) | S(1) | U(2) | X(3) | SX(4) | IS(5) | IX(6) |
|---|---|---|---|---|---|---|---|
| NULL(0) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| S(1) | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✗ |
| U(2) | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ |
| X(3) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| SX(4) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| IS(5) | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ |
| IX(6) | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ |
✓=兼容 ✗=冲突
五、实战场景分析
场景1:快速定位阻塞链
sql
-- 查找完整的阻塞链(阻塞源头 → 被阻塞者)
WITH BlockChain AS (
SELECT
l1.SID AS blocker_sid,
l1.TYPE AS blocker_type,
l1.LMODE AS blocker_mode,
l2.SID AS blocked_sid,
l2.TYPE AS blocked_type,
l2.REQUEST AS blocked_request,
s1.USERNAME AS blocker_user,
s1.SQL_TEXT AS blocker_sql,
s2.USERNAME AS blocked_user,
s2.SQL_TEXT AS blocked_sql,
LEVEL AS chain_level
FROM V$LOCK l1
JOIN V$LOCK l2 ON l1.ID1 = l2.ID1
AND l1.ID2 = l2.ID2
AND l1.TYPE = l2.TYPE
LEFT JOIN V$SESSIONS s1 ON l1.SID = s1.SESS_ID
LEFT JOIN V$SESSIONS s2 ON l2.SID = s2.SESS_ID
WHERE l1.BLOCK = 1
AND l2.REQUEST > 0
START WITH l1.BLOCK = 1 AND NOT EXISTS (
SELECT 1 FROM V$LOCK l3
WHERE l3.ID1 = l1.ID1
AND l3.ID2 = l1.ID2
AND l3.TYPE = l1.TYPE
AND l3.REQUEST = l1.LMODE
)
CONNECT BY PRIOR l2.SID = l1.SID
)
SELECT * FROM BlockChain ORDER BY chain_level;
场景2:查看特定表的锁信息
sql
-- 查看某个表的所有锁
DECLARE
v_table_name VARCHAR(128) := 'EMPLOYEES'; -- 替换为实际表名
v_table_id NUMBER;
BEGIN
-- 获取表ID
SELECT OBJECT_ID INTO v_table_id
FROM DBA_OBJECTS
WHERE OBJECT_NAME = v_table_name AND OBJECT_TYPE = 'TABLE';
-- 查询该表的所有锁
SELECT
l.SID,
s.USERNAME,
l.TYPE,
CASE l.TYPE
WHEN 'TAB' THEN '表锁'
WHEN 'ROW' THEN '行锁'
WHEN 'IX' THEN '意向排他锁'
WHEN 'IS' THEN '意向共享锁'
ELSE l.TYPE
END AS lock_type_desc,
CASE l.LMODE
WHEN 1 THEN 'S(共享)'
WHEN 3 THEN 'X(排他)'
ELSE TO_CHAR(l.LMODE)
END AS lock_mode,
CASE l.REQUEST
WHEN 0 THEN '无'
WHEN 1 THEN '等待S'
WHEN 3 THEN '等待X'
ELSE TO_CHAR(l.REQUEST)
END AS wait_mode,
CASE l.BLOCK
WHEN 1 THEN '阻塞他人'
WHEN 2 THEN '被阻塞'
ELSE '正常'
END AS block_status,
l.CTIME AS hold_wait_seconds,
s.SQL_TEXT,
s.CLNT_IP
FROM V$LOCK l
LEFT JOIN V$SESSIONS s ON l.SID = s.SESS_ID
WHERE (l.TYPE = 'TAB' AND l.ID1 = v_table_id)
OR (l.TYPE IN ('IX', 'IS') AND l.ID1 = v_table_id)
OR (l.TYPE = 'ROW' AND EXISTS (
SELECT 1 FROM DBA_OBJECTS o
WHERE o.OBJECT_ID = l.TABLE_ID
AND o.OBJECT_NAME = v_table_name
))
ORDER BY l.BLOCK DESC, l.TYPE, l.LMODE DESC;
END;
场景3:锁等待超时分析
sql
-- 检查长时间等待的锁(超过30秒)
SELECT
l.SID,
s.USERNAME,
s.STATE,
l.TYPE,
l.LMODE,
l.REQUEST,
l.BLOCK,
l.CTIME AS wait_seconds,
ROUND(l.CTIME / 60, 2) AS wait_minutes,
s.SQL_TEXT,
s.TRX_ID,
t.START_TIME,
CASE
WHEN l.CTIME > 300 THEN '严重:超过5分钟'
WHEN l.CTIME > 60 THEN '警告:超过1分钟'
WHEN l.CTIME > 30 THEN '注意:超过30秒'
ELSE '正常'
END AS wait_level
FROM V$LOCK l
LEFT JOIN V$SESSIONS s ON l.SID = s.SESS_ID
LEFT JOIN V$TRX t ON s.TRX_ID = t.TRX_ID
WHERE l.REQUEST > 0 -- 正在等待锁
AND l.CTIME > 30 -- 等待超过30秒
ORDER BY l.CTIME DESC;
六、锁相关的重要系统视图
| 视图名 | 用途 | 与V$LOCK的关系 |
|---|---|---|
| V$SESSIONS | 会话信息 | 通过SID关联,查看会话详情 |
| V$TRX | 事务信息 | 通过TRX_ID查看事务状态 |
| V$LOCK_WAIT | 锁等待关系 | 专门显示锁等待的视图 |
| V$DEADLOCK_HISTORY | 死锁历史 | 记录已发生的死锁信息 |
| V$SQL_AREA | SQL缓存 | 查看锁相关的SQL语句 |
七、常见问题排查脚本
1. 实时监控锁变化
sql
-- 创建监控表(可选)
CREATE TABLE LOCK_MONITOR_HISTORY AS
SELECT SYSDATE AS SNAP_TIME, l.* FROM V$LOCK l WHERE 1=0;
-- 定期插入快照(在作业中执行)
INSERT INTO LOCK_MONITOR_HISTORY
SELECT SYSDATE, l.*
FROM V$LOCK l
WHERE l.BLOCK > 0 OR l.REQUEST > 0;
-- 分析锁变化趋势
SELECT
TO_CHAR(SNAP_TIME, 'HH24:MI:SS') AS snap_time,
COUNT(*) AS total_locks,
SUM(CASE WHEN BLOCK=1 THEN 1 ELSE 0 END) AS blockers,
SUM(CASE WHEN BLOCK=2 THEN 1 ELSE 0 END) AS blocked,
SUM(CASE WHEN REQUEST>0 THEN 1 ELSE 0 END) AS waiters
FROM LOCK_MONITOR_HISTORY
WHERE SNAP_TIME > SYSDATE - 1/24 -- 最近1小时
GROUP BY TO_CHAR(SNAP_TIME, 'HH24:MI:SS')
ORDER BY snap_time;
2. 生成锁报告
sql
SET LINESIZE 200
SET PAGESIZE 100
COLUMN "锁类型" FORMAT A15
COLUMN "锁模式" FORMAT A15
COLUMN "等待模式" FORMAT A15
COLUMN "阻塞状态" FORMAT A15
COLUMN "SQL语句" FORMAT A50 TRUNC
SELECT
l.SID AS "会话ID",
s.USERNAME AS "用户名",
s.SESS_SEQ AS "会话序列号",
CASE l.TYPE
WHEN 'TAB' THEN '表锁(' || (SELECT OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_ID=l.ID1) || ')'
WHEN 'ROW' THEN '行锁'
WHEN 'IX' THEN '意向排他锁'
WHEN 'IS' THEN '意向共享锁'
ELSE l.TYPE
END AS "锁类型",
DECODE(l.LMODE, 0, 'NULL', 1, 'S', 2, 'U', 3, 'X', 4, 'SX', '未知') AS "锁模式",
DECODE(l.REQUEST, 0, '无', 1, 'S', 2, 'U', 3, 'X', 4, 'SX', '未知') AS "等待模式",
DECODE(l.BLOCK, 0, '正常', 1, '阻塞者', 2, '被阻塞', '未知') AS "阻塞状态",
l.CTIME AS "持续时间(秒)",
SUBSTR(s.SQL_TEXT, 1, 100) AS "SQL语句",
s.CLNT_IP AS "客户端IP",
s.APPNAME AS "应用名称"
FROM V$LOCK l
LEFT JOIN V$SESSIONS s ON l.SID = s.SESS_ID
WHERE s.STATE = 'ACTIVE'
ORDER BY l.BLOCK DESC, l.CTIME DESC;
八、最佳实践建议
-
监控重点:
-
优先关注
BLOCK=1的会话(阻塞源头) -
关注
REQUEST>0且CTIME>30的长时间等待 -
重点关注
TYPE='ROW'的行锁争用
-
-
问题处理流程:
1. 查询V$LOCK发现阻塞 2. 通过SID关联V$SESSIONS查看会话详情 3. 通过SQL_TEXT分析业务逻辑 4. 决定处理方式:等待、提交、回滚或kill会话 5. 如需终止会话:ALTER SYSTEM KILL SESSION '<SID>,<SERIAL>';
-
预防措施:
-
优化SQL语句,减少锁持有时间
-
合理设计事务,避免大事务
-
使用适当的隔离级别
-
建立索引减少锁范围
-
-
注意事项:
-
生产环境谨慎使用KILL SESSION
-
定期分析锁等待趋势
-
关注热点表的锁争用情况
-
使用达梦的AWR报告分析锁历史
-
这个全面的指南应该能帮助您深入理解和使用达梦数据库的V$LOCK视图。实际使用时,请根据您的具体版本(DM7/DM8)调整相关语法和字段。
注意事项:
在达梦数据库(DM Database)中,V$LOCK 视图确实没有 TYPE 字段,而是使用 LTYPE 字段来表示锁类型。这是达梦与 Oracle 等数据库在视图命名上的一个差异。
字段设计原因
达梦采用 LTYPE(Lock Type)而非 TYPE,主要基于以下考量:
-
命名规范化
达梦对锁相关视图采用统一的 "L" 前缀(Lock)命名规则:-
LTYPE:Lock Type(锁类型) -
LMODE:Lock Mode(锁模式) 这种命名方式更清晰地表明字段所属的上下文范畴。
-
-
避免关键字冲突
TYPE是 SQL 标准中的 保留关键字,在部分场景下可能引发解析歧义。使用LTYPE可以有效规避此类潜在冲突。 -
与 Oracle 的差异化设计
虽然达梦在很多方面兼容 Oracle(Oracle 的V$LOCK使用TYPE字段),但达梦在内部数据字典实现上采用了独立的命名体系,以体现其自主设计的架构特性。
V$LOCK 视图结构
根据达梦官方文档,该视图的核心字段如下:
表格
复制
| 字段名 | 类型 | 说明 |
|---|---|---|
ADDR |
BIGINT | 锁的内存地址 |
TRX_ID |
BIGINT | 所属事务 ID |
| LTYPE | VARCHAR(10) | 锁类型:OBJECT(对象锁)或 TID(TID 锁,其实就是事务id指的是事务锁标识) |
LMODE |
CHAR(2) | 锁模式:S(共享)、X(排他)、IS(意向共享)、IX(意向排他) |
BLOCKED |
INTEGER | 是否处于等待状态:0(已上锁),1(等待中) |
TABLE_ID |
INTEGER | 对象锁对应的表 ID;TID 锁对应记录所在表 ID |
ROW_IDX |
BIGINT | TID 锁封锁记录的行信息 |
TID |
BIGINT | TID 锁对象的事务 ID,事务id,间接代表了事务锁id |
锁类型说明(LTYPE)
-
TID 锁
以事务号为封锁对象,替代了传统行锁的机制。每个活动事务生成一把 TID 锁,防止多个事务同时修改同一行记录。 -
OBJECT 锁
对象锁合并了数据字典锁和表锁,通过统一的对象 ID 进行封锁,减少封锁冲突,提升并发性能。
查询示例
sql
复制
-- 查看当前锁信息
SELECT
TRX_ID,
LTYPE, -- 使用 LTYPE 而非 TYPE
LMODE,
TABLE_ID,
BLOCKED
FROM V$LOCK;
-- 查看阻塞锁详情(关联对象名和会话)
SELECT
o.name AS table_name,
l.TRX_ID,
l.LTYPE,
l.LMODE,
s.SESS_ID,
s.SQL_TEXT
FROM V$LOCK l
JOIN DBA_OBJECTS o ON l.TABLE_ID = o.OBJECT_ID
JOIN V$SESSIONS s ON l.TRX_ID = s.TRX_ID
WHERE l.BLOCKED = 1;
总结
达梦数据库使用 LTYPE 而非 TYPE,主要是出于命名规范性和避免关键字冲突的考虑。在编写 SQL 或迁移 Oracle 脚本时,需注意将 TYPE 替换为 LTYPE,同时 ID1/ID2 的概念在达梦中也被 TABLE_ID 和 ROW_IDX 等更直观的字段替代
——————————————————————————————
篇外话题
trxid和tid的区别
在达梦数据库中,TRX_ID 和 TID 是两个密切相关但含义不同的概念,这涉及到达梦独特的 TID 锁机制(行锁替代方案)。
TID 锁 与 TID 区分
在达梦数据库的 V$LOCK 视图中,TRX_ID 和 TID 是两个截然不同的概念,它们的关系体现了达梦独特的 TID 锁机制(行锁替代方案)。
核心区别
表格
复制
| 字段 | 含义 | 指向对象 | 出现场景 |
|---|---|---|---|
| TRX_ID | 锁持有者 | 持有/创建该锁的事务ID | 所有锁类型(TID锁、OBJECT锁) |
| TID | 锁目标 | 被锁定的目标事务ID | 仅 LTYPE='TID' 时有效 |
机制详解
1. TRX_ID(事务标识)
-
定义:表示哪个事务持有或正在申请这把锁
-
作用:标识锁的所有者,用于关联
V$SESSIONS等视图追踪会话信息 -
示例:事务
7539471修改了表数据,它在V$LOCK中的记录TRX_ID = 7539471
2. TID(TID锁对象)
-
定义:仅对 TID锁(
LTYPE='TID')有效,表示被锁定的目标事务号 -
本质:达梦用 TID 锁替代传统行锁,通过锁定事务号来间接锁定行记录
-
物理存储:每行记录隐藏一个
TID字段,存放最后修改该行的事务号
3. 两者的关系(关键)
在达梦的 MVCC + TID锁 机制中:
-
数据行包含隐藏的
TID字段,记录最后修改它的事务号 -
事务 A(TRX_ID=100)修改某行后,该行的
TID被设为 100 -
事务 B(TRX_ID=101)想修改同一行时,发现行
TID=100 -
事务 B 会生成一把 TID锁:
-
TRX_ID= 101(事务B自己,表示谁在申请锁) -
TID= 100(事务A,表示锁定了哪个事务) -
BLOCKED= 1(如果事务A未提交,事务B进入等待)
-
实际查询示例
sql
复制
-- 查询阻塞情况,清晰展示 TRX_ID 和 TID 的关系
SELECT
DS.SESS_ID "被阻塞的会话ID",
DS.TRX_ID "被阻塞的事务ID(TRX_ID)", -- 持有锁的事务(申请者)
L.LTYPE "锁类型",
L.TID "占用锁的事务ID(TID)", -- 被锁定的目标事务(占用者)
SS.SESS_ID "占用锁的会话ID",
SS.TRX_ID "占用者TRX_ID"
FROM V$LOCK L
LEFT JOIN V$SESSIONS DS ON DS.TRX_ID = L.TRX_ID -- TRX_ID 关联申请锁的会话
LEFT JOIN V$SESSIONS SS ON SS.TRX_ID = L.TID -- TID 关联被锁定的目标事务的会话
WHERE L.BLOCKED = 1 AND L.LTYPE = 'TID';
查询结果解读:
-
TRX_ID(申请者):正在等待的事务(如事务 101) -
TID(被锁定目标):之前修改记录且未提交的事务(如事务 100) -
只有当
LTYPE='TID'时,TID字段才有意义;对于OBJECT锁,TID通常为 NULL 或 0
总结
-
TRX_ID:标识锁的持有者(Who holds the lock)(申请者的事务id)
-
TID:在 TID 锁机制下,标识被锁定的目标事务(Which transaction is being locked),实现达梦特有的行级并发控制(上次使用该锁的事务号)
这种设计是达梦区别于 Oracle(使用 ID1/ID2 表示行锁的 rowid 信息)的关键特征,通过锁定事务号而非物理行地址,简化了锁管理并提升了并发性能
——————————————————————————————————
各个字段的具体解释
这是达梦数据库 V$LOCK 动态性能视图的字段映射,以下是每个字段的详细含义:
核心锁标识字段
表格
复制
| 字段 | 类型 | 含义 |
|---|---|---|
addr |
Long |
锁的内存地址。 锁对象在内存中的物理地址标识,用于内部管理和调试。 |
trxId |
Long |
事务 ID。 持有(已获得)或正在申请(等待中)该锁的事务标识号。 是关键字段,用于关联 V$SESSIONS、V$TRX 等视图查询会话信息。 |
ltype |
String |
锁类型。 OBJECT:对象锁(合并了表锁和字典锁) TID:TID 锁(达梦特有的行级锁机制,通过锁定事务号实现行级并发控制)。 区别: OBJECT 锁锁的是表/对象,TID 锁锁的是事务号(间接锁定行记录)。(具体的事务锁) |
lmode |
String |
锁模式。 S:共享锁(Shared) X:排他锁/独占锁(Exclusive) IS:意向共享锁(Intent Shared) IX:意向排他锁(Intent Exclusive) |
锁状态与位置字段
表格
复制
| 字段 | 类型 | 含义 |
|---|---|---|
blocked |
Integer |
阻塞状态。 0:已成功获得锁(holding) 1:正在等待锁(waiting) 用于判断当前事务是锁持有者还是等待者。 |
hlckEp |
Integer |
锁所在服务器节点(集群环境)。 0:表示锁位于控制节点(主节点) 非0:表示锁位于对应的 EP(执行节点)节点号。 |
sptNo |
Integer |
表空间号。 记录锁对应的表空间编号(Tablespace No.),用于定位数据文件。 |
thrdId |
Integer |
线程 ID。 正在等待该锁的线程标识。 NULL/0:表示当前会话已拥有该锁 非0:表示当前会话正在等待该锁对应的线程。 |
hashValue |
Long |
哈希值。 锁对象的 HASH 值,用于在全局锁表中快速定位和检索锁对象。 |
对象定位字段(TID 锁专用)
表格
复制
| 字段 | 类型 | 含义 |
|---|---|---|
tableId |
Integer |
表/对象 ID。 对于 OBJECT 锁:表示被锁定的对象 ID(表 ID 或字典对象 ID)。对于 TID 锁:表示被锁定记录所在的表 ID,对应 DBA_OBJECTS.OBJECT_ID。 |
rowIdx |
Long |
行信息(TID 锁特有)。 这是一个复合编码值,用于定位表中的具体行: 公式: ROW_IDX = N_PAGE × 64 + ROW_ID其中 N_PAGE 是逻辑页号,ROW_ID(0-63)是页内行号。实际计算:行在页内的位置 = rowIdx % 64,页号 = rowIdx / 64。 |
tid |
Long |
TID 锁目标事务 ID。 仅当 ltype = 'TID' 时有效。表示被锁定的目标事务号(即先修改记录且未提交的事务)。 通过锁定该事务号来阻止其他事务修改同一行,实现行级并发控制。 |
辅助字段
表格
复制
| 字段 | 类型 | 含义 |
|---|---|---|
ignFlag |
Integer |
忽略标记。 用于在锁转储分析的视图(如 V$DEADLOCK_HISTORY)中标识无效锁。值为 1 的锁不会被等待,在显示时会被排除(代表着连锁或无效连锁)。 正常情况下通常可忽略此字段。 |
实用查询示例
java
复制
// Java 中使用这些字段查询阻塞状态的示例逻辑:
// blocked = 1 表示该事务(trxId)正在等待 tid 事务释放锁
if (lock.getBlocked() == 1 && "TID".equals(lock.getLtype())) {
System.out.println("事务 " + lock.getTrxId() + " 正在等待事务 "
+ lock.getTid() + " 释放行锁 (表ID: "
+ lock.getTableId() + ")");
}
对应 SQL 查询:
sql
复制
SELECT
S.SESS_ID,
L.TRX_ID, -- 等待者
L.TID, -- 占用者(仅TID锁有效)
L.LTYPE,
L.LMODE,
L.TABLE_ID,
O.NAME AS TABLE_NAME,
L.BLOCKED -- 1=等待中,0=已获得
FROM V$LOCK L
LEFT JOIN DBA_OBJECTS O ON L.TABLE_ID = O.OBJECT_ID
LEFT JOIN V$SESSIONS S ON L.TRX_ID = S.TRX_ID
WHERE L.BLOCKED = 1; -- 仅看被阻塞的锁
关键区分点
-
trxIdvstid:trxId是"谁想要锁",tid是"锁住了谁"(仅TID锁) -
blocked字段:是状态标识而非阻塞对象ID,1表示当前这条记录代表一个等待状态 -
rowIdx编码:需要计算才能还原为页号和行号,通常与TABLE_ID联合使用才能定位物理行 -
hlckEp集群含义:在单节点环境始终为 0,在集群环境用于判断锁的分布位置
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)