這篇文章主要描述oracle的復原機制,篇幅可能較長,因為對于oracle的復原機制來說,要讨論和描述的實在太多,隻能刷選自己認為最有意義的一部分進行深入研究和分享
一、我們來看一個DML語句的處理過程描述
update undotest set object_type=‘VIEW‘ where object_type=‘PROCEDURE‘;
檢查shared pool中是否存在相同的語句,如果存在,重用執行計劃,執行掃描運算,如果不存在,執行硬解析生成執行計劃
根據執行計劃中的掃描運算,檢查undotest表中的相關資料塊是否存在buffer cache中,如果不存在則讀取到記憶體中
檢查資料塊中符合object_type=‘PROCEDURE‘條件的記錄,如果沒有符合條件的行記錄,則結束語句,如果存在則進入下一步
以目前模式(current)擷取符合object_type=‘PROCEDURE‘條件的資料塊,準備進行更新
在復原表空間的相應復原段頭的事務表上配置設定事務槽,這個動作需要記錄redo日志
從復原段資料塊上建立object_type=‘PROCEDURE‘的前映像資料,這個動作也要記錄redo日志
修改object_type=‘VIEW‘ ,這是DML操作的資料變更,而需要記錄redo日志
使用者送出時,在redo日志中記錄送出資訊,将復原段頭上的事務表和復原段資料塊标記為非活動,清除修改資料塊上的事務資訊(也可能延遲清除)。同時必須確定整個事務的redp日志寫到磁盤上的日志檔案
注意:如果最後使用者復原了事務,oracle從復原段中将前映像資料提取出來,覆寫被更新的資料塊。這個復原動作本身也需要産生redo日志,是以,我們要知道復原的代價非常昂貴。
二、不同的DML操作,UNDO BLOCK中儲存的前映像内容
INSERT操作,UNDO中隻需要儲存插入記錄的rowid,如果需要回退,通過儲存的rowid進行删除即可(後面有案例)
UPDATE操作,UNDO中隻需要記錄被更新字段的舊值,如果需要回退,隻需要通過舊值覆寫更新後的值即可。
DELETE操作,UNDO中必須記錄整行的資料,如果需要回退,隻需要将這整行的資料重新插入至表中即可。
備注:本文章隻對INSERT操作,UNDO中儲存的内容進行測試,至于UPDATE、DELETE操作,實驗方法基本一緻,這裡就不再累贅
示例
<code></code>
1.開啟事務
SQL> create table tt as select object_name,object_id from dba_objects;
Table created.
SQL> insert into tt values(‘dddddd‘,1233456);
--執行insert操作
1 row created.
2.檢查事務資訊和其他一些事務資訊
SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments a where segment_name=‘TT‘;
HEADER_FILE HEADER_BLOCK
----------- ------------
4 810
SQL> SELECT
2 dbms_rowid.rowid_object(rowid) object_id,
3 dbms_rowid.rowid_relative_fno(rowid) REL_FNO,
4 dbms_rowid.rowid_block_number(rowid) BLOCKNO,
5 dbms_rowid.rowid_row_number(rowid) ROWNO,rowid,object_name
6 FROM tt WHERE object_name=‘dddddd‘;
OBJECT_ID REL_FNO BLOCKNO ROWNO ROWID
---------- ---------- ---------- ---------- ------------------
OBJECT_NAME
--------------------------------------------------------------------------------
73430 4 1150 0 AAAR7WAAEAAAAR+AAA
dddddd
SQL> select xidusn,xidslot,xidsqn,ubablk,ubafil,ubarec,to_char(start_scnw,‘xxxxxxxx‘)
start_scnw,
2 to_char(start_scnb,‘xxxxxxxx‘) start_scnb, start_scnb+start_scnw*power(2,32)
start_scn
3 from v$transaction;
XIDUSN XIDSLOT XIDSQN UBABLK UBAFIL UBAREC START_SCNW START_SCNB START_SCN
---------- ---------- ---------- ---------- ---------- ---------- -------------------- -------------------- ----------
5 21 960 1466 3 7
0 f5520 1004832
根據上面查詢擷取的事務資訊,dump insert事務undo 段頭和undo 塊
SQL> select name from v$rollname where usn=5;
NAME
------------------------------
_SYSSMU5_1527469038$
3.dump undo 段頭和undo 塊
SQL> oradebug setmypid;
Statement processed.
SQL> oradebug tracefile_name
/u01/oracle/diag/rdbms/test/test/trace/test_ora_604.trc
SQL> alter system dump undo header ‘_SYSSMU5_1527469038$‘;
System altered.
SQL> alter system dump datafile 3 block 1466;
UNDO BLK:
xid: 0x0005.015.000003c0 seq: 0x12c cnt: 0x7 irb: 0x7 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset
Rec Offset
---------------------------------------------------------------------------
0x01 0x1fa4 0x02 0x1f48 0x03 0x1ecc 0x04 0x1e70 0x05 0x1df4
0x06 0x1d90 0x07 0x1d20
*-----------------------------
* Rec #0x7 slt: 0x15 objn: 73430(0x00011ed6) objd: 73430 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x00
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
uba: 0x00c005b9.012c.2d ctl max scn: 0x0000.000f4ed4 prv tx scn: 0x0000.000f4ee0
txn start scn: scn: 0x0000.000f53a9 logon user: 85
prev brb: 12584373 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: DRP row dependencies Disabled --DRP操作完成復原
xtype: XA flags: 0x00000000 bdba: 0x0100047e hdba: 0x0100032a --bdba表示block address hdba 代表sgment header address
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) ---------這個slot表示這一行資料在資料塊中的行位址(行序列)
其中bdba表示file 4,block 1150 ,hdba表示file 4,block 810 與我們上面查詢出來的位址相符。
我們可以看到,undo塊中并沒有直接儲存rowid資訊,但是oracle完全可以根據上面的幾個資訊(bdba,slot,objd)定位復原時需要删除的具體資料,是以對于Insert操作,ORACLE隻需保留上述資訊,即可完成復原操作
三、基本概念和名詞解釋
UBA: Undo block address
RBA: Redo block address
Dba: Data block address
Rdba: Root dba
Xid: Transaction ID
ITL: Interested Transaction List 儲存在資料塊的頭部(事務資訊部分),包含XID,UBA,LCK,FLG等重要資訊
Transaction Identifiers
Transaction identifiers (XID) uniquely identify a transaction within the system; they are used within the Interested Transaction List (ITL) of the data block.
A transaction identifier consists of:
Undo segment number 即v$rollname中的usn
Transaction table slot number 對應復原段頭中復原事務表的第幾條記錄
Sequence number or wrap#
XID = usn# . slot# . wrap#
Undo Block Address
The undo block address (UBA) uniquely identifies the undo block for a given transaction; it is found within the ITL of the data block.
A UBA consists of:
Data block address (DBA) of the block 前映像undo 塊位址
The sequence number of the block 序列号
The record number within the block undo記錄的開始位址(針對該塊)
UBA = DBA. seq#. rec#
四、從一個DML語句開始研究,SESSION A執行下面的語句,更新完成後先不送出
(1)session A執行更新,更新兩條資料,如下
SQL> select * from undotest where object_type=‘PROCEDURE‘ and id in (4703,4704);
ID OBJECT_ID OBJECT_NAME OBJECT_TYPE
---------- ---------- -------------------- ---------------
4703 4771 SUBPTXT2 PROCEDURE
4704 4772 SUBPTXT PROCEDURE
SQL> update undotest set object_type=‘VIEW‘ where object_type=‘PROCEDURE‘ and id in (4703,4704);
2 rows updated.
SQL> select * from undotest where id in (4703,4704);
4703 4771 SUBPTXT2 VIEW
4704 4772 SUBPTXT VIEW
(2)查詢更新資料塊的資訊和事務資訊
sQL> SELECT
5 dbms_rowid.rowid_row_number(rowid) ROWNO,rowid,id,object_name,object_type
6 FROM dh.undotest WHERE id in (4703,4704);
OBJECT_ID REL_FNO BLOCKNO ROWNO ROWID ID OBJECT_NAME OBJECT_TYPE
---------- ---------- ---------- ---------- ------------------ ---------- -------------------- ---------------
73424 4 195 70 AAAR7QAAEAAAADDABG 4703 SUBPTXT2
VIEW
73424 4 195 71 AAAR7QAAEAAAADDABH 4704 SUBPTXT
VIEW
19 0 4 258 5 2 0 0 0
SQL> select name from v$rollname where usn=19;
_SYSSMU19$
(3)重新整理記憶體,dump資料塊,undo 段頭,undo block,如下
SQL> alter system flush buffer_cache;
SQL> oradebug
SQL> oradebug setmypid
/u01/oracle/diag/rdbms/test/test/trace/test_ora_902.trc
SQL> alter system dump datafile 4 block 195;
SQL> alter system dump undo header ‘_SYSSMU19$‘;
SQL> alter system dump datafile 5 block 258;
(4)分析資料塊dump檔案
Block header dump: 0x010000c3
Object id on Block? Y
seg/obj: 0x11ed0 csc: 0x00.f2e95 itc: 3 flg: E typ: 1 - DATA
brn: 1 bdba: 0x10000b8 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.000f2e95
0x02 0x0013.000.00000004 0x01400102.0001.02 ----
2 fsc 0x000a.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
uba中undo record參數為2,即這個事務在這個資料塊上的變更(修改)産生的undo記錄(變更舊值記錄)在對應的undo資料塊中的開始位址(開始偏移量)
bdba: 0x010000c3
data_block_dump,data header at 0x2b0a86e2da7c
.....省略一部分..........
tab 0, row 70, @0x45f
tl: 25 fb: --H-FL-- lb:
0x2 cc: 4 ---這一行資料被鎖定,鎖定該行資料的事務為ITL事務槽中的第二個事務。
col 0: [ 3] c2 30 04
col 1: [ 3] c2 30 48
col 2: [ 8] 53 55 42 50 54 58 54 32
col 3: [ 4] 56 49 45 57
tab 0, row 71, @0x447
tl: 24 fb: --H-FL-- lb:
col 0: [ 3] c2 30 05
col 1: [ 3] c2 30 49
col 2: [ 7] 53 55 42 50 54 58 54
.........省略trace 檔案中後面的輸出.............
(5)分析undo 段頭dump檔案
********************************************************************************
Undo Segment: _SYSSMU19$ (19)
Extent Control Header
-----------------------------------------------------------------
............省略中間一部分................
Retention Table
-----------------------------------------------------------
Extent Number:0 Commit Time: 0
Extent Number:1 Commit Time: 0
TRN CTL:: seq: 0x0001 chd: 0x0001 ctl: 0x0021 inc: 0x00000000 nfb: 0x0000
mgc: 0xb000 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
uba: 0x01400102.0001.01 scn: 0x0000.000e61e6
這個uba經過測試驗證,為事務表中最後(最新)一個事務的對應的undo block上的第一個undo record,即當這個復原段頭存在多個事務時,這個uba表示最新的事務的uba位址,這個位址在整個事務的周期内不發生改變(除非這個復原段頭上又配置設定了一個新的事務表),是以,這個位址指向的是事務使用的第一個undo block
Version: 0x01
FREE BLOCK POOL::
uba: 0x00000000.0000.00 ext: 0x0 spc: 0x0
TRN TBL::
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 10 0x80 0x0004 0x0000 0x0000.00000000 0x01400102 0x0000.000.00000000 0x00000001 0x00000000 0
0x01 9 0x00 0x0003 0x0002 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x02 9 0x00 0x0003 0x0003 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x03 9 0x00 0x0003 0x0004 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x1f 9 0x00 0x0003 0x0020 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x20 9 0x00 0x0003 0x0021 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x21 9 0x00 0x0003 0xffff 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
回顧我們開始時查詢的事務XID資訊:xidslot=0(這個事務占用UNDO事務表中第幾号事務槽) and xidseq=4 與上面标紅的0x00、state=10(代表事務狀态為活動)、wrap#=4 完全相符合。
其中dba列值表示包含這個事務的前映像的undo塊位址(事務最後更新的前映像UNDO位址),與ITL事務槽中的uba位址一緻 ,即file 5,block 258(可使用dbms_utility.data_block_address_file函數轉換)
(6)分析UNDO block dump檔案
xid: 0x0013.000.00000004 seq: 0x1 cnt: 0x2 irb: 0x2 icl: 0x0 flg: 0x0000
Rec Offset --undo資訊偏移量,在undo塊中偏移
0x01 0x1f58 0x02 0x1ef4 --目前undo塊中的最後一個偏移位址即Ox02 與irb一緻
其中irb:0x2 表示未送出事務最新(最後執行的)變更對應的undo資料塊中的UNDO record位址,如果開始rollback,這是復原的起點。
* Rec #0x1 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004) --根據Rec
#0x2 中的rci記錄找到#0x1
* Layer: 11 (Row) opc: 1 rci 0x00 --rci指針為0,表示這是事務復原過程中的最後一條記錄
uba: 0x00000000.0000.00 ctl max scn: 0x0000.000e61e6 prv tx scn: 0x0000.000e61e6
txn start scn: scn: 0x0000.00000000 logon user: 85
prev brb: 0 prev bcl: 0
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000c3 hdba: 0x010000aa
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 70(0x46) flag: 0x2c lock: 0 ckix: 80 --slot表示更新資料的行序列值(rowno),用于定位具體的資料,與我們查詢的一緻
ncol: 4 nnew: 1 size: 5
col 3: [ 9] 50 52 4f 43 45 44 55 52 45 ---轉換為字元為‘PROCEDURE’,與我們更新前資料一緻
轉換方法:
SELECT utl_raw.cast_to_varchar2(replace(‘50 52 4f 43 45 44 55 52 45‘,‘ ‘)) value FROM dual;
* Rec #0x2 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x01 --指向REC#
0x01,即上一個偏移量
Undo type: Regular undo Last buffer split: No
rdba: 0x00000000
op: 0x02 ver: 0x01
op: C uba: 0x01400102.0001.01 --這個uba表示undo chain tx table,即同一update語句中的undo chain位址,這裡為1,指向第一個偏移量。一個事務中的不同DML語句,無法通過該參數連接配接起來(形成undo
chain),因為該參數,不能跨越DML語句。
tabn: 0 slot: 71(0x47) flag: 0x2c lock: 0 ckix: 80 --slot表示更新資料的行序列值(rowno),用于定位具體的資料,與我們查詢的一緻
col 3: [ 9] 50 52 4f 43 45 44 55 52 45 --與上面描述的一樣,轉換為字元為‘PROCEDURE’,與我們更新前資料一緻
Rec #0x2 這條undo record中還記錄了一個rci參數,表示undo chain,同一個事務中的多次修改,根據這個chain連接配接起來。
目前rci參數值為0x01,即指向該undo塊中的第一個undo record,找到Rec #0x01 undo record後,檢查發現确實是我們這個UPDATE語句中的被更新的另一條資料。
五、在SESSION A中繼續進行更新操作,進一步研究
(1)更新兩條資料,同時查詢基本的事務資訊和資料塊資訊
SQL> update undotest set object_type=‘VIEW‘ where object_type=‘PROCEDURE‘ and id in (11504,11505);
6 FROM undotest WHERE id in (11504,11505);
73424 4 236 41 AAAR7QAAEAAAADsAAp 11504 DBMS_FEATURE_RMAN_BZ PROCEDURE
IP2
73424 4 236 42 AAAR7QAAEAAAADsAAq 11505 DBMS_FEATURE_RMAN_BA PROCEDURE
SIC
19 0 4 258 5 4 0 0 0
SQL> alter system dump datafile 4 block 236;
(2)分析資料塊dump檔案
可以看到,SESSION A事務中第一個update語句修改的資料塊(datafile 4 block 195)沒有任何改變
data_block_dump,data header at 0x2b5f5d4e6a7c
事務中第二個update語句修改的資料塊(4,236)上的事務資訊與我們查詢的一緻,如下
Block header dump: 0x010000ec
brn: 0 bdba: 0x10000e8 ver: 0x01 opc: 0
0x02 0x0013.000.00000004 0x01400102.0001.04 ---- 2 fsc 0x000a.00000000
bdba: 0x010000ec
..........省略一部分..........
tab 0, row 41, @0x38f
tl: 42 fb: --H-FL-- lb:
0x2 cc: 4
col 0: [ 4] c3 02 10 05
col 1: [ 4] c3 02 13 03
col 2: [23]
44 42 4d 53 5f 46 45 41 54 55 52 45 5f 52 4d 41 4e 5f 42 5a 49 50 32
tab 0, row 42, @0x365
0x2 cc: 4
col 0: [ 4] c3 02 10 06
col 1: [ 4] c3 02 13 04
(3)分析undo 段頭dump檔案
...............省略一部分..............
mgc: 0xb000 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
uba: 0x01400102.0001.01 scn: 0x0000.000e61e6
FREE BLOCK POOL::
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 10 0x80 0x0004 0x0000 0x0000.00000000 0x01400102 0x0000.000.00000000 0x00000001 0x00000000 0
0x01 9 0x00 0x0003 0x0002 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x02 9 0x00 0x0003 0x0003 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x03 9 0x00 0x0003 0x0004 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x04 9 0x00 0x0003 0x0005 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
0x05 9 0x00 0x0003 0x0006 0x0000.000e61e6 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 0
undo段頭上的事務表沒有發生改變
(4)分析undo block dump檔案
xid: 0x0013.000.00000004 seq: 0x1 cnt: 0x4 irb: 0x4 icl: 0x0 flg: 0x0000
0x01 0x1f58 0x02 0x1ef4 0x03 0x1e98 0x04 0x1e34
* Rec #0x1 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
tabn: 0 slot: 70(0x46) flag: 0x2c lock: 0 ckix: 80
col 3: [ 9] 50 52 4f 43 45 44 55 52 45
* Layer: 11 (Row) opc: 1 rci 0x01
op: C uba: 0x01400102.0001.01
tabn: 0 slot: 71(0x47) flag: 0x2c lock: 0 ckix: 80
* Rec #0x3 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x02
xtype: XA flags: 0x00000000 bdba: 0x010000ec hdba: 0x010000aa --bdba:4,236;即我們update語句修改的資料塊,與查詢出來的資訊一緻
tabn: 0 slot: 41(0x29) flag: 0x2c lock: 0 ckix: 0
* Rec #0x4 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x03
op: C uba: 0x01400102.0001.03
--新發起的update語句,uba參數值與第一條不同(Rec #0x2 undo record記錄),事務中的每個DML語句儲存自己的uba,用于語句復原
xtype: XA flags: 0x00000000 bdba: 0x010000ec hdba: 0x010000aa --bdba:4,236;即我們update語句修改的資料塊,與查詢出來的資訊一緻
tabn: 0 slot: 42(0x2a) flag: 0x2c lock: 0 ckix: 0
End dump data blocks tsn: 6 file#: 5 minblk 258 maxblk 258
六、再次在SESSION A中進行更新,當事務使用的undo block超過一個1個時,分析整個事務的undo record是怎麼串聯起來。
(1)在session A 中繼續更新undotest,并檢視事務資訊
SQL> update undotest set object_type=‘VIEW‘ where object_type=‘TABLE‘ and rownum<99;
98 rows updated.
19 0 4 259 5 20
0 0 0
UBABLK之前為258,現在查詢出來為259,是以可以肯定目前事務使用已經超過一個UNDO block。
(2)DUMP 段頭,undo 塊,data block,這裡就不再列舉出來
SQL> alter system dump datafile 5 block 259;
(3)分析dump 出來的trace 檔案
Extent Header:: spare1: 0 spare2: 0 #extents: 2 #blocks: 15
last map 0x00000000 #maps: 0 offset: 4080
Highwater:: 0x01400103 ext#: 0 blk#: 2 ext size: 7
#blocks in seg. hdr‘s freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 2 obj#: 0 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x01400101 length: 7
0x01400108 length: 8
Retention Table
-----------------------------------------------------------
Extent Number:0 Commit Time: 0
Extent Number:1 Commit Time: 0
uba: 0x01400102.0001.01 scn: 0x0000.000e61e6
0x00 10 0x80 0x0004 0x0000 0x0000.00000000 0x01400103 0x0000.000.00000000 0x00000002 0x00000000 0
可以看到dba的位址已經發生改變,指向最新使用的undo block位址,即datafile 5,block 259
(4)分析undo block trace
1.下面是undo block datafile 5 block 259的dump trace檔案
xid: 0x0013.000.00000004 seq: 0x1 cnt: 0x14 irb: 0x14 icl: 0x0 flg: 0x0000
0x01 0x1f88 0x02 0x1f28 0x03 0x1ec8 0x04 0x1e68 0x05 0x1e08
0x06 0x1da8 0x07 0x1d48 0x08 0x1ce8 0x09 0x1c88 0x0a 0x1c28
0x0b 0x1bc8 0x0c 0x1b68 0x0d 0x1b08 0x0e 0x1aa8 0x0f 0x1a48
0x10 0x19e8 0x11 0x1988 0x12 0x1928 0x13 0x18c8 0x14 0x1868
rdba: 0x01400102
op: C uba: 0x01400102.0001.52 --當一個事務使用多個undo
block時,事務使用的undo塊順序,是根據這個參數串聯起來,即undo chain
xtype: XA flags: 0x00000000 bdba: 0x010000ab hdba: 0x010000aa
tabn: 0 slot: 201(0xc9) flag: 0x2c lock: 0 ckix: 80
ncol: 4 nnew: 1 size: 1
col 3: [ 5] 54 41 42 4c 45
op: C uba: 0x01400103.0001.01
tabn: 0 slot: 205(0xcd) flag: 0x2c lock: 0 ckix: 80
.................省略一部分................
* Rec #0x13 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x12
op: C uba: 0x01400103.0001.12
tabn: 0 slot: 239(0xef) flag: 0x2c lock: 0 ckix: 80
* Rec #0x14 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
--這個對應irb參數:0x14,也對應ITL中的UBA第三個參數:undo record的開始位址。
* Layer: 11 (Row) opc: 1 rci 0x13
op: C uba: 0x01400103.0001.13
tabn: 0 slot: 241(0xf1) flag: 0x2c lock: 0 ckix: 80
---轉化為字元,可以發現與我們更新的舊值相同。符合我們的語氣
End dump data blocks tsn: 6 file#: 5 minblk 259 maxblk 259
2.下面是undo block datafile 5 block 258(事務使用的第一個undo block)的dump trace檔案
我們可以看到如下内容(省略無用資訊),注意undo record中的uba參數
op: C uba: 0x01400102.0001.03
xtype: XA flags: 0x00000000 bdba: 0x010000ec hdba: 0x010000aa
* Rec #0x5 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x04
op: Z
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 80
Rec #0x5 記錄時我們最後一個update語句使用的第一個undo記錄,我們可以看到,該記錄中并沒有儲存事務中上一條語句使用的uba,是以我們可以知道,undo record中的uba參數無法跨越語句,隻能在單個語句中将undo記錄串聯起來
* Rec #0x6 slt: 0x00 objn: 73424(0x00011ed0) objd: 73424 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x05
op: C uba: 0x01400102.0001.05
tabn: 0 slot: 2(0x2) flag: 0x2c lock: 0 ckix: 80
七、一些結論
UNDO段頭中TRN CTL的uba參數:UNDO段頭的事務表中最後(最新)一個事務的對應的undo
block上的第一個undo record,即當這個復原段頭存在多個事務時,這個uba表示最新的事務的uba位址,這個位址在整個事務的周期内不發生改變(除非這個復原段頭上又配置設定了一個新的事務表),是以,這個位址指向的是事務使用的第一個undo block;
UNDO BLOCK中undo record記錄中的uba參數:如果事務中的一個DML語句需要使用多個undo record,則這個參數指向的是前一個undo record的記錄,通過這個參數可以形成同一個DML語句的undo
chain tx table。但是一個事務中的不同DML語句,無法通過該參數連接配接起來(形成undo chain),因為該參數,不能跨越DML語句。當一個事務使用多個undo
block時,事務使用的undo塊順序,是根據這個參數串聯起來;
資料塊頭的ITL中的uba參數:指向事務在這個資料塊上的變更(修改)所使用的undo塊中的最後一個undo
record偏移量位址,針對這個資料塊修改,這個uba是復原的起點;
UNDO record中的bdba表示block address ,hdba表示 segment header address
undo塊中不會直接儲存rowid資訊,但是oracle完全可以undo record中幾個資訊(bdba,slot,objd),生成資料變更是的具體位址(rowid);
一個事務所使用的undo記錄順序是通過undo record中的uba參數、rci參數,undo塊上的irb,itl中的uba共同起作用來串聯變更的順序,事務的復原也是根據這個undo chain按順序完成。其中最關鍵的兩個參數:undo
record中的uba 形成單個dml語句的undo chain,rci參數可以跨越DML語句,可以指向事務中前一個dml語句使用的undo
record;
最後部分其實有幾張原理圖想要附上,供大家更清晰的了解,不過不知道怎麼上傳到部落格,有需要的朋友直接給我留言吧