修改的數據沒有提交之前,其他會話是看不到被修改的數據,被修改之前的數據會存放在UNDO裏面,那麼ORACLE是通過什麼的方式找到存放在UNDO裏面的數據呢?下面通過具體例子來說明
首先開啓兩個會話,其中第一個會話只更新數據(分兩種情況,一、只更新一次, 二、連續更新多次)。第二個會話查詢會話一更新的數據,查看是否能查到。
1、----創建測試表並插入數據-----
SQL> create table my_test(id int, name varchar2(20));
Table created.
SQL> insert into my_test values (1,'a');
1 row created.
SQL> commit;
Commit complete.
SQL>
會話1更新數據不提交
SQL>
SQL> update my_test set id = 2 ;
1 row updated.
SQL> @pid
SID SERIAL# PID SPID
---------- ---------- ---------- ------------------------
125 5 19 26271
SQL> select * from my_test;
ID NAME
---------- --------------------
2 a
SQL>
2、會話2查詢my_test表的數據
SQL> @pid
SID SERIAL# PID SPID
---------- ---------- ---------- ------------------------
150 15 31 26455
SQL> select * from my_test;
ID NAME
---------- --------------------
1 a
SQL>
可以看到會話2(sid = 150)查看到的ID=1, 會話1(sid = 125)已經把ID更新爲2,但是並沒有提交。所以會話2看到ID還是更新之前的數據。ORACLE是通過UNDO的機制,把更新之後的數據寫入UNDO。那麼會話2是怎麼通過UNDO找到會話1更新之前的數據呢?
3、查找會話1產生的UNDO數據有兩種方式,由於我這是測試庫,庫中只有會話1更新了my_test表沒有提交,不存在其他未提交事務。
3.1、直接通過UNDO的相關視圖查找會話1的產生的UNDO數據。
SQL> select addr, XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBASQN,UBAREC from v$transaction;
ADDR XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBASQN UBAREC
---------------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007CB381A8 26 30 12516 19 134 1661 6
SQL>
其中
XIDUSN 回滾段號
XIDSLOT 槽號
XIDSQN 覆蓋次數
UBAFIL 回滾文件號
UBABLK 回滾塊號
UBAREC 代表REC記錄號
首先通過UNDO的文件號和塊號查看UNDO的數據
SQL> alter system dump datafile 19 block 134;
System altered.
SQL> col VALUE for a60
SQL> select value from v$diag_info where name = 'Default Trace File';
VALUE
------------------------------------------------------------
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_26545.trc
SQL>
Block dump from disk:
buffer tsn: 11 rdba: 0x04c00086 (19/134) <====19號文件134塊
scn: 0x0000.027f8d4f seq: 0x01 flg: 0x04 tail: 0x8d4f0201
frmt: 0x02 chkval: 0x7538 type: 0x02=KTU UNDO BLOCK <=====塊類型是UNDO
Hex dump of block: st=0, typ_found=1
********************************************************************************
UNDO BLK:
xid: 0x001a.01e.000030e4 seq: 0x67d cnt: 0x6 irb: 0x6 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f40 0x02 0x1e98 0x03 0x1de0 0x04 0x1d38 0x05 0x1c90
0x06 0x1bf0
其中
xid 0x001a.01e.000030e4分爲三個部分,第一部分代表XIDUSN=0x001a轉換成10進製爲26。
第二部分代表XIDSLOT=01e轉換成10進製爲30, 第三部分爲XIDSQN=30e4轉換成10進製爲12516
可以看到這三個部分和v$transaction查看到的回滾段信息是一致的。
seq 對應v$transaction裏面的UBASQN,0x67d轉換成10進製爲1661
irb代表該undo塊上面最新的事務記錄號0x6和v$transaction裏面的UBAREC=6對應。
查看rec# = 0x6的undo數據
*-----------------------------
* Rec #0x6 slt: 0x1e objn: 136312(0x00021478) objd: 136312 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x00 <======rci=0x00代表上面沒有更新的回滾數據
Undo type: Regular undo Begin trans Last buffer split: No (因爲會話1只更新了一次)
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x04c00085.067d.30 ctl max scn: 0x0000.027f8ac6 prv tx scn: 0x0000.027f8acf
txn start scn: scn: 0x0000.027f8d4f logon user: 0
prev brb: 79691908 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled <======URP 代表更新數據
xtype: XA flags: 0x00000000 bdba: 0x00420bb9 hdba: 0x00420bb8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 0
ncol: 2 nnew: 1 size: 0
col 0: [ 2] c1 02 <======更新之前的數據爲 c102
End dump data blocks tsn: 11 file#: 19 minblk 134 maxblk 134
通過Rec #0x6上面的數據可以看到該UNDO塊上面的保存的數據爲c102,把c102轉換成10進制如下
SQL> select utl_raw.cast_to_number('c102') from dual;
UTL_RAW.CAST_TO_NUMBER('C102')
------------------------------
1
SQL>
可以看到undo塊上面保存的是會話1更新之前的數據。上面是通過v$transaction視圖中的UBAFIL、UBABLK確定的文件號和塊號,然後再通過dump該文件號和塊號得到了會話1更新之前的數據。同樣也可以通過v$transaction中的XIDUSN、XIDSLOT、XIDSQN確定回滾塊的信息
通過v$transaction視圖查看到XIDUSN=26,代表着回滾段爲26號,把XIDUSN=26的回滾段dump出來
SQL> select usn,name from v$rollname where usn = 26;
USN NAME
---------- ------------------------------
26 _SYSSMU26_2510430623$
SQL>
SQL> alter system dump undo header "_SYSSMU26_2510430623$";
System altered.
SQL>
SQL> col VALUE for a60
SQL> select value from v$diag_info where name = 'Default Trace File';
VALUE
------------------------------------------------------------
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_26698.trc
SQL>
查看/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_26698.trc內容
********************************************************************************
Undo Segment: _SYSSMU26_2510430623$ (26)
********************************************************************************
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 3 #blocks: 143
last map 0x00000000 #maps: 0 offset: 4080
Highwater:: 0x04c00086 ext#: 2 blk#: 6 ext size: 128
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 2
Unlocked
Map Header:: next 0x00000000 #extents: 3 obj#: 0 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x028000f1 length: 7
0x028000f8 length: 8
0x04c00080 length: 128
TRN TBL::
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 9 0x00 0x30e0 0x0006 0x0000.027f8c6c 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x01 9 0x00 0x30e6 0x001d 0x0000.027f8cf0 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x02 9 0x00 0x30df 0x001a 0x0000.027f8c06 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x03 9 0x00 0x30eb 0x001b 0x0000.027f8c1c 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x04 9 0x00 0x30e3 0xffff 0x0000.027f8d3b 0x04c00086 0x0000.000.00000000 0x00000002 0x00000000 1582741174
0x05 9 0x00 0x30e5 0x0021 0x0000.027f8b5d 0x04c00081 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x06 9 0x00 0x30e5 0x0017 0x0000.027f8c7b 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x07 9 0x00 0x30e5 0x0005 0x0000.027f8b4c 0x04c00081 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x08 9 0x00 0x30e7 0x0011 0x0000.027f8c9c 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x09 9 0x00 0x30e1 0x0001 0x0000.027f8ccf 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0a 9 0x00 0x30e7 0x0016 0x0000.027f8b1b 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0b 9 0x00 0x30ea 0x000a 0x0000.027f8b05 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0c 9 0x00 0x30e5 0x000d 0x0000.027f8be4 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0d 9 0x00 0x30ed 0x000e 0x0000.027f8bf2 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0e 9 0x00 0x30df 0x0002 0x0000.027f8bfa 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x0f 9 0x00 0x30e7 0x0012 0x0000.027f8b86 0x04c00081 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x10 9 0x00 0x30e4 0x001f 0x0000.027f8af0 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x11 9 0x00 0x30e6 0x0009 0x0000.027f8ca4 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x12 9 0x00 0x30e3 0x0014 0x0000.027f8b93 0x04c00085 0x0000.000.00000000 0x00000002 0x00000000 1582741174
0x13 9 0x00 0x30e7 0x001c 0x0000.027f8c47 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x14 9 0x00 0x30e4 0x0018 0x0000.027f8ba4 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x15 9 0x00 0x30e2 0x0010 0x0000.027f8ae4 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x16 9 0x00 0x30e7 0x0019 0x0000.027f8b33 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x17 9 0x00 0x30e3 0x0008 0x0000.027f8c8c 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x18 9 0x00 0x30e7 0x000c 0x0000.027f8bbf 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x19 9 0x00 0x30eb 0x0007 0x0000.027f8b46 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x1a 9 0x00 0x30ea 0x0003 0x0000.027f8c0f 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x1b 9 0x00 0x30dc 0x0020 0x0000.027f8c2e 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x1c 9 0x00 0x30e7 0x0000 0x0000.027f8c5a 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x1d 9 0x00 0x30e2 0x0004 0x0000.027f8d16 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
==>0x1e 10 0x80 0x30e4 0x0002 0x0000.027f8d4f 0x04c00086 0x0000.000.00000000 0x00000001 0x00000000 0
0x1f 9 0x00 0x30e7 0x000b 0x0000.027f8af8 0x04c00084 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x20 9 0x00 0x30e3 0x0013 0x0000.027f8c40 0x04c00085 0x0000.000.00000000 0x00000001 0x00000000 1582741174
0x21 9 0x00 0x30de 0x000f 0x0000.027f8b65 0x04c00081 0x0000.000.00000000 0x00000001 0x00000000 1582741174
查看回滾段的RN TBL::信息,發現index=0x1e這行的state=10,10代表是活動事物。dba(data block address)爲0x04c00086,意思就是該事物對應的undo數據在0x4c00086上面。把0x4c00086轉換成文件號和塊號,如下:
SQL> select to_number('4c00086','xxxxxxxx') from dual;
TO_NUMBER('4C00086','XXXXXXXX')
-------------------------------
79691910
SQL> select dbms_utility.data_block_address_file(79691910) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(79691910)
----------------------------------------------
19
SQL> select dbms_utility.data_block_address_block(79691910) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(79691910)
-----------------------------------------------
134
SQL>
可以看到dba轉換成10文件號和塊號之後正是v$transaction中的DBAFIL、DBABLK。找到undo的文件號和塊號之後就可以
按照上面的方法找到undo塊上面對應的會話1更新前的數據
wrap#=0x30e3代表v$transaction裏面的XIDSQN,轉換成10進製爲12515。
3.2 方法一是直接通過v$transaction視圖裏面的數據來查找會話1更新之前的undo數據。但是會話2查詢my_test數據時不會通過 v$transaction裏面去查找undo數據。會話2也不會知道v$transaction裏面哪行數據對應my_test表的前鏡像。
會話2查詢數據的過程如下:
查詢my_test表時,首先找到my_test表對應的數據塊
SQL> select dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) from my_test;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------ ------------------------------------
1 134073
SQL>
因爲會話1更新了1號文件134073的塊,所以塊上面會有事物信息,查看上面事物信息
SQL>
SQL> alter system dump datafile 1 block 134073;
System altered.
SQL> select value from v$diag_info where name = 'Default Trace File';
VALUE
--------------------------------------------------------------------------------
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_26859.trc
SQL>
查看/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_26859.trc內容
Block dump from disk:
buffer tsn: 0 rdba: 0x00420bb9 (1/134073)
scn: 0x0000.027f8d66 seq: 0x01 flg: 0x04 tail: 0x8d660601
frmt: 0x02 chkval: 0xa68e type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007FA900615A00 to 0x00007FA900617A00
7FA9006179F0 00000000 0202022C 610103C1 8D660601 [....,......a..f.]
Block header dump: 0x00420bb9
Object id on Block? Y
seg/obj: 0x21478 csc: 0x00.27f8d66 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x001a.000.000030df 0x04c00084.067d.03 C--- 0 scn 0x0000.027f8a36
0x02 0x001a.01e.000030e4 0x04c00086.067d.06 ---- 1 fsc 0x0000.00000000
可以看到Itl =0x02上面的Lck=1。說明該塊上面有其他會話修改,並且沒有提交。會話2訪問該塊的時候只能通過UBA(undo block address)的UNDO數據找到舊鏡像。其中Xid =0x001a.01e.000030e4就是對應v$transaction的XIDUSN、XIDSLOT、XIDSQN。轉換成10進制分別爲第一部分代表XIDUSN=0x001a轉換成10進製爲26。第二部分代表XIDSLOT=01e轉換成10進製爲30, 第三部分爲XIDSQN=30e4轉換成10進製爲12516。和v$transaction裏面看到的一樣UBA的數據爲0x04c00086.067d.06其中第一部分爲undo塊的地址,轉爲文件號和塊號如下:
SQL> select to_number('4c00086','xxxxxxxx') from dual;
TO_NUMBER('4C00086','XXXXXXXX')
-------------------------------
79691910
SQL> select dbms_utility.data_block_address_file(79691910) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(79691910)
----------------------------------------------
19
SQL> select dbms_utility.data_block_address_block(79691910) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(79691910)
-----------------------------------------------
134
SQL>
第二部分爲UBASQN=067d轉換成10進製爲 1661。
第三部分爲UBAREC=6進制也爲6。
可以看到數據塊上面對應的事務信息和v$transaction裏面查到的數據完全一致,然後再按照方法一的方式找到UNDO上面的數據。
所以會話2查看my_test表內容時發現數據塊上面存在事物信息, 然後根據事物的xid以及uba信息找到保存着undo塊上面的數據,然後再和沒有修改的列組成查詢返回的數據。就得到的如下數據
SQL> select * from my_test;
ID NAME
---------- --------------------
1 a
SQL>
4、還有文章開頭提到的如果會話1連續更新多次,UNDO上面的數據是怎麼保存的呢?
SQL> update my_test set id = 3;
1 row updated.
SQL> update my_test set id = 4;
1 row updated.
SQL> update my_test set id = 5;
1 row updated.
SQL> @pid
SID SERIAL# PID SPID
---------- ---------- ---------- ------------------------
125 5 19 26271
SQL>
會話1又更新了3次沒有提交。然後再次dump數據塊
SQL> alter system dump datafile 1 block 134073;
System altered.
SQL>
查看dump文件的事務信息如下:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x001a.000.000030df 0x04c00084.067d.03 C--- 0 scn 0x0000.027f8a36
0x02 0x001a.01e.000030e4 0x04c00086.067d.09 ---- 1 fsc 0x0000.00000000
bdba: 0x00420bb9
data_block_dump,data header at 0x7fa900615a5c
===============
tsiz: 0x1fa0
hsiz: 0x14
pbl: 0x7fa900615a5c
76543210
和第一次dump的對比
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x001a.000.000030df 0x04c00084.067d.03 C--- 0 scn 0x0000.027f8a36
0x02 0x001a.01e.000030e4 0x04c00086.067d.06 ---- 1 fsc 0x0000.00000000
可以看到xid的數據是一致的,uba中的前兩個部分也是一致的,只有第三個部分UBASQN發生了變化,由原來的6變成了9。
Uba的第一部分並沒有發生變化,所有UNDO對應的文件號和塊號是沒有發生變化的。再次dump undo塊查看內容
SQL> alter system dump datafile 19 block 134;
System altered.
SQL> select value from v$diag_info where name = 'Default Trace File';
VALUE
--------------------------------------------------------------------------------
/u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_29036.trc
SQL>
查看UNDO BLK信息
UNDO BLK:
xid: 0x001a.01e.000030e4 seq: 0x67d cnt: 0x9 irb: 0x9 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f40 0x02 0x1e98 0x03 0x1de0 0x04 0x1d38 0x05 0x1c90
0x06 0x1bf0 0x07 0x1b7c 0x08 0x1b08 0x09 0x1a94
*-----------------------------
和第一次dump的對比
UNDO BLK:
xid: 0x001a.01e.000030e4 seq: 0x67d cnt: 0x6 irb: 0x6 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f40 0x02 0x1e98 0x03 0x1de0 0x04 0x1d38 0x05 0x1c90
0x06 0x1bf0
可以發現變爲的爲Rec有原來的最大0x06變成了現在的0x09,和Uba的變化正好相對應。
查看Rec=9的UNDO內容
*-----------------------------
* Rec #0x9 slt: 0x1e objn: 136312(0x00021478) objd: 136312 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x08 <=====指向上一個指針
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: C uba: 0x04c00086.067d.08
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x00420bb9 hdba: 0x00420bb8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 2 ckix: 0
ncol: 2 nnew: 1 size: 0
col 0: [ 2] c1 05 <====轉換成10進製爲4
SQL> select utl_raw.cast_to_number('c105') from dual;
UTL_RAW.CAST_TO_NUMBER('C105')
------------------------------
4
SQL>
rci=0x08 代表指向上一個指針。查看Rec=8 的內容
* Rec #0x8 slt: 0x1e objn: 136312(0x00021478) objd: 136312 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x07 <=====指向上一個指針
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: C uba: 0x04c00086.067d.07
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x00420bb9 hdba: 0x00420bb8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 2 ckix: 0
ncol: 2 nnew: 1 size: 0
col 0: [ 2] c1 04 <====轉換成10進製爲3
rci=0x07 代表指向上一個指針。查看Rec=7 的內容
*-----------------------------
* Rec #0x7 slt: 0x1e objn: 136312(0x00021478) objd: 136312 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x06 <=====指向上一個指針
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: C uba: 0x04c00086.067d.06
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x00420bb9 hdba: 0x00420bb8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 2 ckix: 0
ncol: 2 nnew: 1 size: 0
col 0: [ 2] c1 03 <====轉換成10進製爲2
rci=0x06 代表指向上一個指針。查看Rec=6 的內容
*-----------------------------
* Rec #0x6 slt: 0x1e objn: 136312(0x00021478) objd: 136312 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x00 <=====上一個指針爲NULL
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x04c00085.067d.30 ctl max scn: 0x0000.027f8ac6 prv tx scn: 0x0000.027f8acf
txn start scn: scn: 0x0000.027f8d4f logon user: 0
prev brb: 79691908 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x00420bb9 hdba: 0x00420bb8
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 0
ncol: 2 nnew: 1 size: 0
col 0: [ 2] c1 02 <====轉換成10進製爲1
rci=0x00 意味着Rec=6就是UNDO上面最原始的數據了,該數據內容爲c102轉換成10進製爲1,這個1也正是會話1第一次更新的數據。
所以,一個會話如果有多次更新沒有提交,那麼它會在undo裏面存在多份更新之後的數據,這些數據通過指針的方式串聯起來,如果其他會話需要使用undo數據的時候就要根據指針找到鏈表頭即爲需要的UNDO數據。