TX ENQUEUE阻塞的理解

kewin發表於2011-09-20
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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章