oracle實驗記錄 (oracle 10G 詳細分析undo)

fufuh2o發表於2009-11-02

undo資料存undo tablespace,讀入buffer cache,管理規則也是按buffer cache管理(寫出)

oracle預設啟動時候分配10個rollback segment(非system rollback segment)

SQL> select name from v$rollstat a ,v$rollname b where a.usn=b.usn;

NAME
------------------------------
SYSTEM
_SYSSMU1$
_SYSSMU2$
_SYSSMU3$
_SYSSMU4$
_SYSSMU5$
_SYSSMU6$
_SYSSMU7$
_SYSSMU8$
_SYSSMU9$
_SYSSMU10$

已選擇11行。

 


undo_retention:控制事務commit以後資訊保留時間(是一個建議性引數)S為單位
如果設定為0那麼oracle將啟動動態調整,當undo space足夠時 ,會將undo資訊的保留時間與當前執行時間最長的那個查詢所需要的時間相同(並且以900s為最低值).

 

Autotune of undo retention is turned on.

SQL> show parameter undo_reten

NAME                                 TYPE
------------------------------------ -------------------------------
VALUE
------------------------------
undo_retention                       integer
900

10G R2 DEFAULT 900s

兩個隱藏引數控制
_undo_autotune                 TRUE                      TRUE      FALSE
                    FALSE
enable auto tuning of undo_retention(是否開啟自動調整undo_retention)

_collect_undo_stats            TRUE                      TRUE      FALSE
                    FALSE
Collect Statistics v$undostat (從v$undostat收集統計資訊用於調整 預設是每30秒收集一次)


undo_retention 是noguarantee 意思當undo空間不足時還是會換出去

具體undo block有4種狀態
1.active表示使用這個undo block的 transaction還未提交
2.inactive:undo block上沒有活動事務,可以被覆蓋(但是未過期expired)
3.expired:undo block狀態為inactive的時間 超過了undo_retention
4.free:空的

AUM時候
事務使用undo segment可在不同的undo segment之間動態交換undo 空間(交換extents),當一個transaction需要更多undo空間時,首先會重用當前使用的undo segment裡可用空間,如果沒有按下面步驟獲取undo
1.獲取undo tablespace  中可用free extent
2.獲取其它rollback segment 中expired的extent
3.如果datafile 有autoextend on,那麼自動擴充套件
4.若沒開autoextend on,那麼用狀態為inactive的undo block,如果 還是不足,則報錯,

順序為 : free-expired-autoextend on-inactive

關於undo datafile autoextend on ,如果undo space不夠 oracle會先儘可能使用undo space中free ,expried的 不會馬上 擴充套件空間,除非當要覆蓋的資料是在900s之內的,才會去擴充套件空間


10g 對tablespace多了guarantee選項,保證inactive的 undo block不會被覆蓋
alter  tablespace UNDOTBS1 guarantee

 

 

dml操作產生undo比較


insert 操作將記錄 rowid


SQL> create table t1 ( a varchar2(10), b varchar2(10));

表已建立。

SQL> insert into t1  values('a','a');

已建立 1 行。

SQL> select object_id from dba_objects where object_name='T1';

 OBJECT_ID
----------
     54556

SQL> select file#,block# ,rowid from (select dbms_rowid.rowid_relative_fno(rowid
) file#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from T1);

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       2500 AAANUcAAEAAAAnEAAA

SQL> select xidusn ,ubafil,UBABLK from v$transaction;

    XIDUSN     UBAFIL     UBABLK
---------- ---------- ----------
         2          2        750

SQL> alter system dump datafile 2 block 750;

系統已更改。


* Rec #0x15  slt: 0x11  objn: 54556(0x0000d51c)  objd: 54556  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: 0x00000000
*-----------------------------
uba: 0x008002ee.04f3.14 ctl max scn: 0x0000.004f1084 prv tx scn: 0x0000.004f1092
txn start scn: scn: 0x0000.004fbcb1 logon user: 61
 prev brb: 8389354 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01 
op: Z
KDO Op code: DRP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x010009c4  hdba: 0x010009c3
itli: 1  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0)

End dump data blocks tsn: 1 file#: 2 minblk 750 maxblk 750

SQL> commit;

提交完成。

 

update將記錄修改欄位的前映象

SQL> update t1 set a='aa';

已更新 1 行。

SQL> select xidusn ,ubafil,UBABLK from v$transaction;

    XIDUSN     UBAFIL     UBABLK
---------- ---------- ----------
        10          2        158

SQL> alter system dump datafile 2 block 158;

系統已更改。

 

* Rec #0xb  slt: 0x0e  objn: 54556(0x0000d51c)  objd: 54556  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: 0x00000000
*-----------------------------
uba: 0x0080009e.0499.08 ctl max scn: 0x0000.004f6a4f prv tx scn: 0x0000.004f6a83
txn start scn: scn: 0x0000.004fbf43 logon user: 61
 prev brb: 8388764 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01 
op: Z
KDO Op code: URP row dependencies Disabled( URP 一個update 操作)
  xtype: XA flags: 0x00000000  bdba: 0x010009c4  hdba: 0x010009c3
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 9
ncol: 2 nnew: 1 size: -1
col  0: [ 1]  61~~~~~~~~~修改欄位值前映象

 

 

SQL> select chr(to_number(61,'xxx')) from dual;

CH
--
a

 

delete操作記錄整行內容 (所以 delete產生undo最多,相對的redo最多)

SQL> select xidusn ,ubafil,UBABLK from v$transaction;

    XIDUSN     UBAFIL     UBABLK
---------- ---------- ----------
        10          2        158

SQL> alter system dump datafile 2 block 158;

系統已更改。

SQL>


* Rec #0xd  slt: 0x0e  objn: 54556(0x0000d51c)  objd: 54556  tblspc: 4(0x00000004)
*       Layer:  11 (Row)   opc: 1   rci 0x0c  
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: 0x0080009e.0499.0c
KDO Op code: IRP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x010009c4  hdba: 0x010009c3
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) size/delt: 8
fb: --H-FL-- lb: 0x2  cc: 2
null: --
col  0: [ 2]  61 61~~~修改行前映象
col  1: [ 1]  61~~修改行前映象
 
End dump data blocks tsn: 1 file#: 2 minblk 158 maxblk 158

總結:delete 產生UNDO 最多 ,相對應的redo也就最多

 

關於system tablespace中的 system 還原段
這個還原段是在create database  時建立的 ,存在system tablespace,只對system 中物件所做更改

SQL> select distinct segment_type from user_segments where tablespace_name='SYST
EM';

SEGMENT_TYPE
------------------
INDEX
TABLE
LOBINDEX
LOBSEGMENT
CLUSTER
NESTED TABLE
ROLLBACK

已選擇7行。

 

SQL> select segment_name,segment_type,tablespace_name from user_segments where s
egment_type like '%ROLLBACK%';

SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME
------------------------------ ------------------ ------------------------------

SYSTEM                         ROLLBACK           SYSTEM

 

SQL> shutdown immediate;
資料庫已經關閉。
已經解除安裝資料庫。
ORACLE 例程已經關閉。
SQL>
SQL> startup mount
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE 例程已經啟動。

Total System Global Area  289406976 bytes
Fixed Size                  1248576 bytes
Variable Size             104858304 bytes
Database Buffers          176160768 bytes
Redo Buffers                7139328 bytes
資料庫裝載完畢。

SQL> alter database datafile 2 offline; 將undo檔案offline

資料庫已更改。

SQL> alter database open;~~~database可以正常open

資料庫已更改。

SQL> show user
USER 為 "SYS"
SQL> create table t1(a int);

表已建立。

SQL> insert into t1 values(1);

已建立 1 行。

SQL> commit;

提交完成。

SQL> delete from t1;

已刪除 1 行。

SQL> rollback
  2  ;

回退已完成。

SQL> select * from t1;

         A
----------
         1

SQL> select tablespace_name from user_tables where table_name='T1';

TABLESPACE_NAME
------------------------------
SYSTEM

在system tablespace 建立物件 ,DML操作都是正常的,所用undo為system rollback segment

SQL> select usn,status from v$rollstat; 檢視當前所有回滾段狀態

       USN STATUS
---------- ---------------
         0 ONLINE

SQL> desc v$rollname;
 名稱                                      是否為空? 型別
 ----------------------------------------- -------- ----------------------------

 USN                                                NUMBER
 NAME                                      NOT NULL VARCHAR2(30)

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

NAME
------------------------------
SYSTEM
 只有system rollback segment是online的

 

SQL> conn xh/a831115
已連線。
SQL> select count(*) from t1;

  COUNT(*)
----------
     10000

SQL> delete from t1;
delete from t1
            *
第 1 行出現錯誤:
ORA-01552: 非系統表空間 'USERS' 不能使用系統回退段

可以看到 其它如果dml 其他tablespace的物件 那麼需要擁有非系統回滾段(undo tablespace),system rollback segment只針對system tablespace中物件

SQL> alter database datafile 2 online;

資料庫已更改。

SQL> delete from t1;

已刪除10000行。

SQL> rollback;

回退已完成。

SQL>

 

針對DML語句來說,只要資料塊發生了變化,oracle會將修改前的資料保留下來儲存在rollback segment中(rollback segment存在undo tablespace中),兩種方式管理undo tablespace 自動(AUM AUTOMATIC UNDO MANAGEMENT),手動(mum manual undo management)

SQL> show parameter undo

NAME                                 TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
undo_management                      string~~~管理模式
AUTO
undo_retention                       integer
900
undo_tablespace                      string~~~undo tablespace
UNDOTBS1
SQL>


oracle推薦使用自動管理

undo使用的具體過程:
一條DML 比如update t1 set b='c' where a='a'
1.在shared pool中解析生成執行計劃
2.由執行計劃得出a='a'記錄在file 4 ,block 5中
3.在buffer cache中 找到 可用的undo blk,如果buffer cache中不存在則從undo tablespace中找一個可用undo block調入buffer cache(physical read )比如file 2 block 22,並且在相應的undo segment header中 trn tab中分配一個事務槽(這將會產生redo )
4.將改變前值放入file 2 block 22中
5.由於undo塊改變了將產生redo(redo有保護undo的作用)
6.在buffer cache中找file 4 block 5如果沒找到從buffer cache中調入(physical read )
7.將改變後的值 放入 file 4,block 5
8.由於file 4 ,block 5 發生了變化所以會產生redo
9.返回資訊,操作權給使用者
10.commit時 LGWR 將上面生成的redo寫入online redo file ,在file 4,block 5 ,file 2 block 22塊頭記錄事務狀態標記,設定為已提交,事務表記錄狀態為state 9
(注意上面 file 4,block 5, file 2 block 22 就是 dirty block了  他們並不隨commit而寫入datafile,只有在dirty block數量達到一定的觸發條件時才寫入 屬於incremental checkpoint或者full checkpoint的 時候,即使使用者未commit,那麼對應的dirty block也會寫入datafile )
11.事務只要commit or rollback那麼該事務所使用的undo就可以被其它事務覆蓋

 

實驗:

SQL> show user
USER 為 "XH"
SQL> create table t1 (a varchar2(10));

表已建立。

SQL> insert into t1 values('a');

已建立 1 行。

SQL> commit;

提交完成。

SQL> select * from t1;

A
----------
a

 


SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from xh.t1);

     FILE#     BLOCK#
---------- ----------
         4       2599

SQL> alter system flush  shared_pool;

系統已更改。


SQL> alter system flush buffer_cache;

系統已更改。
SQL> select file#,block#,dirty from v$bh where file#=2 or (file#=4  and block#=2
599);

     FILE#     BLOCK# D
---------- ---------- -
         2        618 Y
         2       2757 Y
         2        105 N
         2        121 N
         2         82 N
         2        137 N
         2        137 Y
         2          9 N
         2        153 N
         2        153 N
         2       2292 N

     FILE#     BLOCK# D
---------- ---------- -
         2         25 N
         2         25 N
         2       3062 Y
         2       2096 N
         2         41 N
         2         41 Y
         2        617 N
         2         83 N
         2       2756 N
         2          2 N
         2          2 N

     FILE#     BLOCK# D
---------- ---------- -
         2         57 Y
         2       3272 N
         2       2628 N
         2         73 N
         2         73 N
         2         89 N
         2         89 N

已選擇29行。

現在buffer cache中沒有 file 4 block 2


SQL> update t1 set a='b';  進行dml操作

已更新 1 行。


SQL> select file#,block#,dirty from v$bh where file#=2 or (file#=4  and block#=2
599);

     FILE#     BLOCK# D
---------- ---------- -
.......................
         4       2599 Y~~~~對應的t1 的file ,block從disk讀入buffer cache(physiacl read)修改並且標記為dirty
'''''''''''''''''''''''

     FILE#     BLOCK# D
---------- ---------- -
 
         2       3272 Y~~~~使用的 undo file block 標記為dirty
   
..........................

 

SQL> select xidusn, XIDSLOT, XIDSQN,UBAFIL,UBABLK,UBASQN,UBAREC from v$transacti
on;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC
---------- ---------- ---------- ---------- ---------- ---------- ----------
         2          0       1493          2       3272       1277         51

XIDUSN NUMBER Undo segment number
XIDSLOT NUMBER Slot number
XIDSQN NUMBER Sequence number
UBAFIL NUMBER Undo block address (UBA) filenum
UBABLK NUMBER UBA block number
UBAREC NUMBER UBA record number

使用file 2 block 3272 剛才的 查詢這個塊在 buffer cache中 所以這次就是 邏輯讀


SQL> select * from  v$rollname where usn=2;

       USN NAME
---------- ------------------------------
         2 _SYSSMU2$


SQL> select header_block,header_file from dba_segments where segment_name='_SYSS
MU2$';

HEADER_BLOCK HEADER_FILE
------------ -----------
          25           2

SQL> select object_id from dba_objects where object_name='T1' and wner='XH';

 OBJECT_ID
----------
     54666


SQL> select usn,writes,rssize,xacts from v$rollstat where usn=2
  2  ;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         2       1344    5365760          1

XACTS NUMBER Number of active transactions

WRITES NUMBER Number of bytes written to the rollback segment
RSSIZE NUMBER Size (in bytes) of the rollback segment. This value differs by the number of bytes in one database block from the value of the BYTES column of the ALL/DBA/USER_SEGMENTS views. 

可以看到 update 這個操作的事務使用的是編號為2的rollback segment ,這個rollback segment中有一個 活動事務(就是update這個操作的)

 

SQL> alter system dump datafile 2 block 3272;

系統已更改。

SQL> alter system dump datafile 4 block 2599;

系統已更改。

 

SQL> alter system dump  undo header '_SYSSMU2$';

系統已更改。


SQL> select group#,status from v$log;

    GROUP# STATUS
---------- ----------------
         1 CURRENT
         2 INACTIVE
         3 INACTIVE

SQL> select group#,member from v$logfile;

    GROUP#
----------
MEMBER
--------------------------------------------------------------------------------

         3
F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\REDO03.LOG

         2
F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\REDO02.LOG

         1
F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\REDO01.LOG


SQL> alter system dump logfile 'F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\REDO01.L
OG';
系統已更改。

 

通過dump 分析下undo機制

首先是 file 2 block 3272這個undo block
Start dump data blocks tsn: 1 file#: 2 minblk 3272 maxblk 3272
buffer tsn: 1 rdba: 0x00800cc8 (2/3272)
scn: 0x0000.0050bff7 seq: 0x01 flg: 0x04 tail: 0xbff70201
frmt: 0x02 chkval: 0x3a46 type: 0x02=KTU UNDO BLOCK
這部分是 塊的基本資訊 塊地址(rdba: 0x00800cc8 ),型別等 (0x02=KTU UNDO BLOCK)
............................................

UNDO BLK: 
xid: 0x0002.000.000005d5  seq: 0x4fd cnt: 0x33  irb: 0x33  icl: 0x0   flg: 0x0000


xid: 0x0002.000.000005d5 :記錄在這個塊上最新事務的資訊(分3段,回滾段編號,slot號,序列號)
與v$transaction中 XIDUSN    XIDSLOT     XIDSQN 對應(2,0,1493)

SQL> select to_number('2','xxxxx') from dual;

TO_NUMBER('2','XXXXX')
----------------------
                     2

SQL> select to_number('5d5','xxxxx') from dual;

TO_NUMBER('5D5','XXXXX')
------------------------
                    1493

 

irb:0x33 中記錄的是最近未提交變更的開始處及最後一次更改處,如果rollback這個是起點


 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
---------------------------------------------------------------------------
................
0x33 0x020c

偏移量資訊 最後這個是0x33

用0x33往下找
找到事務所使用的undo block

* Rec #0x33  slt: 0x00  objn: 54666(0x0000d58a)  objd: 54666  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: 0x00000000
*-----------------------------
uba: 0x00800cc8.04fd.31 ctl max scn: 0x0000.0050bbf6 prv tx scn: 0x0000.0050bbf8
txn start scn: scn: 0x0000.00000000 logon user: 61
 prev brb: 8391879 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01 
op: Z
Array Update of 1 rows: ~~~~~資訊更新一行
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 10
ncol: 1 nnew: 1 size: 0
KDO Op code:  21 row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x01000a27  hdba: 0x01000a23
itli: 2  ispac: 0  maxfr: 4858
vect = 0
col  0: [ 1]  61~~~~~~~~~~~存的舊值


SQL> select chr(to_number('61','xxxxx')) from dual;

CH
--
a

 rci 0x00   :代表同一個事務的關聯修改,rollback時用這個迴圈往下找修改值,找到回滾之處
(undo chain) 實驗中 只修改了一次 ,所以為0表示這是最後一條修改記錄

 

分析下表塊 file 4 block 2599
Start dump data blocks tsn: 4 file#: 4 minblk 2599 maxblk 2599
buffer tsn: 4 rdba: 0x01000a27 (4/2599)
scn: 0x0000.0050bff7 seq: 0x01 flg: 0x04 tail: 0xbff70601
frmt: 0x02 chkval: 0x4463 type: 0x06=trans data


 Object id on Block? Y
 seg/obj: 0xd58a  csc: 0x00.50bf51  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x1000a21 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0006.01d.000005e6  0x00800a44.03f0.36  C---    0  scn 0x0000.0050be9e
0x02   0x0002.000.000005d5  0x00800cc8.04fd.33  ----    1  fsc 0x0000.00000000

 
data_block_dump,data header at 0x7c12264
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x07c12264
bdba: 0x01000a27
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f93
avsp=0x1f7b
tosp=0x1f7b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f93
block_row_dump:
tab 0, row 0, @0x1f93
tl: 5 fb: --H-FL-- lb: 0x2  cc: 1
col  0: [ 1]  62
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 2599 maxblk 2599


這裡主要看itl資訊 事務槽(defalut 2個 )
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x02   0x0002.000.000005d5  0x00800cc8.04fd.33  ----    1  fsc 0x0000.00000000

xid: 回滾段編號+slot號+序列號 (與v$transaction中 XIDUSN    XIDSLOT     XIDSQN 對應(2,0,1493))
uba 0x00800cc8.04fd.33:也是分3段,回滾段塊地址(800cc8),回滾塊序號(4fd)對應v$transaction中 UBASQN(1227) ,undo chain(irb)(0X33), 將指向具體使用的undo block

SQL> variable file# number;
SQL> variable blk# number;
SQL> execute :file#:=dbms_utility.data_block_address_file(to_number('800cc8','xx
xxxx'));

PL/SQL 過程已成功完成。


SQL> execute :blk#:=dbms_utility.data_block_address_block(to_number('800cc8','xx
xxxx'));

PL/SQL 過程已成功完成。

SQL> print blk#

      BLK#
----------
      3272

SQL> print file#

     FILE#
----------
         2

Lck  :表示 transaction修改的行數,這些行被lock住
 Scn/Fsc:transaction的scn資訊, SCN表示commit scn, fsc表示fast commit fsc 的scn

 Flag :標記共4位c---表示已經提交,----表示未提交

 

 

tl: 5 fb: --H-FL-- lb: 0x2 (lb鎖定位資訊指向 0x02 itl) cc: 1(1列)
col  0: [ 1]  62~~~~新值b

 


事務表資訊

********************************************************************************
Undo Segment:  _SYSSMU2$ (2)
********************************************************************************
  Extent Control Header


 Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1256609738
 Extent Number:1  Commit Time: 1256609738
 Extent Number:2  Commit Time: 1256609738
 Extent Number:3  Commit Time: 1256609738
 Extent Number:4  Commit Time: 1256609738
 Extent Number:5  Commit Time: 1256609738
 Extent Number:6  Commit Time: 1256609738
 
以上這部分就是undo_retention使用的部分

  TRN CTL:: seq: 0x04fd chd: 0x001c ctl: 0x0006 inc: 0x00000000 nfb: 0x0000
            mgc: 0x8201 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
            uba: 0x00800cc8.04fd.33 scn: 0x0000.0050bbf8(control scn)
其中事務表控制資訊最新uba資訊 就是 file 2 block 3272


TRN TBL::(transaction table )
 
  index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
  ------------------------------------------------------------------------------------------------
   0x00   10    0x80  0x05d5  0x0004  0x0000.0050bf73  0x00800cc8  0x0000.000.00000000  0x00000001   0x00000000  0

index 就是 v$transaction.xidslot資訊為0 ,index為0x00
找到了update存transaction table中的資訊身體state資訊10表示活動事務


SQL> commit;~~~~~提交後

提交完成。

SQL> alter system dump datafile 2 block 3272;

系統已更改。

SQL> alter system dump datafile 4 block 2599;

系統已更改。


SQL> alter system dump  undo header '_SYSSMU2$';

系統已更改。

 
undo file 2 block 3272~~~undo 資料塊
Start dump data blocks tsn: 1 file#: 2 minblk 3272 maxblk 3272
buffer tsn: 1 rdba: 0x00800cc8 (2/3272)
scn: 0x0000.0050bff7 seq: 0x01 flg: 0x04 tail: 0xbff70201
frmt: 0x02 chkval: 0x3a46 type: 0x02=KTU UNDO BLOCK
Hex dump of block: st=0, typ_found=1
UNDO BLK: 
xid: 0x0002.000.000005d5  seq: 0x4fd cnt: 0x33  irb: 0x33  icl: 0x0   flg: 0x0000
 
 
* Rec #0x33  slt: 0x00  objn: 54666(0x0000d58a)  objd: 54666  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: 0x00000000
*-----------------------------
uba: 0x00800cc8.04fd.31 ctl max scn: 0x0000.0050bbf6 prv tx scn: 0x0000.0050bbf8
txn start scn: scn: 0x0000.00000000 logon user: 61
 prev brb: 8391879 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01 
op: Z
Array Update of 1 rows:
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 10
ncol: 1 nnew: 1 size: 0
KDO Op code:  21 row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x01000a27  hdba: 0x01000a23
itli: 2  ispac: 0  maxfr: 4858
vect = 0
col  0: [ 1]  61


首先undo block不會有任何變化

 

 

data block~~表資料塊


seg/obj: 0xd58a  csc: 0x00.50bf51  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x1000a21 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0006.01d.000005e6  0x00800a44.03f0.36  C---    0  scn 0x0000.0050be9e
0x02   0x0002.000.000005d5  0x00800cc8.04fd.33  --U-    1  fsc 0x0000.0050db99
 
data_block_dump,data header at 0x7be2264
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x07be2264
bdba: 0x01000a27
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f93
avsp=0x1f7b
tosp=0x1f7b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f93
block_row_dump:
tab 0, row 0, @0x1f93
tl: 5 fb: --H-FL-- lb: 0x2  cc: 1
col  0: [ 1]  62
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 2599 maxblk 2599


0x02   0x0002.000.000005d5  0x00800cc8.04fd.33  --U-    1  fsc 0x0000.0050db99
flag:--u-表示使用者已經提交,之後 如果與該塊有關的事務再提交 則 這個itl flag變為c---,以前c---的變為----

 

回滾段頭 事務表:
Undo Segment:  _SYSSMU2$ (2)

  index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
  ------------------------------------------------------------------------------------------------
   0x00    9    0x00  0x05d5  0xffff  0x0000.0050db99  0x00800cc8  0x0000.000.00000000  0x00000001   0x00000000  1256621655
state變為9表示已經 提交

 

 

整體transaction過程:
1.事務開始時,在undo segment header (trn tab)中分配一個INDEX(SLOT)
2.在表所在的資料塊頭獲取一個itl,指向undo segment header的index(用ITL中 XID中slot資訊)
3.在修改資料前記錄前映象undo record形式存在undo segment undo block中,undo segment header中 trn tab(中index,dba )指向該記錄
4.lock修改的行(lb-lock bytes)指向block中 itl
5.資料修改

 


關於塊中itl

SQL> create table t2 (a int, b int);

表已建立。
  1  declare
  2  begin
  3  for i in 1..20 loop
  4  insert into t2 values(i,i+1);
  5  end loop;
  6  commit;
  7* end;
SQL> /

PL/SQL 過程已成功完成。

 

SQL> select distinct block# from (select dbms_rowid.rowid_relative_fno(rowid) fi
le#,dbms_rowid.rowid_block_number(rowid) block# from xh.t2);

    BLOCK#
----------
      2632

SQL>


SQL> update xh.t2  set b=23 where a=1;

已更新 1 行。

SQL>  update xh.t2  set b=24 where a=2;

已更新 1 行。

 

SQL> update xh.t2 set b=25 where a=3;

已更新 1 行。


SQL> alter system dump datafile 4 block 2632;

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000a.002.000004b1  0x00800989.04b0.06  ----    1  fsc 0x0000.00000000
0x02   0x0006.028.00000604  0x00800a20.03fc.26  ----    1  fsc 0x0000.00000000
0x03   0x0008.00f.000005e5  0x00800093.058f.20  ----    1  fsc 0x0000.00000000
3個不同的session更新 產生3個 事務 且都未提交oracle會自動擴充套件itl

 

SQL> select max_trans from all_tables where table_name='T2';

 MAX_TRANS
----------
       255
最多可以擴充套件到255個itl ,可以 擴充套件但會對效能有影響,可以建表時指定 多個 create table name (id number) initrans 3;

SQL> create table t2 (a int ) initrans 3;

表已建立。

SQL> insert into t2 values(1);

已建立 1 行。

SQL> commit;

提交完成。

SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from t2);

     FILE#     BLOCK#
---------- ----------
         1      64554

SQL> alter system dump datafile 1 block 64554;

系統已更改。
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0003.027.000005f5  0x00800aba.0388.34  --U-    1  fsc 0x0000.0053d9b9
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

 

 

 

 

 


undo主要作用
1.consistent read(包括flashback query,flashback drop)
2.instance recovery
3.rollback transaction


讀一致性 就是當select 發出的時候  ,其結果是固定
當block上有 LOCK, flashback query < current block scn,cursor scn< current block scn 會構造cr塊來保證consistent read

過程:
當select 時(一個長時間select ) 時間是8:00 scn為111,8:10 一個SESSION 更新了 一個塊 提交了(select 還未查到獲取這個塊)這個UPDATE會在更新塊ITL中記錄提交時最新的SCN/FSN ,儲存指向一個undo block的指標(UBA),8:15一個session更新了同樣的塊提交了(select 還未查到獲取這個塊),這個UPDATE會在更新塊ITL中記錄提交時最新的SCN/FSN,儲存指向一個undo block的指標(UBA),8:20 一個session第3次更新了同樣的block並且提交了 ,這時候出現一個問題 data block中 ITL 最早第一個更新的 資訊 將被覆蓋被覆蓋的ITL 資訊記載到最新ILT資訊中UBA指向的undo block中,此時查詢語句要 讀取這個塊那麼發現查詢的 SCN

 

SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from xh.t1);

     FILE#     BLOCK#
---------- ----------
         4       2612

SQL> select data_object_id,owner from all_objects where object_name='T1';

DATA_OBJECT_ID OWNER
-------------- ------------------------------
         54727 XH

 


SQL> select * from t1;

A          B
---------- ----------
d          a

 

看下現在塊的結構


SQL> alter system dump datafile 4 block 2612;

系統已更改。

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.013.000005ef  0x008000d8.05a0.25  C---    0  scn 0x0000.005361b3
0x02   0x0003.005.000005e5  0x0080042e.0387.0c  --U-    1  fsc 0x0000.00536254
 
block_row_dump:
tab 0, row 0, @0x1f42
tl: 7 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 1]  64~~~~~~~~~~值d
col  1: [ 1]  61~~~~~~~~~值得a
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 2612 maxblk 2612

SQL> select current_scn from v$database;

CURRENT_SCN
-----------
    5464707

 

 

SQL> update t1 set a='e';

已更新 1 行。

SQL> select  XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK
---------- ---------- ---------- ---------- ----------
         9         29       1568          2      17587

SQL> alter system dump datafile 4 block 2612;

系統已更改。

SQL> alter system dump datafile 2 block 17587;

系統已更改。
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0009.01d.00000620  0x008044b3.0229.17  ----    1  fsc 0x0000.00000000~~~~被覆蓋了
0x02   0x0003.005.000005e5  0x0080042e.0387.0c  C---    0  scn 0x0000.00536254
 
data_block_dump,data header at 0x74a2264
===============

tab 0, row 0, @0x1f42
tl: 7 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 1]  65~~~~~~~~~~~~~~~~~e
col  1: [ 1]  61~~~~~~~~~~~~~~~~~a

 

* Rec #0x17  slt: 0x1d  objn: 54727(0x0000d5c7)  objd: 54727  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: 0x00000000
*-----------------------------
uba: 0x008044b3.0229.16 ctl max scn: 0x0000.00535d48 prv tx scn: 0x0000.00535d98
txn start scn: scn: 0x0000.005362f1 logon user: 61
 prev brb: 8406192 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01 
op: L  itl: xid:  0x0008.013.000005ef uba: 0x008000d8.05a0.25( 這塊itl .xid ,uba ,scn整個是被覆蓋itl的資訊)
                      flg: C---    lkc:  0     scn: 0x0000.005361b3
KDO Op code: URP row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x01000a34  hdba: 0x01000a33
itli: 1  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 7
ncol: 2 nnew: 1 size: 0
Vector content:
col  0: [ 1]  64~~~~~~~值d

 

SQL> commit
  2  ;

提交完成。


SQL> update t1 set a='ee';

已更新 1 行。

SQL> select  XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK
---------- ---------- ---------- ---------- ----------
         9          8       1570          2      17590

 

SQL> alter system dump datafile 4 block 2612;

系統已更改。

SQL> alter system dump datafile 2 block 17590;

系統已更改。

SQL>

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0009.01d.00000620  0x008044b3.0229.17  C---    0  scn 0x0000.0053637d
0x02   0x0009.008.00000622  0x008044b6.0229.31  ----    1  fsc 0x0000.00000000(0x0080042e.0387.0c被覆蓋)
 

tab 0, row 0, @0x1f3a
tl: 8 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2]  65 65~~~~~~~~~~~~~~ee
col  1: [ 1]  61~~~~~~~~~~~~~~~~~~~~~~~~~~~~a

 

 

* Rec #0x31  slt: 0x08  objn: 54727(0x0000d5c7)  objd: 54727  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: 0x00000000
*-----------------------------
uba: 0x008044b6.0229.2f ctl max scn: 0x0000.0053615a prv tx scn: 0x0000.00536174
txn start scn: scn: 0x0000.00536a86 logon user: 61
 prev brb: 8406194 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01 
op: L  itl: xid:  0x0003.005.000005e5 uba: 0x0080042e.0387.0c (被覆蓋itl資訊)
                      flg: C---    lkc:  0     scn: 0x0000.00536254
KDO Op code: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x01000a34  hdba: 0x01000a33
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 7
ncol: 2 nnew: 1 size: -1
col  0: [ 1]  65~~~~~~~~~~~~~~~~~~~~值e

 


SQL> commit;

提交完成。

SQL>


SQL> update t1 set a='eee';

已更新 1 行。

SQL> select  XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK
---------- ---------- ---------- ---------- ----------
         8         10       1520          2        126


SQL> alter system dump datafile 4 block 2612;

系統已更改。

SQL> alter system dump datafile 2 block 126;

系統已更改。

SQL>


 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.00a.000005f0  0x0080007e.05a2.06  ----    1  fsc 0x0000.00000000(0x008044b3.0229.17被覆蓋)
0x02   0x0009.008.00000622  0x008044b6.0229.31  C---    0  scn 0x0000.00536af8
 
data_block_dump,data header at 0x74a2264
===============

tl: 9 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  65 65 65~~~eee
col  1: [ 1]  61~~a

 

* Rec #0x6  slt: 0x0a  objn: 54727(0x0000d5c7)  objd: 54727  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: 0x00000000
*-----------------------------
uba: 0x0080007e.05a2.05 ctl max scn: 0x0000.00536276 prv tx scn: 0x0000.0053628a
txn start scn: scn: 0x0000.00536afd logon user: 61
 prev brb: 8388824 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01 
op: L  itl: xid:  0x0009.01d.00000620 uba: 0x008044b3.0229.17 (被覆蓋itl資訊)
                      flg: C---    lkc:  0     scn: 0x0000.0053637d
KDO Op code: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x01000a34  hdba: 0x01000a33
itli: 1  ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 7
ncol: 2 nnew: 1 size: -1
col  0: [ 2]  65 65~ee

 

 


現在select檢視到 這個塊了 FILE 4 BLOCK 2612  ,QUERY SCN 是 5464707 發現itl中有未提交事務(從lck , LB, Scn/Fsc判斷),開始構造cr塊,

當前block中 狀態資訊
0x01   0x0008.00a.000005f0  0x0080007e.05a2.06  ----    1  fsc 0x0000.00000000
0x02   0x0009.008.00000622  0x008044b6.0229.31  C---    0  scn 0x0000.00536af8

 

通過itl中 uba(0x0080007e.05a2.06 ) 找到file 2 block 126  ,發現其中記載的被覆蓋 itl資訊itl: xid:  0x0009.01d.00000620 uba: 0x008044b3.0229.17  SCN為

SQL> select to_number('53637d','xxxxxxx') from dual;

TO_NUMBER('53637D','XXXXXXX')
-----------------------------
                      5464957~~~~~~~~~比query scn還要大
  ,那麼 繼續回溯用從file 2 block 126中記載的被覆蓋ITL中的undo block address回溯( uba: 0x008044b3.0229.17 )到file 2,block 17587

這個undo block(file 2 block 17587)中 記載覆蓋上一個itl的資訊
itl: xid:  0x0008.013.000005ef uba: 0x008000d8.05a0.25  scn: 0x0000.005361b3
記錄的undo 值 是
Vector content:
col  0: [ 1]  64~~~~~~~值d

SQL> select to_number('5361b3','xxxxxxx') from dual;

TO_NUMBER('5361B3','XXXXXXX')
-----------------------------
                      5464499~~~~~~~~~~~~~~~發現這個 SCN 比 query scn要小

那麼將使用這個 itl資訊

並使用undo file 2 block 17587 中記錄的 值(將 舊值D 替換掉新值ee)  與當前塊構造cr塊

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.013.000005ef  0x008000d8.05a0.25  C---    0  scn 0x0000.005361b3~~~~第一個itl slot出來了,值也替換掉了


但 當前塊中 還有 這個itl資訊
0x02   0x0009.008.00000622  0x008044b6.0229.31  C---  scn 0x0000.00536af8
它的scn>query scn


SQL> select to_number('536af8','xxxxxxx') from dual;

TO_NUMBER('536AF8','XXXXXXX')
-----------------------------
                      5466872>query scn

通過uba (0x008044b6.0229.31 )找到 undo block file 2,block 17590;

這個塊 包含 被覆蓋的 itl資訊 為op: L  itl: xid:  0x0003.005.000005e5 uba: 0x0080042e.0387.0c (被覆蓋itl資訊)
                      flg: C---    lkc:  0     scn: 0x0000.00536254


SQL> select to_number('536254','xxxxxx') from dual;

TO_NUMBER('536254','XXXXXX')
----------------------------
                     5464660 ~~~~~~~~~~query scn(5464707) 要小

這個undo block (2,17950)中值記錄為e ,orcle對只會使用這個undo塊中記錄的被覆蓋itl的資訊構造cr,而不會使用這個undo塊中值資訊構造cr(oracle會使用undo block中儲存 被覆蓋itl資訊中 SCN最接近 query scn的 undo block中記錄的 值 )

那麼 最終 將構造出一個consistent read block ,
這個CR塊 在buffer中 file# 是4  BLOCK#是 2612,在buffer cache中 hash value一樣,所以掛在 同一個hash cache buffer chain
 


 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.013.000005ef  0x008000d8.05a0.25  C---    0  scn 0x0000.005361b3
0x02   0x0003.005.000005e5  0x0080042e.0387.0c  C---    1  fsc 0x0000.00536254
 
block_row_dump:
tab 0, row 0, @0x1f42
tl: 7 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 1]  64~~~~~~~~~~值d
col  1: [ 1]  61~~~~~~~~~值a
end_of_block_dump

 

 


cr塊數量

SQL> set linesize 132
SQL> column name format a30
SQL> column value format a25
SQL> select
  2    x.ksppinm  name,
  3    y.ksppstvl  value,
  4    y.ksppstdf  isdefault,
  5    decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE')  ismod,
  6    decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE')  isadj,x. KSPPDESC
  7  from
  8    sys.x$ksppi x,
  9    sys.x$ksppcv y
 10  where
 11    x.inst_id = userenv('Instance') and
 12    y.inst_id = userenv('Instance') and
 13    x.indx = y.indx and
 14    x.ksppinm like '%_&par%'
 15  order by
 16    translate(x.ksppinm, ' _', ' ')
 17  /
輸入 par 的值:  db_block_max_cr
原值   14:   x.ksppinm like '%_&par%'
新值   14:   x.ksppinm like '%_db_block_max_cr%'

NAME                           VALUE                     ISDEFAULT ISMOD
                    ISADJ
------------------------------ ------------------------- --------- -------------
------------------- --------------------------------
KSPPDESC
--------------------------------------------------------------------------------
----------------------------------------------------
_db_block_max_cr_dba           6                         TRUE      FALSE
                    FALSE
Maximum Allowed Number of CR buffers per dba


預設同一個datablock可以有 6個CR block

SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from t2);

     FILE#     BLOCK#
---------- ----------
         1      64554

SQL> select  file#,block#,status from v$bh where file#=1 and block#=64554;

     FILE#     BLOCK# STATUS
---------- ---------- -------
         1      64554 free
SQL> update t2 set a=2;

已更新 1 行。
SQL> select  file#,block#,status from v$bh where file#=1 and block#=64554;

     FILE#     BLOCK# STATUS
---------- ---------- -------
         1      64554 free
         1      64554 cr
         1      64554 xcur
這個UPDATE 產生一個CR塊 ,和一個當前模式的塊,未commit

SQL> select * from t2;

         A
----------
         3
~~多次查詢
SQL> select  file#,block#,status from v$bh where file#=1 and block#=64554;

     FILE#     BLOCK# STATUS
---------- ---------- -------
         1      64554 free
         1      64554 xcur
         1      64554 cr
         1      64554 cr
         1      64554 cr
         1      64554 cr
         1      64554 cr
         1      64554 cr

已選擇8行。


已選擇8行。~~~~~~~~~~~~~~~·可以看到最多就 構建6個 cr塊,超過後  覆蓋以前的CR塊 繼續構建,cr塊是不會讓其它session共享的 (因為每次查詢的scn不一樣,而且也許事務也在對塊有不同的修改)


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

oracle 10g IMU(IN MEMORY UNDO )

修改資料時UNDO寫到BUFFER CACHE中(產生redo) 然後 按BUFFER CACHE 管理方法 被DBWN 程式將undo寫到undo segment 上,當產生cr塊或rollback操作時 ,undo blk要從undo segment 讀入buffer cache,可能會產生大量consistent get or physical reads

IN MEMROY UNDO (用於控制UNDO產生redo及其從buffer cache寫回disk) shared pool中開獨立記憶體區,存undo 資訊(避免在 buffer cache中進行讀寫操作 減少redo生成)
減少了undo segment的操作,IMU中資料暫存整理收縮後批量寫入undo segment

**imu 與redo 的private redolog strands(zero-copy redo)是緊密相關的,IMU在shared pool中 buffer 64-128K(與 private redolog strands一樣 ),所以只有特定的小事務才可以放入 產生修改變化時候相關redo寫入pvrs(等於都是在shared pool中操作,UNDO,REDO還是對應的),每個transaction 繫結一個獨立的free space(每個獨立IMU 空間由in memory undo latch保護)當 imu buffer,pvrs滿後,oracle會寫出imu中資訊到 undo segment ,pvrs中redo到 online redo log file,RAC不支援IMU特性

 SQL> select * from v$sgastat where nAme like '%KTI%'
  2  ;

POOL         NAME                                BYTES
------------ ------------------------------ ----------
shared pool  KTI-UNDO                          1235304~~~~分配imu記憶體
shared pool  KTI pool states                        20
shared pool  KTI latch structure                  1872
shared pool  KTI latches                           288


SQL> select name,gets from v$latch_children where name like '%undo latch';

NAME                                 GETS
------------------------------ ----------
In memory undo latch                 2845
In memory undo latch                 8261
In memory undo latch                  929
In memory undo latch                 1214
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0

NAME                                 GETS
------------------------------ ----------
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0
In memory undo latch                    0

已選擇18行。

獨立的in memory undo latch


控制imu的隱藏引數
_in_memory_undo default true Make in memory undo for top level transactions 是否起用imu
_imu_pools   default 3 in memory undo pools 預設分3個pool
_recursive_imu_transactions  default false recursive transactions may be IMU 遞迴事務是否使用IMU
_db_writer_flush_imu default   TRUE If FALSE, DBWR will not downgrade IMU txns for AGING 將IMU TRANSACTION 降級為正常事務執行在undo segment的寫出操作

 

IMU 總體資訊
SQL> select  name,to_number(value,'xxxxxxxx') from v$sysstat where name like '%I
MU%';

NAME                           TO_NUMBER(VALUE,'XXXXXXXX')
------------------------------ ---------------------------
IMU commits                                           4119~~提交次數
IMU Flushes                                             40~~重新整理次數
IMU contention                                           0
IMU recursive-transaction flus                           1
h

IMU undo retention flush                                 0
IMU ktichg flush                                         0
IMU bind flushes                                         0
IMU mbu flush                                            0
IMU pool not allocated                                   0

NAME                           TO_NUMBER(VALUE,'XXXXXXXX')
------------------------------ ---------------------------
IMU CR rollbacks                                         0
IMU undo allocation size                          37896594
IMU Redo allocation size                           1644694
IMU- failed to get a private s                           0
trand


已選擇13行。

關於ora-01555

常見原因就是 當一個select 的SCN 小於一個更新操作的 SCN 那麼需要構造CR塊,如果這個查詢完成的時間 大於這個UPDATE 提交時間 那麼該塊的前映象有可能被覆蓋,如果這個UPDATE 事務是 fast block clean 那麼當 構造cr塊時 回滾段資訊已經被覆蓋 資訊不可用,那麼造成ora-01555

SQL> create undo tablespace undotbs2 datafile 'e:\datafile\undotbs2.dbf' size 10m
;

表空間已建立。

SQL> show parameter undo_tablespace

NAME                                 TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
undo_tablespace                      string
UNDOTBS1


SQL> select usn,xacts,status from v$rollstat;

       USN      XACTS STATUS
---------- ---------- ---------------
         0          0 ONLINE
         1          0 ONLINE
         2          0 ONLINE
         3          0 ONLINE
         4          0 ONLINE
         5          0 ONLINE
         6          0 ONLINE
         7          0 ONLINE
         8          0 ONLINE
         9          0 ONLINE
        10          0 ONLINE

已選擇11行。

SQL> alter system set undo_tablespace='UNDOTBS2';

系統已更改。

SQL> select usn,xacts,status from v$rollstat;

       USN      XACTS STATUS
---------- ---------- ---------------
         0          0 ONLINE~~~~~~~~~system undo segment
        11          0 ONLINE
        12          0 ONLINE
        13          0 ONLINE
        14          0 ONLINE
        15          0 ONLINE
        16          0 ONLINE
        17          0 ONLINE

已選擇8行。~~~~可以看到已經切換成最新的UNDO tablespace了

SQL> select segment_name,status,tablespace_name from dba_rollback_segs;

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- ------------------------------
SYSTEM                         ONLINE           SYSTEM
_SYSSMU1$                      OFFLINE          UNDOTBS1
_SYSSMU2$                      OFFLINE          UNDOTBS1
_SYSSMU3$                      OFFLINE          UNDOTBS1
_SYSSMU4$                      OFFLINE          UNDOTBS1
_SYSSMU5$                      OFFLINE          UNDOTBS1
_SYSSMU6$                      OFFLINE          UNDOTBS1
_SYSSMU7$                      OFFLINE          UNDOTBS1
_SYSSMU8$                      OFFLINE          UNDOTBS1
_SYSSMU9$                      OFFLINE          UNDOTBS1
_SYSSMU10$                     OFFLINE          UNDOTBS1

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- ------------------------------
_SYSSMU11$                     ONLINE           UNDOTBS2
_SYSSMU12$                     ONLINE           UNDOTBS2
_SYSSMU13$                     ONLINE           UNDOTBS2
_SYSSMU14$                     ONLINE           UNDOTBS2
_SYSSMU15$                     ONLINE           UNDOTBS2
_SYSSMU16$                     ONLINE           UNDOTBS2
_SYSSMU17$                     ONLINE           UNDOTBS2

已選擇18行。

SQL> conn xh/a831115
已連線。
SQL> show user
USER 為 "XH"
SQL> create table ts(a char(2000), b char(2000), c char(2000));

表已建立。


SQL> declare
  2  begin
  3  for i in 1..20 loop
  4  insert into ts values('a','a','a');
  5  end loop;
  6  commit;
  7  end;
  8  /

PL/SQL 過程已成功完成。
SQL>  select file#,block# ,rowid from (select dbms_rowid.rowid_relative_fno(rowi
d) file#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from TS);

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       2764 AAANcIAAEAAAArMAAA
         4       2765 AAANcIAAEAAAArNAAA
         4       2766 AAANcIAAEAAAArOAAA
         4       2767 AAANcIAAEAAAArPAAA
         4       2768 AAANcIAAEAAAArQAAA
         4       2769 AAANcIAAEAAAArRAAA
         4       2770 AAANcIAAEAAAArSAAA
         4       2771 AAANcIAAEAAAArTAAA
         4       2772 AAANcIAAEAAAArUAAA
         4       2773 AAANcIAAEAAAArVAAA
         4       2774 AAANcIAAEAAAArWAAA

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       2775 AAANcIAAEAAAArXAAA
         4       2776 AAANcIAAEAAAArYAAA
         4       2778 AAANcIAAEAAAAraAAA
         4       2779 AAANcIAAEAAAArbAAA
         4       2780 AAANcIAAEAAAArcAAA
         4       2781 AAANcIAAEAAAArdAAA
         4       2782 AAANcIAAEAAAAreAAA
         4       2783 AAANcIAAEAAAArfAAA
         4       2784 AAANcIAAEAAAArgAAA

SQL> show user
USER 為 "XH"
SQL> select distinct sid from v$mystat;

       SID
----------
       143
SQL> var  a refcursor
SQL> exec open :a for select  * from xh.ts;

PL/SQL 過程已成功完成。


SQL> ed
已寫入 file afiedt.buf

  1  declare
  2  begin
  3  for i in 1..1000 loop
  4  update xh.ts set a='aa';
  5  commit;
  6  end loop;
  7* end;
SQL> /

PL/SQL 過程已成功完成。


SQL> print a
ERROR:
ORA-01555: 快照過舊: 回退段號 16 (名稱為 "_SYSSMU16$") 過小


oracle 按照前面的回溯方法 製造cr塊,但 製造CR塊 時需要的undo資訊 已經被覆蓋了 (可以理解為所有undo block中記載被覆蓋的ITL資訊中SCN 都比查詢的大)


alert.log中會記載詳細資訊
ORA-01555 caused by SQL statement below (SQL ID: 8f9xxvtdbyaf6, Query Duration=138 sec, SCN: 0x0000.0054f00f):
Fri Oct 30 20:41:28 2009
SELECT * FROM XH.TS

SQL> select sql_text from v$sqlarea where sql_id='8f9xxvtdbyaf6';

SQL_TEXT
--------------------------------------------------------------------------------

SELECT * FROM XH.TS

SQL> select sid ,username from v$session where sql_hash_value=1522477510 or PREV
_HASH_VALUE=1522477510;

       SID USERNAME
---------- ------------------------------
       143 XH

errorstack 跟蹤ora-01555
SQL> alter system  set events'1555 trace name errorstack level 4';,跟蹤資訊01555

 

 

 


第2種情況
delayed block cleanout 與ora-01555

tom 對於 延遲塊清除造成ora-01555的解釋
塊清除是導致ORA-01555錯誤錯誤的原因,儘管很難完全杜絕,不過好在畢竟並不多見,因為可能出現塊清除的情況不常發生(至少在Oracle8i及 以上版本中是這樣)。我們已經討論過塊清除機制,不過這裡可以做一個總結:在塊清除過程中,如果一個塊已被修改,下一個會話訪問這個塊時,可能必須檢視最 後一個修改這個塊的事務是否還是活動的。一旦確定該事務不再活動,就會完成塊清除,這樣另一個會話訪問這個塊時就不必再歷經同樣的過程。要完成塊清除,Oracle會從塊首部確定前一個事務所用的undo段,然後確定從undo首部能不能看出這個塊是否已經提交。可以用以下兩種方式完成這種確認。一種方式是Oracle可以確定這個事務很久以前就已經提交,它在undo段事務表中的事務槽已經被覆蓋。另一種情況是COMMIT SCN還在undo段的事務表中,這說明事務只是稍早前剛提交,其事務槽尚未被覆蓋。
要從一個延遲的塊清除收到ORA-01555錯誤,以下條件都必須滿足:
1. 首先做了一個修改並COMMIT,塊沒有自動清理(即沒有自動完成“提交清除”,例如修改了太多的塊,在SGA塊緩衝區快取的10%中放不下)。
2. 其他會話沒有接觸這些塊,而且在我們這個“倒黴”的查詢(稍後顯示)命中這些塊之前,任何會話都不會接觸它們。
3. 開始一個長時間執行的查詢。這個查詢最後會讀其中的一些塊。這個查詢從SCN t1開始,這就是讀一致SCN,必須將資料回滾到這一點來得到讀一致性。開始查詢時,上述修改事務的事務條目還在undo段的事務表中。
4. 查詢期間,系統中執行了多個提交。執行事務沒有接觸執行已修改的塊(如果確實接觸到,也就不存在問題了)。
5.由於出現了大量的COMMIT,undo段中的事務表要回繞並重用事務槽。最重要的是,將迴圈地重用原來修改事務的事務條目。另外,系統重用了undo段的區段,以避免對undo段首部塊本身的一致讀。
6.此外,由於提交太多,undo段中記錄的最低SCN現在超過了t1(高於查詢的讀一致SCN)。
如果查詢到達某個塊,而這個塊在查詢開始之前已經修改並提交,就會遇到麻煩。正常情況下 會回到,到塊所指的undo段,找到修改了這個塊的事務的狀態(換句話說,它會找到事務的COMMIT SCN)。如果這個COMMIT SCN小於t1,查詢就可以使用這個塊。如果該事務的COMMIT SCN大於t1,查詢就必須回滾這個塊。不過,問題是,在這種特殊的情況下,查詢無法確定塊的COMMIT SCN是大於還是小於t1。相應地,不清楚查詢能否使用這個塊映像。這就導致了ORA-01555錯誤。

 

個人總結:簡單說 如果update 提交方式是delayed block cleanout,那麼undo segement header 中的trn tab已經被重用,將造成無法判斷select 與update時間的前後關係,select到這個塊時候發現 塊中有未提交事務的資訊,將去對應的事務表中判斷這個未提交事務的狀態(是否提交) 事務表覆蓋了就無法判斷狀態了,如果可以判斷出 select scn>update scn,這樣select可以直接使用這個塊,如果select scn< update scn那麼將構造cr塊,現在問題就是無法判斷 是哪種情況

 

 

關於塊清除
若一個transcation 修改不超過10%的buffer cache 提交時,oracle將做fast commit cleanout,如果修改超過了10%的buffer cache 提交時,超過的10%的部分將執行delayed block cleanout
在事務commit前修改資料(dirty buffer)若已寫入datafile,當事務提交時候oracle 並不會把已經寫入datafile的來做cleanout,下次讀取時在清除 進行delayed block cleanout,這是一種對效能的優化,減少physiace read,但delayed block cleanout時並不讀入修改的data block,但是會讀入 使用回滾段的 undo segment header block,修改其中的事務表(trn tab)將事務標記為提交,下次另一個事務再次讀入這個data block時發現沒有提交 會先檢視itl xid找到 事務表 看是否提交過,然後做延遲塊清除(如果是select 時候 讀入這個 block 會產生 redo)清除塊中itl資訊和鎖資訊


主要看下塊清除
undo block和修改的data block 未commit前 已經寫回 datafile, 此時commit,延遲塊清除產生,data block不會被從datafile讀入buffer cache,但是undo segment header block會讀入buffer cache修改事務表
SQL> select * from test;

         A
----------
         9
         9


SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from test);

     FILE#     BLOCK#
---------- ----------
         6         50
         6         50

SQL> update test set a=9;

2 rows updated.


SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK
---------- ---------- ---------- ---------- ----------
         4         25        407          2       1630

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

NAME
------------------------------
_SYSSMU4$

 

SQL> alter system dump datafile 6 block 50;

System altered.

SQL> alter system dump undo header '_SYSSMU4$';

System altered.

buffer tsn: 7 rdba: 0x01800032 (6/50)
scn: 0x0000.00277541 seq: 0x01 flg: 0x04 tail: 0x75410601
frmt: 0x02 chkval: 0x2ff4 type: 0x06=trans data
Block header dump:  0x01800032
 Object id on Block? Y
 seg/obj: 0xc972  csc: 0x00.23b1db  itc: 2  flg: O  typ: 1 - DATA
     fsl: 0  fnx: 0x0 ver: 0x01
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0004.019.00000197  0x0080065e.0229.0e  ----    2  fsc 0x0000.00000000
0x02   0x0009.022.000001b7  0x0080008c.0250.63  C---    0  scn 0x0000.0023916f
tab 0, row 0, @0x1f9a
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 0a
tab 0, row 1, @0x1f94
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 0a
end_of_block_dump

~~~~~~~~~~~~~~~~~~~~~~未commit時候塊中資訊

SQL> variable file# number;
SQL> variable blk# number;


uba:0x0080065e.0229.0e 找到這個事務使用的undo block
SQL> execute :file#:=dbms_utility.data_block_address_file(to_number('80065e','xx
xxxxx'));

PL/SQL procedure successfully completed.

SQL> execute :blk#:=dbms_utility.data_block_address_block(to_number('80065e','xx
xxxxx'));

PL/SQL procedure successfully completed.

SQL> print file#

     FILE#
----------
         2

SQL> print blk#

      BLK#
----------
      1630

SQL> select file_id,block_id from dba_extents where segment_name='_SYSSMU4$';

   FILE_ID   BLOCK_ID
---------- ----------
         2         57~~~~~~~~undo segment header 存trn tab(事務表)
         2         17
         2       1545

 

SQL> select file#,block#,class#,status from v$bh where file# in(6,2) and block#
in(1630,57,17,1545,50);

     FILE#     BLOCK#     CLASS# STATUS
---------- ---------- ---------- -------
         2         57         23 xcur
         6         50          1 cr
         6         50          1 xcur
         2       1630         24 xcur


SQL> alter system  flush buffer_cache;~~~事務未提交時,強制將dirty buffer 重新整理到disk

System altered.

SQL> select file#,block#,class#,status ,dirty from v$bh where file# in(6,2) and
block# in(1630,57,17,1545,50);

     FILE#     BLOCK#     CLASS# STATUS  D
---------- ---------- ---------- ------- -
         2         57         23 free    N
         6         50          1 free    N
         6         50          1 free    N
         2       1630         24 free    N


SQL> commit;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~此時執行update 的 session commit,這是一個delayed block cleanout

Commit complete.


QL> /

    FILE#     BLOCK#     CLASS# STATUS  D
--------- ---------- ---------- ------- -
        2         57         23 free    N
        2         57         23 xcur    Y~~~~~~~~~~~~~~~~~~~~~~~~~~buffer cache中讀入 undo header了 修改了 undo header tran tab
        6         50          1 free    N~~~~~~~~~~data block沒有讀入buffer cache
        6         50          1 free    N
        2       1630         24 free    N~~~~~~~~~~undo block也沒讀入buffer cache

 

SQL> select * from test;~~~~此時另一個SESSION 查詢,產生delayed block cleanout

         A
----------
         9
         9

SQL> /

     FILE#     BLOCK#     CLASS# STATUS  D
---------- ---------- ---------- ------- -
         2         57         23 free    N
         2         57         23 xcur    Y~~~~~~~~~~~~~~~~~
         6         50          1 free    N
         6         50          1 free    N
         6         50          1 xcur    Y~~~~~~~~~~~~~~~~~~讀入data block 產生delayed block cleanout
         2       1630         24 free    N

 

 


通過轉儲分析下
SQL> conn xh/a831115
已連線。
SQL> desc t1;
 名稱                                                                     是否為
空? 型別
 ------------------------------------------------------------------------ ------
-- -------------------------------------------------
 A
   VARCHAR2(10)
 B
   VARCHAR2(10)

SQL> update t1 set a='f';

已更新 1 行。

SQL> select file#,block# from (select dbms_rowid.rowid_relative_fno(rowid) file#
,dbms_rowid.rowid_block_number(rowid) block# from t1);

     FILE#     BLOCK#
---------- ----------
         4       2612

SQL> select  XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK
---------- ---------- ---------- ---------- ----------
        15         38         44         11         77

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

NAME
------------------------------
_SYSSMU15$

 


SQL> alter system dump datafile 4 block 2612;

系統已更改。

 


SQL> alter system dump undo header '_SYSSMU15$';

系統已更改。
data block中
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.00a.000005f0  0x0080007e.05a2.06  C---    0  scn 0x0000.00537e75
0x02   0x000f.026.0000002c  0x02c0004d.027d.1b  ----    1  fsc 0x0000.00000000
 
data_block_dump,data header at 0x94f2264

tosp=0x1f7b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f2a
block_row_dump:
tab 0, row 0, @0x1f2a
tl: 7 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 1]  66
col  1: [ 1]  61

 

undo segment header 中
  TRN TBL::
 
  index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
 0x26   10    0x80  0x002c  0x0000  0x0000.0055bdcc  0x02c0004d  0x0000.000.00000000  0x00000001   0x00000000  0
SQL> select to_number('26','xxxx') from dual;

TO_NUMBER('26','XXXX')
----------------------
                    38~~~38好slot(與 v$transaction中 XIDslot一樣 )

SQL> alter system flush buffer_cache;

系統已更改。

SQL> commit;~~~update transaction提交

提交完成。

SQL>
SQL> alter system dump datafile 4 block 2612;

系統已更改。


SQL> alter system dump undo header '_SYSSMU15$';

系統已更改。


Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.00a.000005f0  0x0080007e.05a2.06  C---    0  scn 0x0000.00537e75
0x02   0x000f.026.0000002c  0x02c0004d.027d.1b  ----    1  fsc 0x0000.00000000~~~看 到 itl資訊 沒 清除
 
data_block_dump,data header at 0x94f2264
===============
..........
block_row_dump:
tab 0, row 0, @0x1f2a
tl: 7 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 1]  66
col  1: [ 1]  61

 

  TRN TBL::
 
  index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
0x26    9    0x00  0x002c  0x002d  0x0000.0055c0ae  0x02c0004d  0x0000.000.00000000  0x00000001   0x00000000  1256981843

~~~看 到 undo segment header 中 trn tbl 已經記錄為 提交  state 為 9


SQL> set autotrace trace statistics
SQL> select * from xh.t1;~~另一session查詢


統計資訊
----------------------------------------------------------
         24  recursive calls
          0  db block gets
         11  consistent gets
          8  physical reads~~~從disk讀回buffer cache產生 物理讀
        116  redo size~~~~~~~~~~產生redo
        457  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> alter system dump datafile 4 block 2612;

系統已更改。

SQL> alter system dump undo header '_SYSSMU15$';

系統已更改。

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.00a.000005f0  0x0080007e.05a2.06  C---    0  scn 0x0000.00537e75~~~flag改變
0x02   0x000f.026.0000002c  0x02c0004d.027d.1b  C---    0  scn 0x0000.0055c0ae
 
data_block_dump,data header at 0x94f2264
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x094f2264
bdba: 0x01000a34
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f2a
avsp=0x1f7b
tosp=0x1f7b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f2a
block_row_dump:
tab 0, row 0, @0x1f2a
tl: 7 fb: --H-FL-- lb: 0x0  cc: 2~~~~~~LB 原來指向0x01的lock標記清除(lock修改的行(lb-lock bytes)指向block中 itl)
col  0: [ 1]  66
col  1: [ 1]  61
end_of_block_dump

以上就是 delayed block cleanout時 資料結構

 

關於undo的 恢復


有備份且archive log mode 下 undo tablespace的恢復與恢復普通tablespace並沒有區別,無論損壞時UNDO TABLESPACE中是否存在活動事務;


SQL> show parameter undo_tablespace

NAME                                 TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
undo_tablespace                      string
UNDOTBS1
SQL> select segment_name,status,tablespace_name from dba_rollback_segs;

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- ------------------------------
SYSTEM                         ONLINE           SYSTEM
_SYSSMU1$                      ONLINE           UNDOTBS1
_SYSSMU2$                      ONLINE           UNDOTBS1
_SYSSMU3$                      ONLINE           UNDOTBS1
_SYSSMU4$                      ONLINE           UNDOTBS1
_SYSSMU5$                      ONLINE           UNDOTBS1
_SYSSMU6$                      ONLINE           UNDOTBS1
_SYSSMU7$                      ONLINE           UNDOTBS1
_SYSSMU8$                      ONLINE           UNDOTBS1
_SYSSMU9$                      ONLINE           UNDOTBS1
_SYSSMU10$                     ONLINE           UNDOTBS1

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- ------------------------------
_SYSSMU11$                     OFFLINE          UNDOTBS2
_SYSSMU12$                     OFFLINE          UNDOTBS2
_SYSSMU13$                     OFFLINE          UNDOTBS2
_SYSSMU14$                     OFFLINE          UNDOTBS2
_SYSSMU15$                     OFFLINE          UNDOTBS2
_SYSSMU16$                     OFFLINE          UNDOTBS2
_SYSSMU17$                     OFFLINE          UNDOTBS2

已選擇18行。
RMAN> list backup of database;


RMAN> backup datafile 2;

啟動 backup 於 01-11月-09
使用通道 ORA_DISK_1
通道 ORA_DISK_1: 啟動全部資料檔案備份集
通道 ORA_DISK_1: 正在指定備份集中的資料檔案
輸入資料檔案 fno=00002 name=F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DB
F
通道 ORA_DISK_1: 正在啟動段 1 於 01-11月-09
通道 ORA_DISK_1: 已完成段 1 於 01-11月-09
段控制程式碼=F:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\XHTEST\BACKUPSET\2009_11_01\
O1_MF_NNNDF_TAG20091101T152506_5GTFYNYR_.BKP 標記=TAG20091101T152506 註釋=NONE
通道 ORA_DISK_1: 備份集已完成, 經過時間:00:00:26
完成 backup 於 01-11月-09

啟動 Control File and SPFILE Autobackup 於 01-11月-09
段 handle=F:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\XHTEST\AUTOBACKUP\2009_11
_01\O1_MF_S_701796332_5GTFZF3F_.BKP comment=NONE
完成 Control File and SPFILE Autobackup 於 01-11月-09

SQL> col tablespace_name format a20
SQL> col file_name format a40
SQL> select tablespace_name,file_name from dba_data_files;

TABLESPACE_NAME      FILE_NAME
-------------------- ----------------------------------------
USERS                F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\
                     USERS01.DBF

SYSAUX               F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\
                     SYSAUX01.DBF

UNDOTBS1             F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\
                     UNDOTBS01.DBF

SYSTEM               F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\
                     SYSTEM01.DBF

TABLESPACE_NAME      FILE_NAME
-------------------- ----------------------------------------

EXAMPLE              F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\
                     EXAMPLE01.DBF

TEST                 E:\DATAFILE\TEST.DBF
SSS                  E:\DATAFILE\SSS.DBF
SS                   E:\DATAFILE\SS.DBF
MYT                  E:\DATAFILE\MYT.DBF
UNDO2                E:\DATAFILE\UNDO2.DBF
UNDOTBS2             E:\DATAFILE\UNDOTBS2.DBF

已選擇11行。

SQL>

SQL> select usn,writes,rssize,xacts from v$rollstat
  2  ;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         0      12184     385024          0
         1       9280    6414336          0
         2        402    5365760          0
         3       2078    2416640          0
         4       5860     253952          0
         5        984     253952          0
         6       1466     319488          0
         7       2428    3268608          0
         8        670     319488          0
         9       5742    1171456          0
        10       1406    2416640          0

已選擇11行。~~~沒有存在活動事務

SQL> shutdown immediate;
資料庫已經關閉。
已經解除安裝資料庫。
ORACLE 例程已經關閉。
SQL> host del F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF

SQL> startup
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE 例程已經啟動。

Total System Global Area  289406976 bytes
Fixed Size                  1248576 bytes
Variable Size              83886784 bytes
Database Buffers          197132288 bytes
Redo Buffers                7139328 bytes
資料庫裝載完畢。
ORA-01157: 無法標識/鎖定資料檔案 2 - 請參閱 DBWR 跟蹤檔案
ORA-01110: 資料檔案 2: 'F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF'

 

SQL> alter  database datafile 2 offline;

資料庫已更改。

SQL> alter database open;

資料庫已更改。

RMAN> run{restore datafile 2;
2> recover datafile 2;}

啟動 restore 於 01-11月-09
使用目標資料庫控制檔案替代恢復目錄
分配的通道: ORA_DISK_1
通道 ORA_DISK_1: sid=148 devtype=DISK

通道 ORA_DISK_1: 正在開始恢復資料檔案備份集
通道 ORA_DISK_1: 正在指定從備份集恢復的資料檔案
正將資料檔案00002恢復到F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF
通道 ORA_DISK_1: 正在讀取備份段 F:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\XHT
EST\BACKUPSET\2009_11_01\O1_MF_NNNDF_TAG20091101T152506_5GTFYNYR_.BKP
通道 ORA_DISK_1: 已恢復備份段 1
段控制程式碼 = F:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\XHTEST\BACKUPSET\2009_11_0
1\O1_MF_NNNDF_TAG20091101T152506_5GTFYNYR_.BKP 標記 = TAG20091101T152506
通道 ORA_DISK_1: 恢復完成, 用時: 00:00:26
完成 restore 於 01-11月-09

啟動 recover 於 01-11月-09
使用通道 ORA_DISK_1

正在開始介質的恢復
介質恢復完成, 用時: 00:00:01

完成 recover 於 01-11月-09

SQL> alter database datafile 2 online;

資料庫已更改。


另外 如果undo tablespace 沒有備份,但損壞時所有undo segment 中沒有活動事務那麼可以通過create 一個新的undo tablespace,修改undo_tablespace引數 既可

 

 

情況 2 不存在備份,或archive log 不全,且undo tablespace undo segment中存在活動事務

 

 

SQL> conn xh/a831115
已連線。
SQL> update t1 set a='bbbb';~~~未提交

已更新 1 行。
SQL> select segment_name,status,tablespace_name from dba_rollback_segs;

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
SYSTEM                         ONLINE           SYSTEM
_SYSSMU1$                      ONLINE           UNDOTBS1
_SYSSMU2$                      OFFLINE          UNDOTBS1
_SYSSMU3$                      OFFLINE          UNDOTBS1
_SYSSMU4$                      OFFLINE          UNDOTBS1
_SYSSMU5$                      OFFLINE          UNDOTBS1
_SYSSMU6$                      OFFLINE          UNDOTBS1
_SYSSMU7$                      OFFLINE          UNDOTBS1
_SYSSMU8$                      OFFLINE          UNDOTBS1
_SYSSMU9$                      OFFLINE          UNDOTBS1
_SYSSMU10$                     OFFLINE          UNDOTBS1

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
_SYSSMU11$                     OFFLINE          UNDOTBS2
_SYSSMU12$                     OFFLINE          UNDOTBS2
_SYSSMU13$                     OFFLINE          UNDOTBS2
_SYSSMU14$                     OFFLINE          UNDOTBS2
_SYSSMU15$                     OFFLINE          UNDOTBS2
_SYSSMU16$                     OFFLINE          UNDOTBS2
_SYSSMU17$                     OFFLINE          UNDOTBS2

已選擇18行。
SQL> select usn,writes,rssize,xacts from v$rollstat;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         0      26674     385024          0
         1        382    6414336          1

 


SQL> conn / as sysdba
已連線。
SQL> shutdown abort
ORACLE 例程已經關閉。
SQL> host del F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF

SQL> startup
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE 例程已經啟動。

Total System Global Area  289406976 bytes
Fixed Size                  1248576 bytes
Variable Size              83886784 bytes
Database Buffers          197132288 bytes
Redo Buffers                7139328 bytes
資料庫裝載完畢。
ORA-01157: 無法標識/鎖定資料檔案 2 - 請參閱 DBWR 跟蹤檔案
ORA-01110: 資料檔案 2: 'F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF'

 

SQL> alter database datafile 2 offline;

資料庫已更改。
SQL> alter database open;

資料庫已更改。


SQL> select usn,writes,rssize,xacts from v$rollstat;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         0       4016     385024          0

SQL> select segment_name,status,tablespace_name from dba_rollback_segs;

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
SYSTEM                         ONLINE           SYSTEM
_SYSSMU1$                      NEEDS RECOVERY   UNDOTBS1*******
_SYSSMU2$                      NEEDS RECOVERY   UNDOTBS1*******
_SYSSMU3$                      OFFLINE          UNDOTBS1
_SYSSMU4$                      OFFLINE          UNDOTBS1
_SYSSMU5$                      OFFLINE          UNDOTBS1
_SYSSMU6$                      OFFLINE          UNDOTBS1
_SYSSMU7$                      OFFLINE          UNDOTBS1
_SYSSMU8$                      OFFLINE          UNDOTBS1
_SYSSMU9$                      OFFLINE          UNDOTBS1
_SYSSMU10$                     OFFLINE          UNDOTBS1

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
_SYSSMU11$                     OFFLINE          UNDOTBS2
_SYSSMU12$                     OFFLINE          UNDOTBS2
_SYSSMU13$                     OFFLINE          UNDOTBS2
_SYSSMU14$                     OFFLINE          UNDOTBS2
_SYSSMU15$                     OFFLINE          UNDOTBS2
_SYSSMU16$                     OFFLINE          UNDOTBS2
_SYSSMU17$                     OFFLINE          UNDOTBS2


SQL> alter system set undo_tablespace='UNDOTBS2';

系統已更改。

SQL> select usn,writes,rssize,xacts from v$rollstat;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         0       7572     385024          0
        11          0    1105920          0
        12          0    3399680          0
        13          0    1433600          0
        14          0    1564672          0
        15          0     909312          0
        16          0    1302528          0
        17          0     581632          0

已選擇8行。

SQL> select segment_name,status,tablespace_name from dba_rollback_segs;

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
SYSTEM                         ONLINE           SYSTEM
_SYSSMU1$                      NEEDS RECOVERY   UNDOTBS1
_SYSSMU2$                      NEEDS RECOVERY   UNDOTBS1
_SYSSMU3$                      OFFLINE          UNDOTBS1
_SYSSMU4$                      OFFLINE          UNDOTBS1
_SYSSMU5$                      OFFLINE          UNDOTBS1
_SYSSMU6$                      OFFLINE          UNDOTBS1
_SYSSMU7$                      OFFLINE          UNDOTBS1
_SYSSMU8$                      OFFLINE          UNDOTBS1
_SYSSMU9$                      OFFLINE          UNDOTBS1
_SYSSMU10$                     OFFLINE          UNDOTBS1

SEGMENT_NAME                   STATUS           TABLESPACE_NAME
------------------------------ ---------------- --------------------
_SYSSMU11$                     ONLINE           UNDOTBS2
_SYSSMU12$                     ONLINE           UNDOTBS2
_SYSSMU13$                     ONLINE           UNDOTBS2
_SYSSMU14$                     ONLINE           UNDOTBS2
_SYSSMU15$                     ONLINE           UNDOTBS2
_SYSSMU16$                     ONLINE           UNDOTBS2
_SYSSMU17$                     ONLINE           UNDOTBS2

已選擇18行。


SQL> update t2 set a=555;~~~其他操作可以 正常進行~~使用新的undo tablespace

已更新 1 行。

SQL> select usn,writes,rssize,xacts from v$rollstat;

       USN     WRITES     RSSIZE      XACTS
---------- ---------- ---------- ----------
         0       9604     385024          0
        11      11246    1105920          0
        12      14362    3399680          1
        13     110766    1630208          0
        14       8316    1499136          0
        15      15094     909312          0
        16      53506    1236992          0
        17       7964     581632          0

已選擇8行。

 

SQL> select *  from xh.t1;
select *  from xh.t1
                  *
第 1 行出現錯誤:
ORA-00376: 此時無法讀取檔案 2
ORA-01110: 資料檔案 2: 'F:\ORACLE\PRODUCT\10.2.0\ORADATA\XHTEST\UNDOTBS01.DBF'

此時 這個表經歷了instance recover 現在需要rollback階段,但使用的undo 資訊沒有了

 

SQL> drop tablespace undotbs1 including contents and datafiles;
drop tablespace undotbs1 including contents and datafiles
*
第 1 行出現錯誤:
ORA-01548: 已找到活動回退段 '_SYSSMU1$', 終止刪除表空間(且存在活動事務的話 ,不許刪除)

 


SQL> alter system set "_offline_rollback_segments"="_SYSSMU1$","_SYSSMU2$" scope
=spfile;

系統已更改。

 


SQL> alter system set undo_management='MANUAL' scope=spfile;

系統已更改。

SQL> startup force
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE 例程已經啟動。

Total System Global Area  289406976 bytes
Fixed Size                  1248576 bytes
Variable Size              83886784 bytes
Database Buffers          197132288 bytes
Redo Buffers                7139328 bytes
資料庫裝載完畢。
資料庫已經開啟。


SQL> drop rollback segment "_SYSSMU1$";

回退段已刪除。

SQL> drop rollback segment "_SYSSMU2$";

回退段已刪除。

SQL> drop tablespace undotbs1 including contents and datafiles;

表空間已刪除。

SQL> select * from xh.t1;

A          B
---------- ----------~~~~~~~~~~~
bbbb       a

可以看到 未提交的事務 變成已經提交了,造成 資料不一致,主要是instanc recover時 先是前滾階段,應用所有redo,包括提交 未提交的,然後open後進行後滾,此時後滾需要的undo資訊沒了,所以 無法完成,資料不一致.


SQL> alter system set undo_management='AUTO' scope=spfile;

系統已更改。


另外 也可以用
_corrupted_rollback_segments這個隱藏引數,與上面過程是一樣的

 

 

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

相關文章