深入淺出undo記載01

dotaddjj發表於2011-12-22

初看eygle的深入淺出的關於回滾段undo,其實剛開始自認為對undo的理解還算清晰,undo的記錄的資訊,dmlundo如何和buffer cache聯絡(回滾段也是屬於buffer cache),從AUM的管理,flashback利用undo來閃回,undo表空間的回滾段的自動擴充套件於回收,切換undo表空間,快速塊清除,延遲塊清除,回滾段過舊等,看了回滾這一章發現自己還是有頗多的理解誤區和盲區。

回滾段具體記錄的是什麼:

在看馮春培的回滾段探究中提到了回滾段具體記載的是什麼,同樣eygle深入淺出中再次提到了回滾段的具體記錄的是什麼,自己也有誤區認為回滾段會記錄整個資料塊的前景象,那樣對空間消耗可是很大的。

對於dml操作,回滾段做以下分類記載:

1 insert 操作回滾段記錄的插入資料的rowid,回滾時刪除rowid上的資料

2 update操作回滾段記錄的更新資料的欄位的舊值,回滾時利用回滾段中的舊值重寫block中的資料

3 delete操作回滾段記錄整行資料的舊值,回滾時在從資料從回滾段反向插入到block中去

分批提交處理dml事物:

對於相同資料量的操作,insert產生的undo最少,update其次,delete產生的最多,這也就是經常文件中建議對於dml操作時,特別是delete操作時,分批處理提交,減少對回滾段的佔用和衝擊,不然很有可能會出現所謂的ora-01555回滾段過舊而讓一個執行半天的事物出現錯誤而回滾。

oracle 9I前,回滾表空間都需要手工維護管理,事物使用的回滾段可以如下設定:

Alter rollback segment undo_seg01 online

Set transaction use rollback segment undo_seg01;

整個事物期間使用undo_seg01回滾段,當然回滾段必須存在且上線,可以查詢v$rollstatdba_rollback_segs檢視資訊。

當然在undo_management=manual手工管理undo表空間時,也可以手工create回滾段。

Create rollback segment undo_seg02 tablespace untbso01;

Oracle9I後,AUM的出現,自動管理回滾段的出現已經不需要也不能手工去建立回滾段和制定事物使用回滾段等,回滾段的動態建立 上線 擴充套件 回縮 下線和回收都由oracle自動管理,可以在alert警告日誌中檢視相應資訊,Aum管理下,資料庫初始建立10個回滾段和1個系統回滾段。

SQL> update test03 set id=12 where id=11;

1 row updated

SQL> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubarec from v$transaction;

XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC

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

9 22 582 2 2250 39

SQL> select usn,extents,rssize,writes,xacts,hwmsize,shrinks from v$rollstat where usn=9;

USN EXTENTS RSSIZE WRITES XACTS HWMSIZE SHRINKS

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

9 3 1171456 73306 1 1171456 0

V$rollstat檢視中欄位xacts欄位代表的是該回滾段活動事務的數量。

SQL> select usn,name from v$rollname where usn=9;

USN NAME

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

9 _SYSSMU9$

此時update語句沒有提交,在另一個sessiondump回滾段資訊。

Dump回滾段_SYSSMU9$段頭資訊

Sql> alter system dump undo header '_SYSSMU9$';

Sql> select a.value||''||b.instance||'_ora_'||c.spid trace_name from

(select value from v$parameter where name='user_dump_dest')a,

(select instance from v$thread) b,

(select spid from v$process a,v$session b,v$mystat c where b.sid=c.sid and b.paddr=a.addr and c.statistic#=1)c

檢視回滾段_SYSSMU9$

Undo Segment: _SYSSMU9$ (9)

********************************************************************************

Extent Control Header

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

Extent Header:: spare1: 0 spare2: 0 #extents: 3 #blocks: 143

last map 0x00000000 #maps: 0 offset: 4080

Highwater:: 0x008008ca ext#: 2 blk#: 65 ext size: 128

#blocks in seg. hdr's freelists: 0

#blocks below: 0

mapblk 0x00000000 offset: 2

index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt

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

0x00 9 0x00 0x0246 0x0001 0x0000.001ad5c0 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316

0x01 9 0x00 0x0246 0x0007 0x0000.001ad5ca 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316

0x02 9 0x00 0x0246 0x0006 0x0000.001ad5e0 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316

0x03 9 0x00 0x0246 0x001e 0x0000.001ad6fd 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316

。。。。。。

0x15 9 0x00 0x0246 0x0013 0x0000.001ad69f 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316

0x16 10 0x80 0x0246 0x0002 0x0000.00000000 0x008008ca 0x0000.000.00000000 0x00000001 0x00000000 0

0x17 9 0x00 0x0246 0x000c 0x0000.001ad6d8 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316

可以看出在0x16轉換為10進位制也就是22,也就是第22號事務槽,state10代表是活動事務。回滾段頭事務表中的Dbadata block address)指向的是包含這個事務的前映象. 0x008008ca經轉換也就是file 2 block 2250

將回滾段中這個block dump出來

Sql>Alter system dump datafile 2 block 2250;

部分dump檔案資訊:

其中的irb指的是回滾段中記錄的最近未提交變更開始之處,如果開始回滾,irb是起始的搜尋點。

UNDO BLK:

xid: 0x0009.016.00000246 seq: 0xda cnt: 0x29 irb: 0x29 icl: 0x0 flg: 0x0000

接下來是回滾段資訊的偏移量,最後一個偏移地址正是irb 0x29的資訊

Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset

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

0x01 0x1f68 0x02 0x1ee0 0x03 0x1e60 0x04 0x1ddc 0x05 0x1d5c

0x06 0x1cd8 0x07 0x1c58 0x08 0x1bd0 0x09 0x1b50 0x0a 0x1ac8

0x0b 0x1a48 0x0c 0x19c0 0x0d 0x1940 0x0e 0x18b8 0x0f 0x1838

0x10 0x17b0 0x11 0x1730 0x12 0x16a8 0x13 0x1628 0x14 0x1588

0x15 0x1508 0x16 0x1470 0x17 0x1420 0x18 0x13a0 0x19 0x131c

0x1a 0x12b4 0x1b 0x1234 0x1c 0x119c 0x1d 0x111c 0x1e 0x1094

0x1f 0x1014 0x20 0x0f7c 0x21 0x0efc 0x22 0x0e74 0x23 0x0e24

0x24 0x0d88 0x25 0x0d48 0x26 0x0ca0 0x27 0x0c08 0x28 0x0b98

0x29 0x0b28

。。。。。。

然後繼續在dump檔案中找到0x29資訊,c1 22也就是最後更新記錄的前映象,rci代表的是undo chain(同一事務的多次修改,根據chain連結關聯)的下一個偏移量,這樣繼續用chain連結關聯,undo chain的指標為0x00,表示這個事務內最後更新一條記錄。oracle就這樣透過回滾段保留前映象(不過這個數字如何轉換自己還不清楚)

*-----------------------------

* Rec #0x29 slt: 0x16 objn: 51375(0x0000c8af) objd: 51375 tblspc: 4(0x00000004)

* Layer: 11 (Row) opc: 1 rci 0x28

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

op: C uba: 0x008008ca.00da.28

Array Update of 1 rows:

tabn: 0 slot: 2(0x2) flag: 0x2c lock: 0 ckix: 0

ncol: 1 nnew: 1 size: 0

KDO Op code: 21 row dependencies Disabled

xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x0100005e hdba: 0x0100005b

itli: 2 ispac: 0 maxfr: 4858

vect = 0

col 0: [ 2] c1 22

這裡再檢視x$bhdba_extents檢視,

SQL> select b.segment_name,a.dbarfil,a.dbablk,a.class,a.state,a.file# from x$bh a,dba_extents b

2 where b.owner='XIAOYU' and b.relative_fno=a.dbarfil and b.block_id<=a.dbablk and b.block_id+b.blocks>a.dbablk

3 and segment_name='TEST03';

SQL> select distinct b.segment_name,a.dbarfil,a.dbablk,a.class,a.state,a.file# from x$bh a,dba_extents b

2 where b.owner='XIAOYU' and b.relative_fno=a.dbarfil and b.block_id<=a.dbablk and b.block_id+b.blocks>a.dbablk

3 and segment_name='TEST03';

SEGMENT_NAME DBARFIL DBABLK CLASS STATE FILE#

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

TEST03 4 94 1 1 4

TEST03 4 96 1 1 4

TEST03 4 95 1 1 4

TEST03 4 94 1 0 4

TEST03 4 91 4 1 4

TEST03 4 92 1 1 4

TEST03 4 93 1 1 4

如果此時在別的session進行查詢select * from xiaoyu.test03

SQL> /

SEGMENT_NAME DBARFIL DBABLK CLASS STATE FILE#

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

TEST03 4 94 1 1 4

TEST03 4 96 1 1 4

TEST03 4 95 1 1 4

TEST03 4 94 1 0 4

TEST03 4 91 4 1 4

TEST03 4 92 1 1 4

TEST03 4 94 1 3 4

TEST03 4 93 1 1 4

此時v$bh中會多出一個state=3的塊,也就是為了滿足一致性讀而透過undoblock的構造的資料塊的前映象cr塊,此時buffer cache中有file 4 block 94的三個塊,其中的state分別為0,1,3

class 4表示的是段頭,class 1表示的實際儲存資料資訊的資料塊。

在前映象資訊中,oracle還記錄了前映象對應的資料塊地址,也可以從bdba: 0x0100005e,經轉換也就是file 4 block 94,再轉換該block

Alter system dump datafile 4 block 94

部分trace檔案資訊:

Start dump data blocks tsn: 4 file#: 4 minblk 94 maxblk 94

buffer tsn: 4 rdba: 0x0100005e (4/94)

scn: 0x0000.001aeaa2 seq: 0x01 flg: 0x04 tail: 0xeaa20601

frmt: 0x02 chkval: 0x927d type: 0x06=trans data

Hex dump of block: st=0, typ_found=1

Dump of memory from 0x0A5D2200 to 0x0A5D4200

A5D2200 0000A206 0100005E 001AEAA2 04010000 [....^...........]

A5D2210 0000927D 00000001 0000C8AF 001AEAA2 [}...............]

。。。

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x0008.021.00000221 0x0080042b.00ed.07 C--- 0 scn 0x0000.001a54e5

0x02 0x0009.016.00000246 0x008008ca.00da.29 ---- 3 fsc 0x0000.00000000

這裡存在ITL事務槽資訊:Xidtransaction ID UbaUndo block address lcklck status

Xid進一步分析為:usn=9的回滾段 事務槽22號,wrap#246正是dump回滾段頭中的看到的那個事務的wrap# 0x0246 ,資料塊上同樣存在指向回滾段的事務資訊。

Uba分解:0x008008ca是前映象的dba.00daUNDO BLKseq順序號,29undo記錄的開始地址(irb),回滾將從undo blk的irb開始rollback。

可以簡約總結下:

1 事務開始時,需要在回滾段事務表上分配一個事務槽

2 在資料塊頭部獲取ITL事務槽,該事務槽指向回滾段頭事務槽

3 在修改資料之前,記錄前映象資訊,這個資訊以undo record的形式儲存在回滾段中,回滾段頭事務槽指向該記錄

4 鎖定修改行,修改行鎖定為指向ITL事務槽

5 資料修改進行.

以上就是事務的基本流程。

[@more@]

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

相關文章