Oracle的Undo有两种方式:一是使用undo表空间,二是使用回滚段.
我们通过undo_management参数来控制使用哪种方式,如果设为auto,就使用UNDO表空间,这时必须要指定一个UNDO表空间。如果设为manual,系统启动后使用rollbacksegment方式存储undo信息。如果系统没有指定undo_management,那么系统默认以manual方式启动,即使设置了auto方式的参数,这些参数将被忽略。
当实例启动的时候,系统自动选择第一个有效的undo表空间或者是rollbacksegment,如果没有有效的可用的undo表空间或者是回滚段,系统使用systemrollbacksegment。这种情况是不被推荐的,当系统运行在没有undo的情况下,系统会在alert.log中记录一条警告信息。
SQL>showparameterundo
NAMETYPEVALUE
-----------------------------------------------------------------
undo_managementstringAUTO
undo_retentioninteger900
undo_tablespacestringUNDOTBS1
参考:Oracleundo管理
http://blog.csdn.net/tianlesoftware/archive/2009/11/30/4901666.aspx
一.UNDO表空间
下面来看一下undo的表空间管理。先来查看一下表空间的使用情况:
/*Formattedon2010/6/239:46:58(QP5v5.115.810.9015)*/
SELECTa.tablespace_name,
ROUND(a.total_size)"total_size(MB)",
ROUND(a.total_size)-ROUND(b.free_size,3)"used_size(MB)",
ROUND(b.free_size,3)"free_size(MB)",
ROUND(b.free_size/total_size*100,2)||'%'free_rate
FROM(SELECTtablespace_name,SUM(bytes)/1024/1024total_size
FROMdba_data_files
GROUPBYtablespace_name)a,
(SELECTtablespace_name,SUM(bytes)/1024/1024free_size
FROMdba_free_space
GROUPBYtablespace_name)b
WHEREa.tablespace_name=b.tablespace_name(+);
TABLESPACE_NAMEtotal_size(MB)used_size(MB)free_size(MB)FREE_RATE
--------------------------------------------------------------------------
SYSAUX580545.18734.813 6%
UNDOTBS19023.87566.125 73.47%
DAVE206.2513.75 68.75%
USERS108.3751.625 16.25%
SYSTEM960951.0628.938 93%
从结果我们看到UNDO表空间已经用了23.875M。我们看一下这使用的23M空间里空闲和非空闲比例:
/*Formattedon2010/6/239:49:53(QP5v5.115.810.9015)*/
SELECTtablespace_name,status,SUM(bytes)/1024/1024"Bytes(M)"
FROMdba_undo_extents
GROUPBYtablespace_name,status;
TABLESPACE_NAMESTATUSBytes(M)
---------------------------------------
UNDOTBS1UNEXPIRED9.1875
UNDOTBS1EXPIRED13.6875
我们看一下查询的结果,UNEXPIRED和EXPIRED 是已使用的undo表空间,其中expired说明是已经过期的数据,也就是15分钟(默认情况)以外的数据,以被覆盖,可以认为是空闲的。
在此补充一点知识:
采用UNDO表空间时,会有一个参数UNDO_RETENTION,该参数用来指定undo记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改,通常默认是900秒,也就是15分钟。
undo_retention只是指定undo数据的过期时间,并不是说,undo中的数据一定会在undo表空间中保存15分钟,比如说刚一个新事务开始的时候,如果undo表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建一个自动管理的undo表空间时,还要注意其空间大小,要尽可能保证undo表空间有足够的存储空间。
undo_retention中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention参数的值并不会影响到你,哪怕你设置成1,只要没有事务去覆盖undo数据,它就会持续有效。因此呢,这里还是那句话,要注意undo表空间的大小,保证其有足够的存储空间。
只有在一种情况下,undo表空间能够确保undo中的数据在undo_retention指定时间过期前一定有效,就是为undo表空间指定RetentionGuarantee,指定之后,oracle对于undo表空间中未过期的undo数据不会覆盖,例如:
SQL>Altertablespaceundotbs1retentionguarantee;
禁止undo表空间retentionguarantee,例如:
SQL>Altertablespaceundotbs1retentionnoguarantee;
总结一下:
UNDO表空间是会被重用的,只有当事务没结束,或开了retentionguarantee,或在undo_retention时间内不能被重用。
在undo_retention规定的时间内,数据都是有效的,过期后都会设为无效,状态被改为Expired,这些回滚段将会被看作FreeSpace。但是只要数据没有被覆盖就可以使用。如果空间已满,新事务的数据会自动覆盖掉已经提交的事务数据,即使在undo_retention的时间内。除非指定RetentionGuarantee模式,才能保证在undo_retention内不被覆盖。
二.UNDO表空间满了的处理方法
2.1先模拟UNDO表空间满的情况
SQL>altersystemsetundo_retention=10800;--3个小时
系统已更改。
SQL>createundotablespaceundodatafile'F:/backup/undo.dbf'size1m;
表空间已创建。
SQL>altertablespaceundoretentionguarantee;
表空间已更改。
SQL>altersystemsetundo_tablespace=undo;
系统已更改。
SQL>createtableDBA(idnumber);
表已创建。
SQL>begin
2foriin1..100000loop
3insertintodbavalues(i);
4commit;
5endloop;
6end;
7/
begin
*
第1行出现错误:
ORA-30036:无法按8扩展段(在还原表空间'UNDO'中)
ORA-06512:在line3
2.2处理方法
处理方法有两种,一是添加undo表空间的数据文件,二是切换UNDOtablespace.这种情况下多用在undo表空间已经非常大的情况。
2.2.1增加数据文件
SQL>ALTERTABLESPACEundoADDDATAFILE'F:/backup/undo02.dbf'size100Mreuse;
表空间已更改。
SQL>begin
2foriin1..100000loop
3insertintodbavalues(1);
4commit;
5endloop;
6end;
7/
PL/SQL过程已成功完成。
2.2.2切换UNDO表空间
1、建立新的表空间UNDOTBS2
SQL>CREATEUNDOTABLESPACEUNDOTBS2DATAFILE'F:/backup/undo03.dbf'size100Mreuse;
表空间已创建。
2、切换到新建的UNOD表空间上来,操作如下
SQL>altersystemsetundo_tablespace=UNDOTBS2scope=both;
系统已更改。
3、将原来的UNDO表空间,置为脱机:
SQL>altertablespaceUNDOoffline;
表空间已更改。
4、删除原来的UNDO表空间:
SQL>droptablespaceUNDOincludingcontentsANDDATAFILESCASCADECONSTRAINTS;
表空间已删除。
如果只是droptablespaceUNDO,则只会在删除控制文件里的记录,并不会物理删除文件。
Dropundo表空间的时候必须是在未使用的情况下才能进行。如果undo表空间正在使用(例如事务失败,但是还没有恢复成功),那么drop表空间命令将失败。在drop表空间的时候可以使用includingcontents。
三.UNDO表空间损坏的恢复方法
一般Undo表空间损坏的情况下,数据库都已不能正常打开了。启动时都会报类似如下的错误:
ORA-01157:cannotidentify/lockdatafile12-seeDBWRtracefile
ORA-01110:datafile12:'/d01/oramtest/proddata/undo01.dbf'
要想解决问题,必须重建UNDO表空间,但是如果不open,就不能重建创建undo表空间。所以可以先用系统默认的undo表空间:systemrollbacksegment来启动数据库,再创建UNDO表空间。
3.1创建pfile文件
SQL>createpfile='F:/initorcl.ora'fromspfile;
文件已创建。
3.2修改pfile文件
#*.undo_tablespace='UNDOTBS1'
#*.undo_management='AUTO'
undo_management='MANUAL'
rollback_segments='SYSTEM'
3.3启动数据库至Mount状态
SQL>STARTUPMOUNTpfile='F:/initorcl.ora';
3.4offlinedropundo表空间
SQL>ALTERDATABASEDATAFILE'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'OFFLINEDROP;
3.5open数据库
SQL>ALTERDATABASEOPEN;
3.6删除旧的undo表空间
SQL>DROPTABLESPACEUNDOTBS1INCLUDINGCONTENTS;
注:该命令不会删除物理文件。 要想一起删除物理文件需要ANDDATAFILESCASCADECONSTRAINTS;
如: droptablespaceUNDOTBS1includingcontentsANDDATAFILESCASCADECONSTRAINTS;
3.7创建新的UNDO表空间
SQL>createundotablespaceundotbs1datafile'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'size100M;
createundotablespaceundotbs1datafile'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'size100M
*
第1行出现错误:
ORA-01119:创建数据库文件'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'时出错
ORA-27038:所创建的文件已存在
OSD-04010:指定了<create>选项,但文件已经存在
因为我们之前删除时并没有删除物理文件,所以在建同名文件时就会报错。我们可以加上REUSE参数。只要文件不在使用,就可以重写已经存在的文件。
SQL>createundotablespaceundotbs1datafile'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'size100Mreuse;
表空间已创建。
3.8shutdown数据库并将pfile改回
SQL>selectname,issys_modifiablefromv$parameterwherename='undo_management'orname='rollback_segments';
NAMEISSYS_MOD
-----------------------------
rollback_segmentsFALSE
undo_managementFALSE
从上面查询的结果,可以知道修改这2个参数必须重启数据,所以还是shutdown吧。
SQL>shutdownimmediate
3.9修改pfile参数
*.undo_tablespace='UNDOTBS1'
*.undo_management='AUTO'
#undo_management='MANUAL'
#rollback_segments='SYSTEM'
3.10用刚才修改的pfile启动数据库,并创建spfile
SQL>startuppfile='F:/initorcl.ora';
SQL>createspfilefrompfile='F:/initorcl.ora';
3.10再次shutdown,用spfile启动.
SQL>shutdownimmediate
SQL>startup
一般数据文件损坏的情况也可以采用类似的方法,先启动到mount,在将损坏的数据文件offlinedrop。在open数据库,drop掉损坏的数据文件。当然这种做法有数据丢失。能恢复的话,尽量恢复。
------------------------------------------------------------------------------
Blog:http://blog.csdn.net/tianlesoftware
网上资源:http://tianlesoftware.download.csdn.net
相关视频:http://blog.csdn.net/tianlesoftware/archive/2009/11/27/4886500.aspx
DBA1群:62697716(满);DBA2群:62697977