
好的,我们来深入探讨 Oracle 19C 中一个更为底层和专有的动态性能视图:V$TRANSACTION_ENQUEUE。
这个视图对于诊断复杂的锁问题和深入理解 Oracle 的队列锁(Enqueue)机制至关重要。
🔍 深入解析 Oracle 19C 的 V$TRANSACTION_ENQUEUE 视图
1. 视图概述与核心作用
V$TRANSACTION_ENQUEUE 是一个专门用于显示与活动事务直接相关的队列锁(Enqueue) 信息的动态性能视图。它揭示了每个活动事务当前持有(Holding)或正在等待(Waiting)的锁资源。
- 核心作用:将事务(VTRANSACTION)∗∗与∗∗锁(VTRANSACTION)** 与**锁(VTRANSACTION)∗∗与∗∗锁(VLOCK / V$ENQUEUE_LOCK) 精确地关联起来。它回答了“哪个事务持有或等待哪个特定的锁?”这个问题。
- 与 V$LOCK 的区别:
- V$LOCK:显示的是会话(Session) 级别的锁信息。一个会话可能包含多个事务(尽管通常是一个),但它主要告诉你“哪个会话”持有或等待锁。
- V$TRANSACTION_ENQUEUE:显示的是事务(Transaction) 级别的锁信息。它直接链接到事务的唯一标识(XID),更精确地反映了事务之间的锁依赖关系,这对于分析阻塞链至关重要。
简单来说,VTRANSACTIONENQUEUE是VTRANSACTION_ENQUEUE 是 VTRANSACTIONENQUEUE是VTRANSACTION 和 V$LOCK 之间的桥梁,提供了事务粒度下的锁详情。
2. 核心字段详解
以下是该视图的核心字段,其格式已按要求调整以确保清晰。
| 字段名 | 数据类型 | 是否可为空 | 描述 |
|---|---|---|---|
| ADDR | RAW(8) | NO | 此条锁信息在内存中的地址。是此视图的一个唯一标识符。 |
| TRANS_ADDR | RAW(8) | NO | 关联的事务对象地址。直接对应 V$TRANSACTION.ADDR 字段,用于连接到特定的事务。 |
| INST_ID | NUMBER | NO | (在 RAC 环境中)持有或等待该锁的实例 ID。 |
| TYPE | VARCHAR2(2) | NO | 锁类型。这是队列锁的核心标识。常见类型: - TX:事务锁(行级锁) - TM:表锁(DML 锁) - UL:用户自定义锁 - ST:空间事务锁 - 等等 |
| ID1 | NUMBER | NO | 锁标识符 #1。其含义根据 TYPE 变化:- 对于 TX 锁: ID1 表示回滚段号 (USN) 和槽号 (SLOT) 的转换值。通常计算方式为:(USN << 16) + SLOT。- 对于 TM 锁: ID1 就是被锁定的表的 OBJECT_ID (可关联 DBA_OBJECTS) 。 |
| ID2 | NUMBER | NO | 锁标识符 #2。其含义根据 TYPE 变化:- 对于 TX 锁: ID2 表示事务的序列号 (SQN)。- 对于 TM 锁: ID2 通常为 0。 |
| MODE_HELD | NUMBER | NO | 持有的锁模式。表示该事务当前已经持有的锁的模式。数值与 V$LOCK 中的 LMODE 对应。常见模式:- 1 - NULL - 2 - 行共享 (RS/SS) - 3 - 行排他 (RX/SX) - 4 - 共享 (S) - 5 - 共享行排他 (SRX/SSX) - 6 - 排他 (X) |
| MODE_REQUESTED | NUMBER | NO | 请求的锁模式。表示该事务当前正在请求(等待) 的锁的模式。如果为 0(None),则表示该事务没有等待,而是持有该锁。数值与 V$LOCK 中的 REQUEST 对应。模式值同上。 |
| BLOCKING_OTHERS | VARCHAR2(1) | YES | 是否阻塞其他事务。指示此锁是否正在阻塞其他事务。 - Y:是的,此锁正在阻塞其他事务。 - N:否,此锁没有阻塞其他事务。 |
| TRANS_INDEX | NUMBER | YES | (已废弃)事务索引,为了向后兼容而保留。应使用 TRANS_ADDR。 |
| RESOURCE_NAME1 | VARCHAR2(30) | YES | 锁资源的名称组件 1(内部格式)。 |
| RESOURCE_NAME2 | VARCHAR2(30) | YES | 锁资源的名称组件 2(内部格式)。 |
3. 工作原理与底层机制
3.1 队列锁(Enqueue)机制简介
Oracle 使用队列锁(Enqueue)作为一种高级的串行化机制来管理对共享资源(如表、行、事务等)的并发访问。它是一种复杂的、基于队列的锁管理系统。
- 当事务需要访问一个资源时,它会向该资源的锁队列请求一个特定模式的锁。
- 如果请求的锁模式与队列中现有锁的模式兼容,请求会立即被授予。
- 如果不兼容,请求将被放入等待队列,事务进入等待状态(如
enq: TX - row lock contention)。
3.2 V$TRANSACTION_ENQUEUE 的底层原理
VTRANSACTIONENQUEUE∗∗视图的数据直接来源于内存中的底层∗∗XTRANSACTION_ENQUEUE** 视图的数据直接来源于内存中的底层 **XTRANSACTIONENQUEUE∗∗视图的数据直接来源于内存中的底层∗∗XKTADM 和 **XKTCXB∗∗等结构。这些XKTCXB** 等结构。这些 XKTCXB∗∗等结构。这些X 表存储了实例中所有活动事务的队列锁信息。
TRANS_ADDR直接指向X$KTCXB(Transaction Context Block)中的地址,从而将锁与事务关联。- 视图中的
TYPE,ID1,ID2定义了一个唯一的锁资源。Oracle 使用哈希算法基于这三个值来快速定位和管理锁。 MODE_HELD和MODE_REQUESTED反映了该事务在此资源上的当前状态,是锁兼容性判断的核心。
3.3 事务与锁的映射
- 事务开始时,会在回滚段事务表中获得一个槽位,形成唯一 XID (XIDUSN, XIDSLOT, XIDSQN)。
- 当事务修改数据时,它会自动在其所属的回滚段上获取一个 TX 锁,锁的
ID1和ID2由 XID 计算而来。这保证了同一时间只有一个事务能操作(提交或回滚)这个回滚段槽位。 - 当事务修改某表中的行时,它会先获取一个 TM 锁(在表上)以防止DDL操作,然后在该行上获取 TX 锁(通过修改数据块中的锁字节和ITL槽实现)。
- 所有这些锁信息都会实时反映在 V$TRANSACTION_ENQUEUE 中。
4. 主要应用场景
4.1 精确定位阻塞者事务
这是最核心的应用。当发现系统中有等待事件(如 enq: TX - row lock contention)时,可以使用此视图快速找到是哪个具体的事务导致了阻塞。
-- 查找所有正在阻塞其他事务的锁及其对应的事务信息
SELECT
te.inst_id,
te.type,
te.id1,
te.id2,
te.mode_held,
te.mode_requested,
te.blocking_others,
t.start_time,
t.status,
t.xidusn,
t.xidslot,
t.xidsqn,
s.sid,
s.serial#,
s.username,
s.machine,
s.program
FROM
gv$transaction_enqueue te
JOIN
gv$transaction t ON te.trans_addr = t.addr
JOIN
gv$session s ON t.ses_addr = s.saddr
WHERE
te.blocking_others = 'Y';
4.2 分析特定事务持有的所有锁
当你已经通过 V$TRANSACTION 找到了一个可疑的长事务,可以查看它持有和等待的所有锁。
-- 替换 '你的SID' 和 '你的SERIAL#' 为实际值
SELECT
te.type,
te.id1,
te.id2,
te.mode_held,
te.mode_requested,
te.blocking_others,
CASE te.type
WHEN 'TM' THEN (SELECT object_name FROM dba_objects WHERE object_id = te.id1)
WHEN 'TX' THEN 'Transaction Lock (Row Lock)'
ELSE 'Other'
END AS lock_description
FROM
v$transaction_enqueue te
JOIN
v$transaction t ON te.trans_addr = t.addr
JOIN
v$session s ON t.ses_addr = s.saddr
WHERE
s.sid = &your_sid
AND s.serial# = &your_serial;
4.3 死锁分析
在分析死锁时,V$TRANSACTION_ENQUEUE 可以帮助理解每个事务在死锁发生时持有和请求的锁资源,从而还原死锁环(Cycle)。
5. 相关视图与关联查询
| 视图名称 | 描述 | 常用关联字段 |
|---|---|---|
| V$TRANSACTION | 活动事务信息。 | V$TRANSACTION_ENQUEUE.TRANS_ADDR = V$TRANSACTION.ADDR |
| V$SESSION | 会话信息。 | V$TRANSACTION.SES_ADDR = V$SESSION.SADDR |
| VLOCK∗∗/∗∗GVLOCK** / **GVLOCK∗∗/∗∗GVLOCK | 会话级别的锁信息。 | V$SESSION.SID = V$LOCK.SID V$TRANSACTION_ENQUEUE.TYPE = V$LOCK.TYPE V$TRANSACTION_ENQUEUE.ID1 = V$LOCK.ID1 V$TRANSACTION_ENQUEUE.ID2 = V$LOCK.ID2 |
| V$ENQUEUE_LOCK | 另一个显示队列锁信息的视图。 | 关联方式类似 V$LOCK。 |
| DBA_OBJECTS | 数据库对象信息。 | V$TRANSACTION_ENQUEUE.ID1 = DBA_OBJECTS.OBJECT_ID (当 TYPE='TM') |
| V$SQL | SQL 文本。 | V$SESSION.SQL_ADDRESS = V$SQL.ADDRESS V$SESSION.SQL_HASH_VALUE = V$SQL.HASH_VALUE |
常用综合查询:获取完整的锁等待链(Blocking Chain)
COLUMN blocker_username FORMAT A15
COLUMN blocker_machine FORMAT A20
COLUMN blocker_program FORMAT A25
COLUMN waiter_username FORMAT A15
COLUMN waiter_machine FORMAT A20
COLUMN waiter_program FORMAT A25
SELECT
-- Blocker Info (Holder)
blocker_sess.sid blocker_sid,
blocker_sess.username blocker_username,
blocker_sess.machine blocker_machine,
blocker_sess.program blocker_program,
-- Blocker TX Info
blocker_te.type blocker_lock_type,
blocker_te.mode_held blocker_lock_mode_held,
-- Waiter Info (Waiter)
waiter_sess.sid waiter_sid,
waiter_sess.serial# waiter_serial#,
waiter_sess.username waiter_username,
waiter_sess.machine waiter_machine,
waiter_sess.program waiter_program,
waiter_sess.event waiter_wait_event,
-- Waiter TX Info (what it's waiting for)
waiter_te.type waiter_lock_type,
waiter_te.mode_requested waiter_lock_mode_req
FROM
v$transaction_enqueue blocker_te
JOIN
v$transaction blocker_t ON blocker_te.trans_addr = blocker_t.addr
JOIN
v$session blocker_sess ON blocker_t.ses_addr = blocker_sess.saddr
JOIN
v$lock waiter_lock ON (blocker_te.type = waiter_lock.type
AND blocker_te.id1 = waiter_lock.id1
AND blocker_te.id2 = waiter_lock.id2)
JOIN
v$session waiter_sess ON waiter_lock.sid = waiter_sess.sid
JOIN
v$transaction_enqueue waiter_te ON waiter_sess.saddr = waiter_te.ses_addr -- This join might need adjustment
WHERE
blocker_te.blocking_others = 'Y'
AND waiter_lock.request > 0
AND waiter_sess.state = 'WAITING';
6. 关键知识点总结
- 事务粒度:
V$TRANSACTION_ENQUEUE的核心价值在于提供了事务级别的锁视图,而V$LOCK是会话级别。 - TX 锁与事务ID:TX 锁的
ID1和ID2直接编码了事务的 XID (USN, Slot, SQN)。这是连接事务和锁的关键。 - 锁模式兼容性:理解
MODE_HELD和MODE_REQUESTED的含义以及它们之间的兼容性是分析阻塞的基础。(例如,持有的排他锁(6)与请求的共享锁(4)不兼容)。 - 内存结构:该视图的数据源于 SGA 中的 X$ 表,是实时的、易失的。实例重启后信息消失。
- RAC 环境:在 RAC 中,必须使用
GV$全局视图,并通过INST_ID来区分不同实例上的事务和锁。跨实例的阻塞也需要关注CI_(Current Instance) 和PI_(Past Instance) 相关的锁状态。
通过掌握 V$TRANSACTION_ENQUEUE,你可以穿透会话的抽象层,直接洞察事务之间的锁竞争关系,是进行高级性能诊断和故障排除的利器。
欢迎关注我的公众号《IT小Chen》
321

被折叠的 条评论
为什么被折叠?



