达梦数据库 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:表的对象IDID2:通常为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'的行锁争用
问题处理流程:
text
复制 下载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)调整相关语法和字段。
本回答由 AI 生成,内容仅供参考,请仔细甄别。