主表、子表、外鍵TM鎖

       在學習子表的外鍵列上是否添加索引這一塊知識時,建議是要添加索引的,但是這裏我想記錄的是許多資料都提到如果不添加索引,在對主表進行UPDATE、DELETE操作時,會對子表加個全表鎖-TM鎖,但是沒有提到是哪種TM鎖,後來經過搜索資料後,並通過自己的實驗,發現是添加的TM LOCK TYPE=4  Share類型的共享鎖。

       這裏提一下這個TM LOCK TYPE 4類型的鎖只會作用在UPDATE、DELETE語句對主表進行操作時,執行完畢後,子表上的這個Share鎖就會消失,而不是作用在整個事務上的鎖,所以如果不進行特定的測試,是看不到該鎖的,有請多同學對這一塊理解的有誤,以爲是作用在整個事務上的,即以爲UPDATE、DELETE語句執行完後,會在V$LOCK中看到這個TM LOCK TYPE 4類型的鎖,但是當UPDATE、DELETE語句執行完後,子表上的這個鎖就消失了。

      並且在主表上的INSERT語句是不會對子表產生該鎖的。

      下面把如何看到該鎖的實驗貼出來,分享給大家:

實驗環境:

數據庫版本:11.2.0.1 

操作系統:Windows

下面是實驗記錄可以看到該鎖:

SESSION 1:   select sid from v$mystat where rownum=1;    SID=17

SESSION 2:   select sid from v$mystat where rownum=1;    SID=22

使用SCOTT用戶下的表: 主表:DEPT (主鍵DEPTNO,OBJECT_ID=79188)   子表:EMP(外鍵DEPTNO,OBJECT_ID=80523),這裏同學們也可以自己來創建主表和子表。

在子表EMP的DEPTNO列上沒有創建索引時:

SESSION 1:

  1. 刪除子表上的一行,其實做這步的目的就是爲了一會阻塞主表上的這個Share鎖,這一步是關鍵,否則會看不到這個Share鎖,原因上面已經說過了:  
  2. SQL> delete from emp where rownum=1;  
  3.   
  4. 1 row deleted.  

查看會話中目前已經有的鎖,當對子表進行INSERT、UPDATE、DELETE操作時,也會對主表加個3級的Row-X (SX)行級排它鎖

  1. SQL> select * from v$lock where sid in (17,22) and type in ('TM','TX'order by sid,type;  
  2.   
  3. ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK  
  4. -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------  
  5. 0D79C52C 0D79C55C         17 TM      79188          0          3          0          6          0  
  6. 0D79C52C 0D79C55C         17 TM      80523          0          3          0          6          0  
  7. 2DE15208 2DE15248         17 TX     196614       3830          6          0          6          0  

SESSION 2:

  1. 我們對主表DELETEUPDATE一條記錄,這裏要更新或刪除子表中沒有使用的記錄:  
  2. SQL> delete from dept where deptno=50;  
  3. 你會發現上現這條語句hang住了  

SESSION 1:

  1. 查看鎖信息,你會發現22號會話想對80523對象(EMP表)加一個TYPE 4類型的鎖,根據TM鎖兼容的矩陣圖,可以瞭解到3號與4號鎖不兼容,所以22號會話被阻塞,需要等待:  
  2. SQL> select * from v$lock where sid in (17,22) and type in ('TM','TX'order by sid,type;  
  3.   
  4.   
  5. ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK  
  6. -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------  
  7. 0D79C52C 0D79C55C         17 TM      79188          0          3          0          6          0  
  8. 0D79C52C 0D79C55C         17 TM      80523          0          3          0          6          1  
  9. 2DE15208 2DE15248         17 TX     196614       3830          6          0          6          0  
  10. 0D79C52C 0D79C55C         22 TM      80523          0          0          4          3          0  
  11. 0D79C52C 0D79C55C         22 TM      79188          0          3          0          3          0  
  12.   
  13. SQL> rollback;  
  14.   
  15. Rollback complete.  
  16. 回滾後22話會話操作成功,再次查看鎖信息,你會發現子表的4號鎖已經沒有了,所以驗證了上面說的,只在語句操作期間加鎖,操作完成後,就沒了,不作用在整個事務上:  
  17. SQL> select * from v$lock where sid in (17,22) and type in ('TM','TX'order by sid,type;  
  18.   
  19.   
  20. ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK  
  21. -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------  
  22. 0D79C52C 0D79C55C         22 TM      79188          0          3          0        724          0  
  23. 2DDE31F4 2DDE3234         22 TX     589836       3809          6          0         47          0  


       上面我們還說過INSERT對主表操作,是不會對子表加鎖的,可以按照上面的操作來一次,這裏就不在演示,如果添加索引後,就不會發生這種阻塞,請自行驗證。

       再提一句,如果子表不能被加上類型4的鎖,即上面SESSION 2被阻塞後,再有其它會話來更新子表(UPDATE/DELETE)也會被HANG住。

附上TM鎖兼容矩陣圖:

發佈了50 篇原創文章 · 獲贊 13 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章