您的位置:首页 > 数据库 > Oracle

oracle 10G 详细分析undo

2010-10-26 22:00 260 查看
转自:http://space.itpub.net/12020513/viewspace-617904

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 <现在块中的ITL中记载的SCN,那么将制造CR 块(consistent read block),按下面的方式

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这个隐藏参数,与上面过程是一样的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: