system表空间的undo
默认system表空间会有一个单独的undo segment(usn为0)。其他表空间的事务不能使用它。缺省下undo tablespace会被分配10个undo segment,理论上一个段可以有多个事务,但Oracle的策略并不情愿如此,实验表明,对应并发的事务,通常每个事务会分配一个UNDO段,也就是说如果这10个段不够,Oracle会自动在增加段。
当数据库启动时,如果碰到undo数据文件损坏或不同步,可以将其offline,即只有一个系统表空间的undo也能进入系统,使数据字典得以维护,但不能对其他表空间做DML操作。
模拟数据库open下的undo损坏和修复
如果数据库打开状态下,undo损坏的话,比如现在使用的表空间为UNDOTBS2,它出现了介质损坏,那么数据库就不能继续DML操作了。如果这时UNDOTBS2表空间上还有active状态的事务(未提交),Oracle会将其下的所有段都标志位NEEDS RECOVERY,这是有备份可以恢复这个UNDOTBS2,但如果没有备份,你需要用新建的UNDO替代损坏的UNDO,那么损坏UNDO上的未提交事务也将不得不丢弃。但Oracle没有提供自动解决NEEDS RECOVERY的机制,如果你想删除这个损坏的NIDO表空间,必须另做处理(需要系统择时重启),我们模拟一下这种情况:
1.模拟undo丢失或损坏
查看当前使用的undo表空间
idle>show parameter undo;
可知当前使用表空间为UNDOTBS2
idle>show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2
idle>
scott用户下执行一条DML语句
update emp set sal=1000 where empno=7369;
scott@ORCL>update emp set sal=1000 where empno=7369;
1 row updated.
scott@ORCL>
cd到undo文件所存路径,更改undotbs02.dbf文件的文件名,模拟undo文件已丢失的场景
cd /opt/oracle/oradata/orcl
mv undotbs02.dbf undotbs02.bk
[oracle@db01 ~]$ cd /opt/oracle/oradata/orcl
[oracle@db01 orcl]$ ll
total 1649896
-rw-r-----. 1 oracle oinstall 9748480 Jun 26 21:34 con01
-rw-r--r--. 1 oracle oinstall 5787 Jun 26 21:18 con.trace
-rw-r-----. 1 oracle oinstall 10076160 Jul 27 15:06 control01.ctl
-rw-r-----. 1 oracle oinstall 104865792 Jul 27 11:34 example01.dbf
-rw-r-----. 1 oracle oinstall 52429312 Jul 27 15:06 redo01.log
-rw-r-----. 1 oracle oinstall 52429312 Jul 27 11:34 redo02.log
-rw-r-----. 1 oracle oinstall 52429312 Jul 27 11:34 redo03.log
-rw-r-----. 1 oracle oinstall 8389120 Jul 27 11:34 redo04.log
-rw-r-----. 1 oracle oinstall 566239232 Jul 27 15:06 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 723525632 Jul 27 15:05 system01.dbf
-rw-r-----. 1 oracle oinstall 20979712 Jun 26 19:13 temp01.dbf
-rw-r-----. 1 oracle oinstall 52436992 Jul 27 15:05 undotbs02.dbf
-rw-r-----. 1 oracle oinstall 38019072 Jul 27 13:55 users01.dbf
[oracle@db01 orcl]$
[oracle@db01 orcl]$ mv undotbs02.dbf undotbs02.bk
[oracle@db01 orcl]$ ll
total 1649896
-rw-r-----. 1 oracle oinstall 9748480 Jun 26 21:34 con01
-rw-r--r--. 1 oracle oinstall 5787 Jun 26 21:18 con.trace
-rw-r-----. 1 oracle oinstall 10076160 Jul 30 21:43 control01.ctl
-rw-r-----. 1 oracle oinstall 104865792 Jul 30 21:33 example01.dbf
-rw-r-----. 1 oracle oinstall 52429312 Jul 30 21:33 redo01.log
-rw-r-----. 1 oracle oinstall 52429312 Jul 30 21:33 redo02.log
-rw-r-----. 1 oracle oinstall 52429312 Jul 30 21:33 redo03.log
-rw-r-----. 1 oracle oinstall 8389120 Jul 30 21:42 redo04.log
-rw-r-----. 1 oracle oinstall 566239232 Jul 30 21:39 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 723525632 Jul 30 21:38 system01.dbf
-rw-r-----. 1 oracle oinstall 20979712 Jun 26 19:13 temp01.dbf
-rw-r-----. 1 oracle oinstall 52436992 Jul 30 21:40 undotbs02.bk
-rw-r-----. 1 oracle oinstall 38019072 Jul 30 21:40 users01.dbf
[oracle@db01 orcl]$
此时作检查点切换,或回滚都相继报错
检查点切换 : alter system checkpoint;
回滚 :rollback;
scott@ORCL>conn sys/oracle as sysdba;
ERROR:
ORA-02002: error while writing to audit trail
ORA-00604: error occurred at recursive SQL level 1
ORA-01116: error in opening database file 6
ORA-01110: data file 6: '/opt/oracle/oradata/orcl/undotbs02.dbf'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
Connected.
sys@ORCL>
sys@ORCL>
sys@ORCL>
sys@ORCL>alter system checkpoint;
ERROR:
ORA-03114: not connected to ORACLE
alter system checkpoint
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 6605
Session ID: 1 Serial number: 11
sys@ORCL>
2.解决办法
shutdown 数据库
shutdown immediate; 或 shutdown abort;
idle>shutdown abort;
ORACLE instance shut down.
idle>
重启数据库
startup; 或 startup mount;
idle>startup;
ORACLE instance started.
Total System Global Area 409194496 bytes
Fixed Size 2213856 bytes
Variable Size 310380576 bytes
Database Buffers 92274688 bytes
Redo Buffers 4325376 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/opt/oracle/oradata/orcl/undotbs02.dbf'
//看当前数据库状态
idle>select status from v$instance;
STATUS
------------
MOUNTED
idle>
查看当前undo表空间状态
select * from v$tablespace;
show parameter undo;
idle>select * from v$tablespace;
TS# NAME INC BIG FLA ENC
---------- ------------------------------ --- --- --- ---
0 SYSTEM YES NO YES
1 SYSAUX YES NO YES
4 USERS YES NO YES
6 EXAMPLE YES NO YES
3 TEMP NO NO YES
5 UNDOTBS2 YES NO YES
6 rows selected.
idle>show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2
查看数据文件检查点和数据文件头检查点
select file#
,checkpoint_change#
,name
from v$datafile
;(数据文件检查点:记录在控制文件中)
select file#
,checkpoint_change#
from v$datafile_header
;(数据文件头检查点:记录在数据文件中)
由下可知: 数据文件和控制文件的checkpoint_change对不上,一个是1744764,一个是0
数据库开启时,要检查这些检查点是否能对上,对的上,才能正常开启
idle>select file#,checkpoint_change#,name from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
NAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 1744764
/opt/oracle/oradata/orcl/system01.dbf
2 1744764
/opt/oracle/oradata/orcl/sysaux01.dbf
4 1744764
/opt/oracle/oradata/orcl/users01.dbf
5 1744764
/opt/oracle/oradata/orcl/example01.dbf
6 1744764
/opt/oracle/oradata/orcl/undotbs02.dbf
idle>
idle>select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 1745577
2 1745577
4 1745577
5 1745577
6 0
查看表空间的段信息
select * from v$rollname;
报错,查不了
idle>select * from v$rollname;
select * from v$rollname
*
ERROR at line 1:
ORA-01219: database not open: queries allowed on fixed tables/views only
正常思维是把数据给offline一下
但是这里alter database datafile 6 offline; 不好用了
idle>alter database datafile 6 offline;
alter database datafile 6 offline
*
ERROR at line 1:
ORA-01145: offline immediate disallowed unless media recovery enabled
idle>
idle>
idle>
idle>
idle>alter database datafile 6 offline;
alter database datafile 6 offline
*
ERROR at line 1:
ORA-01145: offline immediate disallowed unless media recovery enabled
idle>
idle>
idle>
idle>alter database UNDOTBS2 offline;
alter database UNDOTBS2 offline
*
ERROR at line 1:
ORA-02231: missing or invalid option to ALTER DATABASE
idle>
idle>
idle>alter tablespace UNDOTBS2 offline;
alter tablespace UNDOTBS2 offline
*
ERROR at line 1:
ORA-01109: database not open
idle>alter databse datafile '
2 ;
alter databse datafile '
*
ERROR at line 1:
ORA-00940: invalid ALTER command
idle>
idle>
idle>
idle>alter database datafile '/opt/oracle/oradata/undotbs02.dbf' offline;
alter database datafile '/opt/oracle/oradata/undotbs02.dbf' offline
*
ERROR at line 1:
ORA-01516: nonexistent log file, data file, or temporary file "/opt/oracle/oradata/undotbs02.dbf"
idle>alter tablespace UNDOTBS2 offline;
alter tablespace UNDOTBS2 offline
*
ERROR at line 1:
ORA-01109: database not open
idle>
按如下步骤offline drop undotbs02表空间
alter system set undo_management=manual scope=spfile;
shutdown immediate;
startup;
alter database datafile ‘/opt/oracle/oradata/orcl/undotbs02.dbf’ offline drop;
idle>alter system set undo_management=manual scope=spfile;
System altered.
idle>
idle>
idle>
idle>
idle>
idle>shutdown immediate;
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.
idle>
idle>
idle>
idle>startup;
ORACLE instance started.
Total System Global Area 409194496 bytes
Fixed Size 2213856 bytes
Variable Size 310380576 bytes
Database Buffers 92274688 bytes
Redo Buffers 4325376 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/opt/oracle/oradata/orcl/undotbs02.dbf'
idle>
idle>
idle>
idle>
idle>alter database datafile '/opt/oracle/oradata/orcl/undotbs02.dbf' offline dr op
2 /
Database altered.
idle>
idle>
idle>alter database open;
Database altered.
idle>
Reference:
http://www.itpub.net/thread-1812889-1-1.html
此时再查看rollname
select * from v$rollname;
idle>select * from v$rollname;
USN NAME
---------- ------------------------------
0 SYSTEM
idle>
scott用户下此时仍做不了DML操作
update emp set sal=1000;
报错如下
idle>update emp set sal=1000;
update emp set sal=1000
*
ERROR at line 1:
ORA-00942: table or view does not exist
idle>
sys用户下创建一个undo表空间
idle>create undo tablespace undotbs1 datafile '/opt/oracle/oradata/orcl/undotbs01.dbf' size 100M autoextend on next 50M maxsize unlimited;
Tablespace created.
idle>
查看现在使用的undo表空间
select * from v$tablespace;
idle>select * from v$tablespace;
TS# NAME INC BIG FLA ENC
---------- ------------------------------ --- --- --- ---
0 SYSTEM YES NO YES
1 SYSAUX YES NO YES
2 UNDOTBS1 YES NO YES
4 USERS YES NO YES
6 EXAMPLE YES NO YES
3 TEMP NO NO YES
5 UNDOTBS2 YES NO YES
7 rows selected.
idle>
show parameter undo
idle>show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string MANUAL
undo_retention integer 900
undo_tablespace string UNDOTBS2
idle>
select * from v$rollname;
idle>select * from v$rollname;
USN NAME
---------- ------------------------------
0 SYSTEM
idle>
conn scott/tiger;
update emp set sal = 1000
还是报错
scott@ORCL>update emp set sal = 1000;
update emp set sal = 1000
*
ERROR at line 1:
ORA-01552: cannot use system rollback segment for non-system tablespace 'USERS'
scott@ORCL>
sys用户下执行
select segment_name,status from dba_rollback_segs;
显示needsrecovery
sys@ORCL>select segment_name,status from dba_rollback_segs;
SEGMENT_NAME STATUS
------------------------------ ----------------
SYSTEM ONLINE
_SYSSMU10_3648379721$ OFFLINE
_SYSSMU9_1275578431$ OFFLINE
_SYSSMU8_3826739819$ OFFLINE
_SYSSMU7_2957964192$ OFFLINE
_SYSSMU6_1108593665$ OFFLINE
_SYSSMU5_1695433794$ OFFLINE
_SYSSMU4_3177103441$ OFFLINE
_SYSSMU3_2393473844$ OFFLINE
_SYSSMU2_2393246700$ OFFLINE
_SYSSMU1_4125566212$ OFFLINE
_SYSSMU20_2343668525$ NEEDS RECOVERY
_SYSSMU19_3332159894$ NEEDS RECOVERY
_SYSSMU18_337899998$ NEEDS RECOVERY
_SYSSMU17_3535887706$ NEEDS RECOVERY
_SYSSMU16_3980642801$ NEEDS RECOVERY
_SYSSMU15_3499720984$ NEEDS RECOVERY
_SYSSMU14_3150185878$ NEEDS RECOVERY
_SYSSMU13_1397975244$ NEEDS RECOVERY
_SYSSMU12_2905439648$ NEEDS RECOVERY
_SYSSMU11_4023443810$ NEEDS RECOVERY
21 rows selected.
sys@ORCL>
刚才undotbs2没有清,里面有执行的事务,
正常来讲应该删掉undotbs2
drop tablespace undotbs2 including contents and datafiles;
sys@ORCL>drop tablespace undotbs2 including contents and datafiles;
drop tablespace undotbs2 including contents and datafiles
*
ERROR at line 1:
ORA-01548: active rollback segment '_SYSSMU11_4023443810$' found, terminate dropping tablespace
sys@ORCL>
但是因为在undo文件丢失之前,undotbs2里面正好有正在执行的事务,所以有needsrecovery的内容,所以删不掉
解决办法:
如果有备份的话就把needs RECOVERY的内容恢复回来
如果没有备份,则使用oracle提供的隐含参数_CORRUPTED_ROLLBACK_SEGMENTS
这里没有备份,我们选择提供的隐含参数_CORRUPTED_ROLLBACK_SEGMENTS方法进行:
建立静态参数文件
SQL>create pfile from spfile;
sys@ORCL>create pfile from spfile;
File created.
sys@ORCL>
SQL>shutdown abort
sys@ORCL>shutdown abort;
ORACLE instance shut down.
sys@ORCL>
在静态参数文件里第一行插入以下内容,然后存盘
vi $ORACLE_HOME/dbs/initorcl.ora
_CORRUPTED_ROLLBACK_SEGMENTS=(_SYSSMU20_2343668525$,_SYSSMU19_3332159894$,_SYSSMU18_337899998$,_SYSSMU17_3535887706$,_SYSSMU16_3980642801$,_SYSSMU15_3499720984$,_SYSSMU14_3150185878$,_SYSSMU13_1397975244$,_SYSSMU12_2905439648$,_SYSSMU11_4023443810$)
再使静态参数文件启动数据库
startup pfile=’/opt/oracle/product/11.2.0/dbhome_1/dbs/initorcl.ora’;
sys@ORCL>startup pfile='/opt/oracle/product/11.2.0/dbhome_1/dbs/initorcl.ora';
ORACLE instance started.
Total System Global Area 409194496 bytes
Fixed Size 2213856 bytes
Variable Size 310380576 bytes
Database Buffers 92274688 bytes
Redo Buffers 4325376 bytes
Database mounted.
Database opened.
sys@ORCL>
依次进行回退段删除
例:
SQL>drop rollback segment “_SYSSMU11_1357956213$”;
sys@ORCL>drop rollback segment "_SYSSMU20_2343668525$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU19_3332159894$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU18_337899998$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU17_3535887706$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU16_3980642801$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU15_3499720984$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU14_3150185878$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU13_1397975244$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU12_2905439648$";
Rollback segment dropped.
sys@ORCL>drop rollback segment "_SYSSMU11_4023443810$";
Rollback segment dropped.
sys@ORCL>
select segment_name,status from dba_rollback_segs;
sys@ORCL>select segment_name,status from dba_rollback_segs;
SEGMENT_NAME STATUS
------------------------------ ----------------
SYSTEM ONLINE
_SYSSMU10_3648379721$ OFFLINE
_SYSSMU9_1275578431$ OFFLINE
_SYSSMU8_3826739819$ OFFLINE
_SYSSMU7_2957964192$ OFFLINE
_SYSSMU6_1108593665$ OFFLINE
_SYSSMU5_1695433794$ OFFLINE
_SYSSMU4_3177103441$ OFFLINE
_SYSSMU3_2393473844$ OFFLINE
_SYSSMU2_2393246700$ OFFLINE
_SYSSMU1_4125566212$ OFFLINE
11 rows selected.
sys@ORCL>
此时可以正常删除表空间了
SQL> drop tablespace undotbs2 including contents and datafiles;
sys@ORCL>drop tablespace undotbs2 including contents and datafiles;
Tablespace dropped.
sys@ORCL>
如果还删除不了,则尝试修改字典 select * from v$tablespace; 记下要删除的undo对应的ts#号,比如是=2,则执行下行语句: 然后再删除该表空间即可。 update seg$ set type# = 3 where ts#=2
到这里就完成了