在发现TX锁时,我们如何鉴别是哪一种情况导致的呢?当存在TX等待队列时,如何找到锁所在的对象呢?
记录锁
这类锁是事务插入/删除/更新数据记录时加在记录的锁。对于插入操作,数据在未提交之前对其他事务是“不可见”的,因而不会导致TX等待。这一类的TX锁是比较容易鉴别的——只有这类锁的模式(mode)是6(即排它锁,exclusive)。通过v$lock很容易鉴定出来:
HELLODBA.COM> create table tx_lock_tab (a number, b char(1), c varchar2(20));
Table created.
HELLODBA.COM> insert into tx_lock_tab (a, b, c) values (99, 'C', 'AOAKAPSOD');
1 row created.
HELLODBA.COM> insert into tx_lock_tab (a, b, c) values (100, 'C', 'AOAKAPSOD');
1 row created.
HELLODBA.COM> insert into tx_lock_tab (a, b, c) values (101, 'd', 'AOAKAPSOD');
1 row created.
HELLODBA.COM> commit;
Commit complete.
session 1中:
HELLODBA.COM> delete from tx_lock_tab where a=100;
1 row deleted.
HELLODBA.COM> select * from v$lock where type='TX';
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
1E200F98 1E2010B4 135 TX 458781 104223 6 0 36 0
可以看到,Lock Mode为6.
等待队列分析
当发现系统中由于此类锁导致的等待而致使会话hung住时,可以通过以下过程来找到导致阻塞的会话、语句和对象。
续上,在Session 2中执行:
HELLODBA.COM> delete from tx_lock_tab where a=100;
此时,锁等待队列形成。从V$ENQUEUE_LOCK中可以查询到这一锁队列:
HELLODBA.COM> select * from V$ENQUEUE_LOCK where type='TX';
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
1EC34448 1EC3445C 127 TX 458781 104223 0 6 213 0
注意:V$ENQUEUE_LOCK的结构与V$LOCK结构很相似,但是,V$LOCK查询到的是被持有的锁及其SID,V$ENQUEUE_LOCK查询到的导致队列等待的锁以及请求锁的SID。
同时,通过v$session_event可以查询到会话等待事件是"enq: TX - row lock contention":
HELLODBA.COM> select s.sid, s.event
2 from v$session_event s, v$enqueue_lock l
3 where s.sid = l.sid
4 and s.event like 'enq: TX%';
SID EVENT
---------- -----------------------------------------------------
127 enq: TX - row lock contention
责任编辑:小草