rebuild index online的鎖機制淺析

wengtf發表於2012-10-30

一般都說,rebuild index online不阻塞DML操作,這是相對於rebuild index來說的,加上了online,只是在rebuild的期間不阻塞DML,但是在開始和結束階段還是可能阻塞其他程式的DML的,要弄清楚到底是阻塞還是不阻塞,何處阻塞,為什麼阻塞,還是要從鎖的角度來分析。本文實驗環境為Oracle 10.2.0.4

Oracle中的鎖,一共有6兩種模式:

  • 0:none
  • 1:null 空
  • 2:Row-S 行共享(RS):共享表鎖,sub share
  • 3:Row-X 行獨佔(RX):用於行的修改,sub exclusive
  • 4:Share 共享鎖(S):阻止其他DML操作,share
  • 5:S/Row-X 共享行獨佔(SRX):阻止其他事務操作,share/sub exclusive
  • 6:exclusive 獨佔(X):獨立訪問使用,exclusive

我們知道,DML操作一般要加兩個鎖,一個是對錶加模式為3的TM鎖,一個是對資料行的模式為6的TX鎖。只要操作的不是同一行資料,是互不阻塞的。但是rebuild index online在開始和結束的時候是需要對錶加一個模式為4的TM鎖的,這個可以很容易通過實驗觀察到,實驗中的測試表t是通過create table t as select * from all_objects生成,並且多次執行insert into t select * from t產生較多的資料,以便延遲rebuild的時間來觀察系統中鎖的情況:

session 1:

SQL> delete from t where object_id=28;

1 row deleted.

session 2:

SQL> alter index ix_t rebuild online;

Session 2被阻塞,會話掛起,這時查詢v$lock,可以得到如下結果:

SQL> select sid,type,id1,id2,lmode,request from v$lock where type in('DL','TM','TX'); 

       SID TY        ID1        ID2      LMODE    REQUEST
---------- -- ---------- ---------- ---------- ----------
      1643 DL      10599          0          3          0
      1643 DL      10599          0          3          0
      1622 TM      10599          0          3          0
      1643 TM      10599          0          2          4
      1643 TM      10607          0          4          0
      1622 TX     655398       1361          6          0


從上面的結果可以知道,1622是session 1,1643是session 2,session 2一共出現了4個鎖,兩個DL鎖,一個針對表t的TM鎖,一個是online rebuild index時需要的一箇中間表的TM鎖,中間表用於記錄rebuild期間的增量資料,原理類似於物化檢視日誌,其object_id為10607,這是一個索引組織表(IOT),從這裡我們也可以發現IOT的優點和適合的場合,這張中間表只有插入,不會有刪除和修改操作,而且只有主鍵條件查詢,正是IOT最合適的場景:

SQL> select object_name,object_type from all_objects where object_id=10607;

OBJECT_NAME                    OBJECT_TYPE
------------------------------ -------------------
SYS_JOURNAL_10602              TABLE

SQL> select table_name,iot_type from all_tables where table_name='SYS_JOURNAL_10602';

TABLE_NAME                     IOT_TYPE
------------------------------ ------------
SYS_JOURNAL_10602              IOT

Session 2在請求一個模式為4的TM鎖,模式4會阻塞這個表上的所有DML操作,所以這是再往這個表上執行DML也會掛起

session 3:

SQL> delete from t where object_id=46;

SQL> select sid,type,id1,id2,lmode,request from v$lock where type in('DL','TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST
---------- -- ---------- ---------- ---------- ----------
      1643 DL      10599          0          3          0
      1643 DL      10599          0          3          0
      1622 TM      10599          0          3          0
      1643 TM      10599          0          2          4
      1643 TM      10607          0          4          0
      1627 TM      10599          0          0          3
      1622 TX     655398       1361          6          0

1627就是session 3,請求模式為3的TM鎖無法獲得,會話被阻塞。這是因為鎖請求是需要排隊的,即使session 3和session 1是可以併發的,但由於session 2先請求鎖並進入等待佇列,或來的session 3也只好進入佇列等待。所以如果在執行rebuild index online前長事務,並且併發量比較大,則一旦執行alter index rebuild online,可能因為長事務阻塞,可能導致系統瞬間出現大量的鎖,對於壓力比較大的系統,這是一個不小的風險。這是需要迅速找出導致阻塞的會話kill掉,rebuild index online一旦執行,不可輕易中斷,否則可能遇到ORA-08104

在session 1執行rollback,可以發現很短時間內session 3也正常執行完畢,說明session 2只有模式4的TM鎖的時間很短,然後在rebuild online的進行過程中,對錶加的是模式為2的TM鎖,所以這段時間不會阻塞DML操作:

SQL> select sid,type,id1,id2,lmode,request from v$lock where type in('DL','TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST
---------- -- ---------- ---------- ---------- ----------
      1643 DL      10599          0          3          0
      1643 DL      10599          0          3          0
      1643 TM      10599          0          2          0
      1643 TM      10607          0          4          0
      1627 TM      10599          0          3          0
      1627 TX     655392       1361          6          0

保持session 3的事務不提交,等待一段時間後,session 2始終無法完成操作,再觀察系統中鎖的情況,可以發現又發生了變化:

SQL> select sid,type,id1,id2,lmode,request from v$lock where type in('DL','TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST
---------- -- ---------- ---------- ---------- ----------
      1643 DL      10599          0          3          0
      1643 DL      10599          0          3          0
      1643 TM      10599          0          2          4
      1643 TM      10607          0          4          0
      1627 TM      10599          0          3          0
      1643 TX     589852        258          6          0
      1627 TX     655392       1361          6          0
 

Session 2又開始在請求模式4的TM鎖,被session 3阻塞!這是在session 1再執行DML操作,同樣會被session 2阻塞,進入鎖等待佇列。

Session 1:

SQL>delete from t where object_id=11;

SQL> select sid,type,id1,id2,lmode,request from v$lock where type in('DL','TM','TX');

      SID TY        ID1        ID2      LMODE    REQUEST
---------- -- ---------- ---------- ---------- ----------
      1643 DL      10599          0          3          0
      1643 DL      10599          0          3          0
      1622 TM      10599          0          0          3
      1643 TM      10599          0          2          4
      1643 TM      10607          0          4          0
      1627 TM      10599          0          3          0
      1643 TX     589852        258          6          0
      1627 TX     655392       1361          6          0

在session 3執行rollback或者commit以後,session 2和session 3都很快執行完畢。

從上面的試驗可以發現,雖然rebuild index online在執行期間只持有模式2的TM鎖,不會阻塞DML操作,但在操作的開始和結束階段,是需要短暫的持有模式為4的TM鎖的,這段會阻塞表上的所有DML操作。我們在做rebuild index online的時候,一定要在開始和結束階段觀察系統中是否有長事務的儲存,對於併發量較大的系統,最嚴重的後果,可能在這兩個關鍵點導致資料庫產生大量鎖等待,系統負載飆升,甚至當機。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22907091/viewspace-747916/,如需轉載,請註明出處,否則將追究法律責任。

相關文章