consistent read(讀一致性)的通俗理解

tolywang發表於2005-04-14

首先介紹undo 中的簡單結構:
undo header--&gttransaction table--&gtundo entries(undo block)--&gt
undo entries包含的只有一個行改變的col值的undo,並不包含整個行的befor image。
KDO undo record:
KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x02000004.0005.0a
KDO Op code: URP xtype: XA bdba: 0x01c00007 hdba: 0x01c00006
itli: 1 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) flag: 0x2c
lock: 0 ckix: 0 ncol: 8 nnew: 2 size: -1
col 5: [ 3] c2 20 24
col 7: [ 2] c1 1f 





consistent read:
1.讀取資料塊,如果該塊在記憶體中,則增加一個克隆用於undo
2.讀取行頭:
tab 0, row 0, @0x1e4c
tl: 44 fb: --H-FL-- lb: 0x1 cc: 8
3.檢查lb是否這裡有一個itl:
Itl Xid Uba Flag
0x01 xid: 0x0003.000.00000010 uba: 0x02000004.0005.09 ----
4.如果有,則讀取這個itl的xid,xid=us#.slot#.wrap#

5.讀取交易表,如果這個交易已經提交(state=9表示提交)並且有了一scn小於當前查詢的system change number,
那麼clean out這個塊,繼續下一個塊(如果需要的話)並且返回第一步。(在每一個查詢的時候都將產生一個查詢
scn,在該scn一下的commit scn都認為對應的交易已經提交)
TRN TBL:
index state cflags wrap# uel scn dba nub
--------------------------------------------------------------------------
0x00 10 0xc0 0x0010 0x0000 0x0000.00075fec 0x02000004 0x00000001
0x01 9 0x00 0x000f 0x0002 0x0000.00075f77 0x00000000 0x00000000
6.如果沒有提交,那麼讀取最新改變的undo block根據transaction table中顯示的dba(該地址為undo entries中最
新改變的塊)
7.對比這個塊的交易號同交易表中的交易號。如果在undo block中的交易號不等於交易表中的交易號,那麼報告錯誤:
ORA-01555 “Snapshot Too Old.”.
xid: 0x0001.01d.000023a4 seq: 0x2a7 cnt: 0x3f irb: 0x3f icl: 0x0 flg: 0x0000

Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f68 0x02 0x1ee8 0x03 0x1e68 0x04 0x1de8 0x05 0x1d68
0x06 0x1cec 0x07 0x1c6c 0x08 0x1bec 0x09 0x1b6c 0x0a 0x1aec
0x0b 0x1a6c 0x0c 0x19f0 0x0d 0x1970 0x0e 0x18f0 0x0f 0x1874
0x10 0x17f8 0x11 0x1778 0x12 0x16f8 0x13 0x1678 0x14 0x15f8
8.如果這個塊的交易號等於交易表中的交易號,那麼從這個undo entry的頭開始,應用改變到塊上(該塊為在記憶體中
克隆的塊)
If the Transaction IDs are identical, make a copy of the data block in memory.
Starting with the head undo entry, apply the changes to the copied data block.
9.如果這個undo enties的尾巴上有其他的塊地址(因為一個交易可能佔用了好幾個undo塊),那麼將這個undo block
讀到記憶體中重複分析第七步和第八步。重複7和8步直到首先的record不在包含其他塊的地址。
10.當這裡不再有前一個資料塊的地址,那麼這個交易就完全被undo了。(因為undo 塊是從最後一個塊往前讀的,這
是為了保證在你讀的時候,最新改變的資料都能在undo中體現)
11.如果這個undo entry包含:
a):包含一個指向前一個交易undo block的地址,讀取這個交易的id號在這個前一個交易的undo block頭裡並讀取相應
的交易表entries,返回第五步。record紀錄也是從後往前讀的,因此有irb指定先讀取哪一個。
* Rec #0x1 slt: 0x00 objn: 48636(0x0000bdfc) objd: 49636 tblspc: 33(0x00000021)
* Layer: 11 (Row) opc: 1 rci 0x00
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00801b7c----------------------------------------&gt>>>>> 這裡有一個指標指向前一個undo block證明
這個undo chain上還有一些undo 塊。
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x00801b7c.02a7.3e
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x054016c1 hdba: 0x054016b9
itli: 1 ispac: 0 maxfr: 4863
tabn: 0 slot: 85(0x55) flag: 0x2c lock: 0 ckix: 0
ncol: 8 nnew: 5 size: 0
col 3: [ 3] c1 06 36
col 4: [ 3] c1 06 36
col 5: [ 1] 30
col 6: [ 2] c1 02
col 7: [ 6] c4 02 23 38 39 3d

*-----------------------------
* Rec #0x2 slt: 0x00 objn: 48636(0x0000bdfc) objd: 49636 tblspc: 33(0x00000021)
* Layer: 11 (Row) opc: 1 rci 0x01
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000------------------------------------------&gt>>>>>這裡的dba因為rci決定了它不是這個block的最
後一個record。
這是因為,如果你查詢的表有很多個交易在修改,那也需要讀取這些所有的這些交易所涉及的undo block,應用到重做
b):如果包含一個ITL紀錄,儲存這個ITL record到資料塊(cr block),然後返回第四步。
這裡比較迷惑,為什麼一個undo entries上還會包含一個ITL紀錄呢?哪裡來的?

----------------------

一句話: 一致讀就是session查詢所讀到的資料,是查詢開始的時間點之前已經提交的資料+當時session自己做出變更還沒有提交的資料。


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

相關文章