熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

解析Oracle多粒度鎖的驗證步驟

2022-06-13   來源: Oracle 

  創建測試表

  create>aaa@AAAUSORACLECOM>create table test (a numberb number)

  表已創建

   對於未提交的insert操作

  insert>aaa@AAAUSORACLECOM>insert into test values(

  已創建

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  AB ABA  TM      
  AF AF  TX      

  可見對於未提交的insert操作會產生兩個鎖其類型(TYPE)分別為TM和TX也就是表級意向鎖和事務鎖

  表級意向鎖的模式(LMODE)為表示是row exclusive即表示此表中的某行獲得了行排他鎖

  事務鎖的模式(LMODE)為 表示是exclusive即排他鎖表示此事務獲得了排他鎖

  BLOCK表示此鎖是否阻塞了其它的鎖即發生死鎖此處沒有

   對於提交的insert操作

  commit>aaa@AAAUSORACLECOM>commit

  提交完成

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;

  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK

  此處已沒有記錄說明在提交後即完成了鎖的釋放

   對於未提交的update操作

  update>aaa@AAAUSORACLECOM>update test set a= where a=

  已更新

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  AB ABA  TM      
  AF AF  TX      

  可見update操作所引起的鎖的信息完全等同於insert操作……

   對於提交的update操作

  commit>aaa@AAAUSORACLECOM>commit

  提交完成

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK

  此處已沒有記錄說明在提交後即完成了鎖的釋放

   對於select操作

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>select * from test where a=;
  A B
   
   
  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK

  此處已沒有記錄說明select操作不會引起任何鎖

  這是與sql server等數據庫不同的這些數據庫select操作也會引起鎖以取得一致讀

  而oracle是通過回滾機制實現一致讀的所以不需要引入鎖機制這極大增強了oracle的並發度

   for update操作

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>select * from test for update;
  A B
   
   
  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  AB ABA  TM      
  AF AF  TX      

  可見for update操作會引起兩個鎖分別是表級意向鎖(TM)和事務鎖(TX)

  表級意向鎖鎖定模式為(row share)這表示屬於此表中的某行獲得了共享鎖相比較DML操作此處鎖級別低了一級DML的是其實在oracle中沒有行級共享鎖

  TX的鎖定模式為表示行級排他鎖這與DML的效果一致

   for update操作commit後

  當commit後就會發現鎖已被釋放

   for update與update互鎖問題

  ) session

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>select * from test for update;
  A B
   
   

  ) session

  update>aaa@AAAUSORACLECOM>update test set a= where a=

  此時這條語句處於阻塞狀態說明等待鎖

  查看鎖

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  DCCC DCDC  TX      
  AB AB TM      
  AB ABA  TM      
  AF AF  TX      

  發現有兩個會話處於有鎖的活動

  發出for update操作的session (sid=)的有模式為(row share)的行級共享意向表級鎖模式為(exclusive)行級排他鎖

  發出update操作的session (sid=)的模式為(row exclusive)的行級排他意向鎖模式為(None)的行級鎖

  這說明第二個session(sid=)由於是後發出的操作它會首先去檢索將要操作的表是否存在鎖此處由於存在故就堵塞了所以沒有獲得行級鎖

  這也就說兩個session在檢測操作對象是否處於被鎖狀態時是首先檢測其表級鎖這就避免了去檢測沒一行的鎖這就提升了性能

  像這裡的情況我們所操作的對象是行但所利用的檢測鎖機制是在表級

  同時會發現session (sid=)的TX鎖的BLOCK為這表示此鎖堵住了另外的鎖同時我們會看到session (sid=)的TX鎖等待的對象ID和ID與sid=的相同這說明sid=的堵住了sid=

   rollback第一個會話的for update操作

  rollback>aaa@AAAUSORACLECOM>rollback

  回退已完成

  查看鎖

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  AB AB TM      
  AEB AEBC  TX      

  可見第一鎖的信息已沒有

  此時只有session 的鎖的信息而且session 已獲得鎖

  如果再將session 進行回滾就會發現session 的鎖也沒有了

  實體完整性引發的鎖阻塞

  在具有primary key約束的表中在兩個session中插入同樣的記錄

  alter>aaa@AAAUSORACLECOM>alter table test add constraint pk_a primary key(a)

  表已更改

  Session

  insert>aaa@AAAUSORACLECOM>insert into test(a) values(

  已創建

  Session

  insert>aaa@AAAUSORACLECOM>insert into test(a) values(

  session 處於阻塞狀態

  可見在session沒有提交的情況實體完整性約束就會阻塞住session

  查看鎖

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select * from v$lock;
  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  DCCC DCDC  TX      
  AEB AEBC  TX      
  AB AB TM      
  AB ABA  TM      
  AEAEA  TX      

  可見session (sid=)已獲得TM和TX鎖並且阻塞住了其它的鎖

  session (sid=)被阻塞

  可以發現 session 已獲得了行排他鎖

  AEB AEBC TX

  已經完全分配了新的事務所以session 不是被堵在和session 競爭同一個數據塊上(如上面的例子)而是被堵在了完整行約束上

  DCCC DCDC TX

  這個鎖請求的類型為 (share)

  Sessio

  rollback>aaa@AAAUSORACLECOM>rollback

  回退已完成

  Session

  insert>aaa@AAAUSORACLECOM>insert into test(a) values(

  已創建

   cellPadding= width=% bgColor=#cccccc> ff>

  ADDR KADDR SID TYPE ID D LMODE REQUEST CTIME BLOCK
  AB AB TM      
  AEB AEBC  TX      

  可見session 所持有的鎖剩余兩個那個原來等待session 的鎖已釋放

  參照完整性引發的鎖阻塞

  create>aaa@AAAUSORACLECOM>create table test_child(c numbera number not null constra

  int pk_a_ref references test(a))

  表已創建

  insert>aaa@AAAUSORACLECOM>insert into test(a) values(

  已創建

  Session

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row Exclusive TEST  
  
  AAA  Row share TEST_CHILD  
  

  可以發現有兩個對象被鎖住 TEST和TEST_CHILD

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TM   Row Exclusive  
  
   TM   Row share  
  
   TX   Exclusive  
  

  可見有三個鎖

   cellPadding= width=% bgColor=#cccccc> ff>

  SQL> select object_name from dba_objects where object_id=;
  OBJECT_NAME
  
  TEST
  SQL> select object_name from dba_objects where object_id=;
  OBJECT_NAME
  
  TEST_CHILD

  可見除了TEST表需要的TM和TX鎖外

  還同時將TEST_CHILD表鎖住了其鎖類型為Row share

  session

  insert>aaa@AAAUSORACLECOM>insert into test_child(ca) values(

  插入外鍵值為語句的執行會停頓

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row share TEST  
  
  AAA  Row Exclusive TEST_CHILD  
  
  AAA  Row Exclusive TEST  
  
  AAA  Row share TEST_CHILD  
  

  這時會發現被鎖住的對象有這是因為在子表中的插入同時會鎖住父表和子表

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TX   None  
  
   TM   Row share  
  
   TM   Row Exclusive  
  
   TX   Exclusive  
  
   TM   Row Exclusive  
  
   TX   Exclusive  
  
   TM   Row share  
  

  已選擇

  分析鎖的情況

  Session (sid=)有四個鎖分別是子表的TM和TX鎖

   TM Row Exclusive

  

   TX Exclusive

  父表的TM和TX鎖

   TX None

  

   TM Row share

  

  這是因為參照完整性需要父表在參照的過程中不能發生改變所以要對父表加上這些限制

  Session

  rollback>aaa@AAAUSORACLECOM>rollback

  回退已完成

  Session

  insert>aaa@AAAUSORACLECOM>insert into test_child(ca) values(

  insert into test_child(ca) values(

  *

  ERROR 位於第

  ORA 違反完整約束條件 (AAAPK_A_REF) 未找到父項關鍵字

   更新子表時

  update>aaa@AAAUSORACLECOM>update test_child set a= where =

  已更新

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row share TEST  
  
  AAA  Row Exclusive TEST_CHILD  
  
  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TM   Row share  
  
   TM   Row Exclusive  
  

  可見當更新子表時會鎖住父子兩個表即使實際上沒有更新數據

   當更新父表時

  update>aaa@AAAUSORACLECOM>update test set a= where =

  已更新

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row Exclusive TEST  
  
  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TM   Row Exclusive  
  
  >
  可見更新父表只會鎖住父表

   當父子兩個表同時更新時

  session

  update>aaa@AAAUSORACLECOM>update test_child set a= where =

  已更新

  Session

  update>aaa@AAAUSORACLECOM>update test set a= where =

  session 會被鎖住

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row Exclusive TEST  
  
  AAA  None TEST_CHILD  
  
  AAA  Row Exclusive TEST  
  
  AAA  Row Exclusive TEST_CHILD  
  
  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TM   Row Exclusive  
  
   TM   None  
  
   TM   Row Exclusive  
  
   TM   Row Exclusive  
  

  可見會發生死鎖是由於第二個session 申請子表的share鎖時發生的

  對外鍵建立索引

  create>aaa@AAAUSORACLECOM>create index idx_child on test_child(a)

  索引已創建

  當父子兩個表同時更新時

  session

  update>aaa@AAAUSORACLECOM>update test_child set a= where =

  已更新

  Session

  update>aaa@AAAUSORACLECOM>update test set a= where =

  已更新

  可見不會發生死鎖

   cellPadding= width=% bgColor=#cccccc> ff>

  aaa@AAAUSORACLECOM>@showlockedobj
  O_NAME SID LOCK_TYPE OBJECT_NAME XIDUSN XIDSLOT
  XIDSQN
      
  
  AAA  Row Exclusive TEST  
  
  AAA  Row share TEST_CHILD  
  
  AAA  Row share TEST  
  
  AAA  Row Exclusive TEST_CHILD  
  
  aaa@AAAUSORACLECOM>@showlocks
  SID TYPE ID ID LOCK_TYPE REQUEST CTIME
  BLOCK
       
  
   TM   Row Exclusive  
  
   TM   Row share  
  
   TM   Row share  
  
   TM   Row Exclusive  
  

  可以發現session 獲得TEST_CHILD行級排他意向表鎖同時獲得TEST表的行級共享排他意向鎖

  session 獲得TEST行級排他意向表鎖同時獲得TEST_CHILD表的行級共享排他意向鎖

  與上個例子相比區別在於前面的例子中session 獲得TEST_CHILD和TEST行級排他意向表鎖

  也就是說對外鍵建立索引可以防止兩個表的死鎖

   總結

  Oracle通過具有意向鎖的多粒度封鎖機制進行並發控制保證數據的一致性其DML鎖(數據鎖)分為兩個層次(粒度)即表級和行級通常的DML操作在表級獲得的只是意向鎖(RS或RX)其真正的封鎖粒度還是在行級另外在Oracle數據庫中單純地讀數據(SELECT)並不加鎖這些都極大地提高了系統的並發程度

  在支持高並發度的同時Oracle利用意向鎖及數據行上加鎖標志位等設計技巧減小了Oracle維護行級鎖的開銷使其在數據庫並發控制方面有著明顯的優勢


From:http://tw.wingwit.com/Article/program/Oracle/201311/18429.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.