TX ENQUEUE阻塞的理解
Kevin Zou
2011-9-19
当一个SESSION开启新事务时,该SESSION 就要获取一个TX ENQUEUE。该TX ENQUEUE在会话的第一个DML就开始获得,一直到事务提交或者回滚。这里LOCK 和ENQUEUE的同义词。
通过回滚段号,事务槽号每个事务都是唯一的。具体的点就是通过V$SQL的ID1和ID2来得到。TX ENQUEUE主要是用来建立一个队列机制,所以其他的事务等待事务的完成。
一个事务在等待TX ENQUEUE锁是因为以下原因:
1) 其他的事务锁定了特定的行;
2) 当两个事务想插入相同的唯一健值到表中,两个事务都没有提交;后来会话就要等待;
3) 没有足够的ITL。
其他的事务锁定了特定的行例子:
SESSION-1:
SQL> create table t(id int);
表已创建。
SQL> alter table t add constraint t_pri primary key (id) ;
表已更改。
SQL> insert into t values(1);
已创建 1 行。
SQL> COMMIT;
SQL> update t set id = 2 where id =1;
已更新 1 行。
新创建一个会话 SESSION-2:
SQL> conn /as sysdba
已连接。
SQL> update t set id =4 where id = 1;
这时SESSION-2被阻塞;
通过SESSION-1查看:
SQL> SELECT sid,id1,id2,type,lmode,request,block FROM v$lock where sid in (139,1
40) and type='TX' order by sid;
SID ID1 ID2 TY LMODE REQUEST BLOCK
---------- ---------- ---------- -- ---------- ---------- ----------
139 983082 6 TX 6 0 1
140 983082 6 TX 0 6 0
SQL> select P1, p1raw, p2,p3 from v$session where sid = 140;
P1 P1RAW P2 P3
---------- -------- ---------- ----------
1415053318 54580006 983082 6
SQL> select chr(bitand(&&P1,-16777216)/16777215)||chr(bitand(&&P1,16711680)/6553
5) "Lock", mod(&&p1,16) "MODE"
2 from dual;
原值 1: select chr(bitand(&&P1,-16777216)/16777215)||chr(bitand(&&P1,16711680
)/65535) "Lock", mod(&&p1,16) "MODE"
新值 1: select chr(bitand(1415053318,-16777216)/16777215)||chr(bitand(1415053
318,16711680)/65535) "Lock", mod(1415053318,16) "MODE"
Lo MODE
-- ----------
TX 6
SQL> select ROW_WAIT_OBJ#,
2 ROW_WAIT_FILE#,ROW_WAIT_BLOCK#,ROW_WAIT_ROW#
3 from v$session
4 where sid=140;
ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
------------- -------------- --------------- -------------
52326 1 60618 0
SQL> select object_name, object_id from dba_objects where object_id = 52326;
OBJECT_NAME OBJECT_ID
T 52326
SESSION-1 的ID 为139
SESSION-2 的ID 为140
因为140 会话想更新和139相同的数据,但是139没有提交,140只有等待;139 阻塞了140.
插入相同的唯一健值的例子:
在SESSION-1#:
SQL> insert into t values(10);
已创建 1 行。
在SESSION-2#:
SQL> insert into t values(10);
这时窗口被HOLD住了。
回到第一个SESSION-1#:
SQL> SELECT sid,id1,id2,type,lmode,request,block FROM v$lock where sid in (139,140) and type='TX' order by sid;
SID ID1 ID2 TY LMODE REQUEST BLOCK
---------- ---------- ---------- -- ---------- ---------- ----------
139 1114159 6 TX 6 0 1
140 852007 6 TX 6 0 0
140 1114159 6 TX 0 4 0
session-2#除了拥有自身的TX ENQUEUE外,还以共享模式申请了SESSION-1#拥有的TX ENQUEUE。
SESSION-1#
SQL> commit;
提交完成。
SESSION-2#
SQL> insert into t values(10);
insert into t values(10)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SYS.T_PRI)
没有足够的ITL例子:
ORACLE在每个BLOCK 头开辟了一块区域来记录哪行数据被哪个事务锁住,这块区域就是ITL,全称为interested transaction list。
对象的INITRANS 和 MAXTRANS 属性确定了对象块的ITL大小。INITRANS是至少数值,而MAXTRANS指定了上限。每个想修改数据块中的数据必须获得数据块的ITL的槽位。如果申请槽位的数量大于MAXTRANS,那后来的SESSION必须等待,知道某个槽位被释放出来。
SESSION-1#:
SQL> ALTER TABLE t MAXTRANS 1;
表已更改。
SQL> select * from t;
ID
----------
10
20
SQL> update t set id =1 where id =10;
已更新 1 行。
在SESSION-2#中,
SQL> update t set id =2 where id =20;
已更新 1 行。
在10GR2的环境中模拟不了这个例子。是因为MAXTRANS 不起作用了。
SQL> select table_name,INI_TRANS,MAX_TRANS from user_tables where table_name='T'
;
TABLE_NAME INI_TRANS MAX_TRANS
------------------------------ ---------- ----------
T 1 255
看到这个TABLE 的MAXTRANS还是255,无法更新。
-THE END-
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/40239/viewspace-707937/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/40239/viewspace-707937/