鎖讀書筆記

foxmile發表於2008-01-17
一、基本概念
1、丟失更新
在沒有鎖的情況下,兩個人在基本同一時間對資料庫的某行做修改。後來修改的會話會覆蓋掉之前修改的會話的結果。

2、阻塞
一個會話保持另一個會話正在請求的資源上的鎖定時,就發生阻塞。阻塞分為插入阻塞、更新和刪除阻塞。
避免發生阻塞的方法是使用序列或者DBMS_LOCK包提供的方法手工鎖定避免此情況。
更新阻塞可採用select  from upadate nowait來驗證沒有更新的行。

3、死鎖
A會話:Update test Set test.col1 = 36 不提交
B會話:Update test1 set test1.col1=48 不提交

B會話:update test set test.col1=48 不提交
A會話:Update test1 Set test1.col1 = 96

然後在B會話會提示:
ORA-00060:等待資源時檢測到死鎖

檢查沒有索引的外來鍵:
column columns format a30 word_wrapped
column tablename format a15 word_wrapped
column constraint_name format a15 word_wrapped
    
 select table_name, constraint_name,
      cname1 || nvl2(cname2,','||cname2,null) ||
      nvl2(cname3,','||cname3,null) || nvl2(cname4,','||cname4,null) ||
      nvl2(cname5,','||cname5,null) || nvl2(cname6,','||cname6,null) ||
      nvl2(cname7,','||cname7,null) || nvl2(cname8,','||cname8,null)
            columns
   from ( select b.table_name,
                b.constraint_name,
                max(decode( position, 1, column_name, null )) cname1,
               max(decode( position, 2, column_name, null )) cname2,
            max(decode( position, 3, column_name, null )) cname3,
                max(decode( position, 4, column_name, null )) cname4,
                 max(decode( position, 5, column_name, null )) cname5,
                max(decode( position, 6, column_name, null )) cname6,
                max(decode( position, 7, column_name, null )) cname7,
                 max(decode( position, 8, column_name, null )) cname8,
                 count(*) col_cnt
           from (select substr(table_name,1,30) table_name,
                        substr(constraint_name,1,30) constraint_name,
                        substr(column_name,1,30) column_name,
                         position
                    from user_cons_columns ) a,
                 user_constraints b
           where a.constraint_name = b.constraint_name
             and b.constraint_type = 'R'
           group by b.table_name, b.constraint_name
       ) cons
 where col_cnt > ALL
          ( select count(*)
             from user_ind_columns i
             where i.table_name = cons.table_name
              and i.column_name in (cname1, cname2, cname3, cname4,
                                     cname5, cname6, cname7, cname8 )
              and i.column_position <= cons.col_cnt
             group by i.index_name
         )
/

在plsql中執行該指令碼報錯。提示ORA-00979:不是group by表示式,儘管報錯了,但是測試繼續。

二、鎖定型別
1  DML鎖定
1.1 TX鎖定
TX用於保證在一段時間只有一個使用者進行修改,並且別人不可一刪除正在使用的表。
測試如下:

在會話A執行
Update test Set col1 = 118 Where col1 = 18
不提交

在當前會話執行
Update test Set col1 = 128 Where col1 = 18

提示0行被更新

在B會話執行
Update test Set col1 = 128 Where col1 = 18

該執行掛起,等待A會話的執行確認或者回滾之後才能正常執行。


在A會話執行:
alter table TEST drop column COL1;
提示:ORA-00054: 資源正忙,要求指定 NOWAIT

執行:
select username,v$lock.TYPE,
        v$lock.sid,
        trunc(id1/power(2,16)) rbs,
       bitand(id1,to_number('ffff','xxxx'))+0 slot,
        id2 seq,
        lmode,
        request
 from v$lock, v$session
 where v$lock.type = 'TX'
    and v$lock.sid = v$session.sid
   and v$session.username = USER
/
v$session展示登陸的會話
v$lock包含所有被持有的鎖的入口,也包含正在等待鎖定的會話的入口

結果如下:

SQL> select username,v$lock.TYPE,
  2          v$lock.sid,
  3          trunc(id1/power(2,16)) rbs,
  4         bitand(id1,to_number('ffff','xxxx'))+0 slot,
  5          id2 seq,
  6          lmode,
  7          request
  8   from v$lock, v$session
  9   where v$lock.type = 'TX'
 10      and v$lock.sid = v$session.sid
 11     and v$session.username = USER
 12  /
 
 
USERNAME                       TYPE        SID        RBS       SLOT        SEQ      LMODE    REQUEST
------------------------------ ---- ---------- ---------- ---------- ---------- ---------- ----------
TEST                           TX           13          7         31        250          0          6
TEST                           TX           14          7         31        250          6          0


執行指令碼:
select XIDUSN, XIDSLOT, XIDSQN
    from v$transaction
/

v$transaction展示了每個活動事物的入口

結果如下:

select XIDUSN, XIDSLOT, XIDSQN
  2      from v$transaction
  3  /
 
 
    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         7         31        250


繼續測試,回滾A會話的修改,回滾B會話的修改,關閉B會話

執行:
select username,v$lock.TYPE,
        v$lock.sid,
        trunc(id1/power(2,16)) rbs,
       bitand(id1,to_number('ffff','xxxx'))+0 slot,
        id2 seq,
        lmode,
        request
 from v$lock, v$session
 where v$lock.type = 'TX'
    and v$lock.sid = v$session.sid
   and v$session.username = USER
/

SQL> select username,v$lock.TYPE,
  2          v$lock.sid,
  3          trunc(id1/power(2,16)) rbs,
  4         bitand(id1,to_number('ffff','xxxx'))+0 slot,
  5          id2 seq,
  6          lmode,
  7          request
  8   from v$lock, v$session
  9   where v$lock.type = 'TX'
 10      and v$lock.sid = v$session.sid
 11     and v$session.username = USER
 12  /
 
USERNAME                       TYPE        SID        RBS       SLOT        SEQ      LMODE    REQUEST
------------------------------ ---- ---------- ---------- ---------- ---------- ---------- ----------
 
SQL>

此時鎖定消失。


在會話A執行
Update test Set col1 = 118 Where col1 = 18
不提交

執行:
select username,v$lock.TYPE,
        v$lock.sid,
        trunc(id1/power(2,16)) rbs,
       bitand(id1,to_number('ffff','xxxx'))+0 slot,
        id2 seq,
        lmode,
        request
 from v$lock, v$session
 where v$lock.type = 'TX'
    and v$lock.sid = v$session.sid
   and v$session.username = USER
/

結果:

SQL> select username,v$lock.TYPE,
  2          v$lock.sid,
  3          trunc(id1/power(2,16)) rbs,
  4         bitand(id1,to_number('ffff','xxxx'))+0 slot,
  5          id2 seq,
  6          lmode,
  7          request
  8   from v$lock, v$session
  9   where v$lock.type = 'TX'
 10      and v$lock.sid = v$session.sid
 11     and v$session.username = USER
 12  /
 
USERNAME                       TYPE        SID        RBS       SLOT        SEQ      LMODE    REQUEST
------------------------------ ---- ---------- ---------- ---------- ---------- ---------- ----------
TEST                           TX           14          3         17        329          6          0
 
結論:oracle給每個會話開啟一個鎖定

1.2 TM鎖定

這些鎖定用來保證在更改表的內容時,表的結構不會被更改。

分別執行下面的語句,
Insert Into test Values(1,2)

Insert Into test1 Values (2,3)
不提交

執行:

select username,
       v$lock.sid,
            id1, id2,
        lmode,
           request, block, v$lock.type
 from v$lock, v$session
  where v$lock.sid = v$session.sid
    and v$session.username = USER
/

結果如下:

SQL> select username,
  2         v$lock.sid,
  3              id1, id2,
  4          lmode,
  5             request, block, v$lock.type
  6   from v$lock, v$session
  7    where v$lock.sid = v$session.sid
  8      and v$session.username = USER
  9  /
 
 
USERNAME                              SID        ID1        ID2      LMODE    REQUEST      BLOCK TYPE
------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- ----
TEST                                   14      30914          0          3          0          0 TM
TEST                                   14      65558        265          6          0          0 TX
TEST                                   14      31267          0          3          0          0 TM
 
SQL>

結論:每個事務中只獲取一個TX鎖,但是可以獲取與所修改數量一樣多的TM鎖定。此時ID1是DML鎖定物件的物件ID。
TM縮的總數是可配置的DML_LOCKS,如果該引數配置為0,意味著不允許DDL。

2、DDL鎖定

三種DDL鎖定:
2.1 獨佔的DDL鎖定,防止其他會話獲得DDL鎖定或TM鎖定,意味著在此期間,查詢可以進行,任何方式的修改不允許。
2.2 共享的DDL鎖定,保護引用物件的結構,防止其他會話修改,但是允許資料修改
2.3 可以打破的分析鎖定,不能防止DDL發生

多數的DDL使用獨佔的DDL鎖定

下面的語句不使用DDL獨佔鎖
Create Index index_test On test(col1) Online

執行該語句之前執行:
Create Table ddl_lock1 As Select *  From dba_ddl_locks
SQL> desc  ddl_lock1;
Name           Type         Nullable Default Comments
-------------- ------------ -------- ------- --------
SESSION_ID     NUMBER       Y                        
OWNER          VARCHAR2(60) Y                        
NAME           VARCHAR2(60) Y                        
TYPE           VARCHAR2(40) Y                        
MODE_HELD      VARCHAR2(9)  Y                        
MODE_REQUESTED VARCHAR2(9)  Y   
SQL> col session_id for a10;
SQL> col owner for a10;
SQL> col name for a30;
SQL> col type for a30;
SQL> select * from ddl_lock1
  2  /
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
         5 XDB        DBMS_XDBZ0                     Body                           Null      None
         5 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
         5 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
         5 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
         5 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
         5 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
         5 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
         5 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
         5 XDB        DBMS_XDBZ                      Body                           Null      None
        13 XDB        DBMS_XDBZ0                     Body                           Null      None
        13 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
        13 SYS        DATABASE                       18                             Null      None
        13 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
        13 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
        13 TEST       TEST                           18                             Null      None
        13 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        13 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        13 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        13 XDB        DBMS_XDBZ                      Body                           Null      None
        13 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
        17 SYS        DBMS_TRANSACTION               Table/Procedure/Type           Null      None
        17 SYS        DBMS_TRANSACTION               Body                           Null      None
        17 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        17 SYS        DATABASE                       18                             Null      None
        17 TEST       TEST                           18                             Null      None
        17 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
 
28 rows selected
 



執行該語句之後執行:
Create Table ddl_lock2 As Select *  From dba_ddl_locks

利用PL/SQL DEVELOPER工具進行DDL操作,刪除col1欄位,不提交
同時執行語句:
Create Table ddl_lock3 As Select *  From dba_ddl_locks


在另外一個會話利用PL/SQL DEVELOPER工具進行DDL操作,修改col1欄位為col3欄位,不提交

執行:

Create Table ddl_lock4 As Select *  From dba_ddl_locks


執行:
Select * From  ddl_lock2
Minus
Select * From  ddl_lock1

結果:

SQL> Select * From  ddl_lock2
  2  Minus
  3  Select * From  ddl_lock1
  4  /
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        13 SYS        DATABASE                       18                             Null      None
        13 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        13 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
        13 SYS        DBMS_OUTPUT                    Body                           Null      None
        13 SYS        DBMS_OUTPUT                    Table/Procedure/Type           Null      None
        13 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
        13 SYS        DBMS_TRANSACTION               Body                           Null      None
        13 SYS        DBMS_TRANSACTION               Table/Procedure/Type           Null      None
        13 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
        13 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
        13 TEST       TEST                           18                             Null      None
        13 XDB        DBMS_XDBZ                      Body                           Null      None
        13 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
        13 XDB        DBMS_XDBZ0                     Body                           Null      None
        13 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
        17 TEST       DDL_LOCK2                      Table/Procedure/Type           Exclusive None
 

執行:
Select * From  ddl_lock3
Minus
Select * From  ddl_lock2
結果:
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        17 TEST       DDL_LOCK3                      Table/Procedure/Type           Exclusive None

執行:
Select * From  ddl_lock4
Minus
Select * From  ddl_lock3

結果:

SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        17 TEST       DDL_LOCK4                      Table/Procedure/Type           Exclusive None

最終的dba_ddl_locks內容如下:
SQL> col session_id for a10;
SQL> col owner for a10;
SQL> col name for a30;
SQL> col type for a30
SQL> Select * From  ddl_lock4
  2  /
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
         5 XDB        DBMS_XDBZ0                     Body                           Null      None
         5 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
         5 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
         5 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
         5 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
         5 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
         5 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
         5 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
         5 XDB        DBMS_XDBZ                      Body                           Null      None
         7 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
         7 SYS        DATABASE                       18                             Null      None
         7 TEST       TEST                           18                             Null      None
         7 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        12 XDB        DBMS_XDBZ0                     Body                           Null      None
        12 SYS        DATABASE                       18                             Null      None
        12 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
        12 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
        12 TEST       TEST                           18                             Null      None
        12 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        12 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        12 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
        12 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
        12 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        12 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
        12 XDB        DBMS_XDBZ                      Body                           Null      None
        12 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
        13 XDB        DBMS_XDBZ0                     Body                           Null      None
        13 SYS        DATABASE                       18                             Null      None
        13 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
        13 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
        13 TEST       TEST                           18                             Null      None
        13 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        13 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        13 SYS        DBMS_OUTPUT                    Body                           Null      None
        13 SYS        DBMS_OUTPUT                    Table/Procedure/Type           Null      None
        13 SYS        DBMS_TRANSACTION               Body                           Null      None
        13 SYS        DBMS_TRANSACTION               Table/Procedure/Type           Null      None
        13 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
        13 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
        13 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
 
SESSION_ID OWNER      NAME                           TYPE                           MODE_HELD MODE_REQUESTED
---------- ---------- ------------------------------ ------------------------------ --------- --------------
        13 XDB        DBMS_XDBZ                      Body                           Null      None
        13 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
        17 TEST       DDL_LOCK4                      Table/Procedure/Type           Exclusive None
        17 XDB        DBMS_XDBZ0                     Table/Procedure/Type           Null      None
        17 SYS        DBMS_STANDARD                  Table/Procedure/Type           Null      None
        17 TEST       TEST                           18                             Null      None
        17 SYS        DBMS_APPLICATION_INFO          Body                           Null      None
        17 SYS        DBMS_APPLICATION_INFO          Table/Procedure/Type           Null      None
        17 SYS        DBMS_OUTPUT                    Body                           Null      None
        17 SYS        DBMS_OUTPUT                    Table/Procedure/Type           Null      None
        17 SYS        DBMS_TRANSACTION               Body                           Null      None
        17 SYS        DBMS_TRANSACTION               Table/Procedure/Type           Null      None
        17 SYS        DATABASE                       18                             Null      None
        17 SYS        DICTIONARY_OBJ_NAME            Table/Procedure/Type           Null      None
        17 SYS        DICTIONARY_OBJ_OWNER           Table/Procedure/Type           Null      None
        17 SYS        DBMS_CDC_PUBLISH               Table/Procedure/Type           Null      None
        17 SYS        DBMS_CDC_PUBLISH               Body                           Null      None
        17 XDB        DBMS_XDBZ                      Body                           Null      None
        17 XDB        DBMS_XDBZ0                     Body                           Null      None
        17 XDB        DBMS_XDBZ                      Table/Procedure/Type           Null      None
 
61 rows selected

SQL>
其中的含義不是很明白,只瞭解,在每次進行過程中,就加了一個DDL鎖定。
在模擬DDL鎖之前dba_ddl_locks的內容都是什麼含義?
模擬DDL鎖定之後,TEST使用者中的每個鎖定意義是什麼?
DDL鎖釋放之後,什麼時候更新dba_ddl_locks表中的內容,還是說不會更新?

3 鎖存器和內部鎖定(入隊)(latches and internal locks(enqueues))
鎖存器是在極短時間內,例如用於修改記憶體裡資料結構的時間內保持的鎖定,他們用來保護某些記憶體結構。
入隊是另外一個複雜的序列化裝置,例如在更新資料庫表中的行時使用,它們與鎖存器的區別在於他們允許請求者排隊等待資源,使用鎖存器請求,請求者立刻被告知他們是否得到了鎖存器,使用入隊,請求者將被阻塞,直到實際地獲得它為止。它速度不如鎖存器,但是提供的功能在鎖存器功能之上。入隊可以在不同的等級獲得。

上面是概念,但是還是不能完全理解latch 和enquenue,不知道有沒有實踐的例子可以展示。或者論壇上已經有的很細的帖子,給個連線也可以。



 

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