關於事務對資料塊的操作過程的分析和試驗(2)(轉)

flysky0814發表於2007-12-04

快速提交

當一個事物訪問一個資料塊時,它會佔用資料塊Itl中的一個條目,記錄下事務IDXid)、該事務對該資料塊操作時使用的回滾塊地址(Uba)和在該資料塊上產生的行級鎖的數量,並在對應資料行上打上行鎖標誌,與Itl對應。當提交時,設定Itl中的事物標誌為U,並寫入一個快速提交SCNFsc),但並不清除鎖標誌。這就是快速提交。

看下面的一個試驗。

先對資料塊進行修改,然後dump出資料塊:

SQL> conn demo/demo
Connected.
SQL>
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> update t_multiver set b=115 where a=1;
 
1 row updated.
 
SQL>
SQL> commit;
 
Commit complete.
 
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> alter system dump datafile 5 block 50959;
 
System altered.

看看dump出來的內容:

Block header dump:  0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c  csc: 0x00.a4a48c25  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x140c709 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000f.006.00000a14  0x02c00050.0376.10  C---    0  scn 0x0000.a4a39ef0
0x02   0x0013.003.00000a58  0x02c0008f.039a.0a  --U-    1  fsc 0x0000.a4a48c26
 
... ...
 
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2]  c1 02
col  1: [ 3]  c2 02 10
tab 0, row 1, @0x1f4a
tl: 10 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 03
col  1: [ 3]  c2 03 17
... ...

可以看到,事務在Itl中記錄下了XidUbaFlagU)、鎖、Fsc;並且記錄上的鎖標誌沒有清除。

延遲塊清除

從上面內容可以知道,事務在資料塊上作的操作並沒有清除產生的鎖標誌和其他標誌(檢測鎖衝突),這些標誌的清除需要留到下一個訪問該資料塊的事務去做清除。下一個訪問到該資料塊的事務會先檢查自己要訪問的資料行上有沒有鎖,如果都沒有,就繼續作自己的操作,如果記錄上有鎖,就做一次清除(Cleanout)。看下面的試驗:

這個試驗是接著上面的,但是這修改的是資料塊中的另外一條記錄:

SQL> conn demo/demo
Connected.
SQL>
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> update t_multiver set b=115 where a=2;
 
1 row updated.
 
SQL>
SQL> commit;
 
Commit complete.
 
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> alter system dump datafile 5 block 50959;
 
System altered.

看看dump出的資料塊:

Block header dump:  0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c  csc: 0x00.a4a48c25  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x140c709 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000e.008.000007f2  0x02c0003f.02ca.24  --U-    1  fsc 0x0000.a4a48df3
0x02   0x0013.003.00000a58  0x02c0008f.039a.0a  --U-    1  fsc 0x0000.a4a48c26
 
... ...
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2]  c1 02
col  1: [ 3]  c2 02 10
tab 0, row 1, @0x1f4a
tl: 10 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 03
col  1: [ 3]  c2 02 10
tab 0, row 2, @0x1f54
... ...

這個事務並沒有清除上一事務的鎖標誌,並且還產生了自己的鎖標誌,因為他們之間沒有鎖衝突。從這個試驗,我們還可以得出以下結論:事務是按照資料塊中的記錄處理的,不是按照Itl中的條目處理的。

而塊清除可以分為兩種情況。一種是針對快速提交的。如果快速提交後,髒資料回寫到磁碟上,此時資料塊的鎖標誌還沒有清除,後面訪問該資料塊的事務(只是產生資料更新的事務,不包括讀事務),會先清除(Cleanout)上一個快速提交事務留下的鎖標誌(同時也是做鎖判斷),然後開始事務操作。看看試驗:

這裡繼續接著上面的試驗,再對資料塊做一次修改操作,並且修改的記錄上已經有鎖標誌,看看後面事務是否清除了前面事務的標誌:

SQL> conn demo/demo
Connected.
SQL>
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> update t_multiver set b=115 where a=2;
 
1 row updated.
 
SQL>
SQL> commit;
 
Commit complete.
 
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> alter system dump datafile 5 block 50959;
 
System altered.

看看dump出的內容:

Block header dump:  0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c  csc: 0x00.a4a4918e  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x140c709 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000e.008.000007f2  0x02c0003f.02ca.24  C---    0  scn 0x0000.a4a48df3
0x02   0x0014.007.000007a2  0x02c000a5.02ab.23  --U-    1  fsc 0x0000.a4a4918f
 
... ...
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 02
col  1: [ 3]  c2 02 10
tab 0, row 1, @0x1f4a
tl: 10 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2]  c1 03
col  1: [ 3]  c2 02 10
tab 0, row 2, @0x1f54
... ...

可以看到,這個事務對前面的事務作了一次Cleanout,所有相關標誌都被修改。

另一種情況是,事務開始後,會給資料塊打上鎖標誌。但是事務標誌和SCN號是在事務提交後寫入的,如果在事務提交前,DBWn程式已經將資料回寫到磁碟,那麼資料塊上就沒有這些資訊。後面訪問該資料塊的事務(包括所有讀寫事務)需要先根據XidUba從回滾段的事務資訊表中獲取到這些資訊,然後作一次Cleanout。再看試驗:

事務提交前回寫資料塊:

SQL> update t_multiver set b=115 where a=1;
 
1 row updated.
 
SQL>
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> commit;
 
Commit complete.
 
SQL>
SQL> alter system dump datafile 5 block 50959;
 
System altered.

看看資料塊內容:

Block header dump:  0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c  csc: 0x00.a4a49c85  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x140c709 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000e.00a.000007f5  0x02c0003f.02cc.1e  ----    1  fsc 0x0000.00000000
0x02   0x000d.028.00000a2b  0x02c00035.039b.03  C---    0  scn 0x0000.a4a49c71
 
... ...
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 02
col  1: [ 3]  c2 02 10
tab 0, row 1, @0x1f4a
... ...
 

可以看到,Flagscn沒有被記錄,而XidUba和鎖標誌都已經被記錄。這裡還可以推斷出:XidUba在事務開始,獲取到空閒Itl後是最先被記錄的;鎖標誌是針對記錄一一被記錄的;FlagScn是事務提交後被記錄的。

看看這種情況下,是如何做Cleanout的。我們這不再選用更新事務,而是做一個讀操作:

SQL> alter system dump datafile 5 block 50959;
 
System altered.
 
SQL> select * from t_multiver;
 
         A          B
---------- ----------
         1        115
         2        115
         3        222
 
SQL>
SQL> alter system dump datafile 5 block 50959;
 
System altered.

Dump內容:

Block header dump:  0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c  csc: 0x00.a4a49e6b  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x140c709 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000e.00a.000007f5  0x02c0003f.02cc.1e  C---    0  scn 0x0000.a4a49c89
0x02   0x000d.028.00000a2b  0x02c00035.039b.03  C---    0  scn 0x0000.a4a49c71
 
... ...
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x0  cc: 2
col  0: [ 2]  c1 02
col  1: [ 3]  c2 02 10
tab 0, row 1, @0x1f4a
... ...

可以看到,前面事務的標誌都被Cleanout了。

[@more@]

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

相關文章