继续上一篇文章,delayed block cleanout存在一些问题,下面列出问题,通过测试来分析delayed block cleanout过程中的一些变化会对delayed block cleanout有什么影响?并且redo,undo是如何变化的?
问题1、当出现事务递交前modified block就被flush回硬盘,此时没有提交事务,但是undo表空间被删除,紧接着做了回滚操作,此时modified block的原始数据从哪里获取?
问题2、假设在modified block被flush回硬盘之前,undo tablespace中的datablock的原始值的信息被覆盖,此时modified block被flush写回硬盘能够成功吗?
问题3: undo$系统表是专门用来记录什么信息的表?是记录数据块的信息还是记录块头信息?
实验1、理解undo$系统表,针对问题3
--删除表
drop table test;
--建表
create table test
pctfree 99
pctused 1
as
select rownum n1, rpad(rownum,200) v1
from all_objects
where rownum <= 1000 ;
--查询下信息
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from test where rownum=1;
DBMS_ROWID.ROWID_RELATIVE_FNO( DBMS_ROWID.ROWID_BLOCK_NUMBER(
------------------------------ ------------------------------
2 15730
--更新表,但先不提交
update test set n1=n1+1;
--强制将缓存中的数据块写进磁盘中去
ALTER SESSION SET EVENTS 'immediate trace name flush_cache';
--查看undo表空间信息
SQL> show parameter undo_tablespace
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTS2
--提交事务
commit;
--切换undo tablespace
alter system set undo_tablespace=UNDO_SMALL;
--删除旧的undo tablespace
DROP TABLESPACE UNDOTS2 INCLUDING CONTENTS AND DATAFILES;
--DUMP出data block的头信息,此时是在cleanout以前
alter system dump datafile 2 block 15730;
--cleanout
select count(*) from test;
--DUMP出data block的头信息,此时是在cleanout之后
alter system dump datafile 2 block 15730;
(注:介绍下Xid参数保存的信息
Xid是一个指向回滚段上的事务表上的槽的指针(undoseg#.slot#.wrap)。undoseg# 参数
表示回滚段,slot#表示事务表上的一个槽,并且wrap参数表示在一个事务中这个槽被使用
的次数。)
--比较cleanout前后DUMP出来的信息
--发生cleanout以前
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x0000 0000.0000.00 C--- 0 scn 0x 0000.002562f 2
0x02 0x 0013.01a .00000025 0x018000bd.0027.01 ---- 1 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x0000 0000.0000.00 ---- 0 fsc 0x0000.00000000
tl: 207 fb: --H-FL-- lb: 0x2 cc: 2
--发生cleanout之后:尽管原来的UNDO表空间已经被删除,但是经过延迟块清除之后,仍能够得到一个SCN,这个SCN表示什么意思呢?又是从哪里得来的?下面解释
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x0000 0000.0000.00 C--- 0 scn 0x 0000.002562f 2
0x02 0x 0013.01a .00000025 0x018000bd. 0027.01 C -U- 0 scn 0x 0000.002567a 6 --2451366
0x03 0x0000.000.00000000 0x0000 0000.0000.00 ---- 0 fsc 0x0000.00000000
tl: 207 fb: --H-FL-- lb: 0x0 cc: 2
在系统中有一个系统基表记录了系统中回滚段中的部分信息,这个表是undo$,可以在路径C:/oracle/product/ 10.2.0 /db_1/RDBMS/ADMIN下的sql.bsq文件中查找该undo$系统基表的定义以及表中每个字段的注释,定义如下:
create table undo$ /* undo segment table */
( us# number not null, /* undo segment number */
name varchar2("M_IDEN") not null, /* name of this undo segment */
user# number not null, /* owner: 0 = SYS(PRIVATE), 1 = PUBLIC */
file# number not null, /* segment header file number */
block# number not null, /* segment header block number */
scnbas number, /* highest commit time in rollback segment */
scnwrp number, /* scnbas - scn base, scnwrp - scn wrap */
xactsqn number, /* highest transaction sequence number */
undosqn number, /* highest undo block sequence number */
inst# number, /* parallel server instance that owns the segment */
status$ number not null, /* segment status (see KTS.H): */
/* 1 = INVALID, 2 = AVAILABLE, 3 = IN USE, 4 = OFFLINE, 5 = NEED RECOVERY,
* 6 = PARTLY AVAILABLE (contains in-doubt txs)
*/
ts# number, /* tablespace number */
ugrp# number, /* The undo group it belongs to */
keep number,
optimal number,
flags number,
spare1 number,
spare2 number,
spare3 number,
spare4 varchar2(1000),
spare5 varchar2(1000),
spare6 date
);
有兴趣的战友可以继续研究系统表,这个UNDO$表就介绍到此。
经过分析上面的ITL列表,可以看出ITL=0X02是当前的活动事务,其Xid为0x 0013.01a .00000025,其中0x0013表示回滚段的段头,通过这个编号在undo$表中查询相关的回滚段的信息,如下:
SQL> select name,SCNBAS,file#,block# from undo$ where name='_SYSSMU19$'; --2451366
NAME SCNBAS FILE# BLOCK#
------------------------------ ---------- ---------- ----------
_SYSSMU19$ 2451366 6 137
SQL> alter system dump datafile 6 block 137;--DUMP这个系统基表所在数据块中的信息
System altered
*** 2008-05-04 20:37:58.500
alter system dump datafile/tempfile: file 6 not readable –但是具体的信息oracle是不允许访问的,没有DUMP出来详细的信息
SQL> SELECT * FROM test
2 as of SCN 2451366 ; --使用回闪查询来查询在SCN=2451366点上的表信息,查询出来得到的结果是更新之后的信息,也就是说在更新之前的信息已经被覆盖掉
N1 V1
---------- --------------------------------------------------------------------------------
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
。。。
999 998
1000 999
1001 1000
1000 rows selected
SQL> SELECT * FROM test
2 as of SCN 2451365 ;(<2451366)--将SCN缩小到小于2451366,则出现ORA-01555快照过旧的错误,说明已经在回滚段中已经不存表在更新之前的表信息,更新之前的表信息已经被覆盖,此时可以确定SCN=2451366为当前的upper bound scn,当前回滚段中没有比这个SCN再小的SCN了,这个SCN已经是数据库能够恢复的最早的SCN
SELECT * FROM test
as of SCN 2451365
ORA-01555: 快照过旧: 回退段号 19 (名称为 "_SYSSMU19$") 过小
对上面的实验产生一个问题:就是回闪查询得到的数据是如何得到的?是从哪里得到的?是undo$系统表中的吗?是不是在系统更新的时候会将UNDO项同时插入到回滚段和系统表undo$中吗?还是原来的回滚段中的信息转移到undo$系统表中的呢?
实验2、针对产生的问题测试如下:
--查看跟踪文件可以看到这个alter操作内部都做了什么,来确定这些DDL语句做了什么?
步骤如下:
SQL> alter session set events '10046 trace name context forever,level 14';
会话已更改。
SQL> alter system set undo_tablespace=UNDO_SMALL;--alter system set remote_login_passwordfile=none scope=spfile;
系统已更改。
SQL> alter session set events '10046 trace name context off';
会话已更改。
--查看DUMP文件如下:
*** 2008-05-04 22:28:10.328
=====================
PARSING IN CURSOR #14 len=70 dep=0 uid=65 oct=42 lid=65 tim=6482826468 hv=1349202016 ad='259e5160'
alter session set events '10046 trace name context forever,level 14'
END OF STMT
EXEC #14:c=0,e=54,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=6482826465
WAIT #14: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=54517 tim=6482826551
WAIT #14: nam='SQL*Net message from client' ela= 27729 driver id=1413697536 #bytes=1 p3=0 obj#=54517 tim=6482854305
=====================
.....
=====================
PARSING IN CURSOR #11 len=44 dep=0 uid=65 oct=49 lid=65 tim=6486442627 hv=2472468311 ad=' 2569a 588'
alter system set undo_tablespace=UNDO_SMALL
END OF STMT
PARSE #11:c=0,e=309,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=6486442624
BINDS #11:
XCTEND rlbk=0, rd_only=1 -- XCTEND rlbk=0, rd_only=1:表示commit
-- XCTEND rlbk=1, rd_only=1: 表示rollback.
=====================
......
=====================
PARSING IN CURSOR #13 len=148 dep=1 uid=0 oct=6 lid=0 tim=6486492876 hv=3540833987 ad='33ec8e30'
update undo$ set name=:2,file#=:3,block#=:4,status$=:5,user#=:6,undosqn=:7,xactsqn=:8,scnbas=:9,scnwrp=:10,inst#=:11,ts#=:12,spare1=:13 where us#=:1 –更新了undo$系统基表的信息
END OF STMT
PARSE #13:c=31250,e=49926,p=12,cr=68,cu=0,mis=1,r=0,dep=1,og=4,tim=6486492873
BINDS #13:
kkscoacd
Bind#0
oacdty=01 mxl=32(09) mxlc=00 mal=00 scl=00 pre=00
oacflg=18 fl2=0001 frm=01 csi=852 siz=32 off=0
kxsbbbfp=33ed4cb2 bln=32 avl=09 flg=09
value="_SYSSMU1$"
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2328c 4 bln=24 avl=02 flg=05
value=7
Bind#2
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2328a 0 bln=24 avl=02 flg=05
value=9
Bind#3
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 23287c bln=24 avl=02 flg=05
value=2
Bind#4
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 232858 bln=24 avl=02 flg=05
value=1
Bind#5
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 232834 bln=24 avl=03 flg=05
value=519
Bind#6
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 232810 bln=24 avl=03 flg=05
value=1041
Bind#7
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2327ec bln=24 avl=05 flg=05
value=2465980
Bind#8
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2327c 8 bln=24 avl=01 flg=05
value=0
Bind#9
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2327a 4 bln=24 avl=01 flg=05
value=0
Bind#10
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 232780 bln=24 avl=02 flg=05
value=10
Bind#11
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 23275c bln=24 avl=02 flg=05
value=1
Bind#12
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0
kxsbbbfp= 0c 2328e8 bln=22 avl=02 flg=05
value=1
WAIT #13: nam='db file sequential read' ela= 233 file#=1 block#=202 blocks=1 obj#=54517 tim=6486494597
WAIT #13: nam='db file sequential read' ela= 2483 file#=1 block#=106 blocks=1 obj#=54517 tim=6486497143
WAIT #13: nam='db file sequential read' ela= 7947 file#=1 block#=9 blocks=1 obj#=54517 tim=6486505167
WAIT #13: nam='db file sequential read' ela= 1614 file#=1 block#=403 blocks=1 obj#=54517 tim=6486506833
EXEC #13:c=15625,e=13965,p=4,cr=1,cu=3,mis=1,r=1,dep=1,og=4,tim=6486506933
STAT #13 id=1 cnt=1 pid=0 pos=1 obj=0 op='UPDATE UNDO$ (cr=1 pr=4 pw=0 time=12597 us)'
STAT #13 id=2 cnt=1 pid=1 pos=1 obj=34 op='INDEX UNIQUE SCAN I_UNDO1 (cr=1 pr=1 pw=0 time=308 us)'
WAIT #11: nam='db file sequential read' ela= 14410 file#=7 block#=9 blocks=1 obj#=0 tim=6486560235
=====================
....
=====================
PARSING IN CURSOR #10 len=56 dep=0 uid=65 oct=42 lid=65 tim=6489733238 hv=3193596740 ad='259e4e40'
alter session set events '10046 trace name context off'
END OF STMT
PARSE #10:c=0,e=242,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=6489733236
BINDS #10:
EXEC #10:c=0,e=58,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6489733338
分析:发现在DUMP出来的文件中有20个对undo$表中记录的更新信息,说明在做alter system set undo_tablespace=UNDO_SMALLDDL语句时,实质上做了隐式的提交工作,并且也及时更新了数据字典中一些系统基表中的信息,如:对undo$表做了更新操作。此时猜测是在做UNDO表空间切换时,oracle将原来的回滚段上的信息及时地更新到undo$系统表中去。不是原先想的对原回滚段和undo$系统表都插入undo项。
实验3、针对问题1的实验
--删除表
drop table test;
--建表
create table test
pctfree 99
pctused 1
as
select rownum n1, rpad(rownum,200) v1
from all_objects
where rownum <= 1000 ;
--查询下信息
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid), dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from test where rownum=1;
DBMS_ROWID.ROWID_RELATIVE_FNO( DBMS_ROWID.ROWID_BLOCK_NUMBER(
------------------------------ ------------------------------
2 994
--查看undo表空间信息
SQL> show parameter undo_tablespace
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDO_SMALL
--更新表,但先不提交
update test set n1=n1+1;
--强制将缓存中的数据块写进磁盘中去
ALTER SESSION SET EVENTS 'immediate trace name flush_cache';
--下面一语句在另一个会话中完成,否则会提交之前的更新事务
SQL> alter system set undo_tablespace=undots3;
System altered
--查看undo表空间信息
SQL> show parameter undo_tablespace
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTS3
--删除UNDO表空间
SQL> DROP TABLESPACE UNDO_SMALL INCLUDING CONTENTS AND DATAFILES;
DROP TABLESPACE UNDO_SMALL INCLUDING CONTENTS AND DATAFILES
ORA-30013: 还原表空间 'UNDO_SMALL' 当前正在使用中
此时报错:ORA-30013: 还原表空间 'UNDO_SMALL' 当前正在使用中
表示在事务还没有提交之前,删除UNDO表空间是不允许的,因为此时更新事务仍然占用着UNDO表空间中一部分空间资源,
但是此时想删除UNDO表空间需要等待更新事务释放所占用的UNDO表空间中的资源。
--下面就无法完成回滚原来更新的数据的工作
rollback;
实验4、针对问题2
明天继续:)