如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!
诗檀软件专业数据库修复团队
服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com
今天的文章是关于从丢失的UNDO数据文件中恢复数据库(如果没有可用的备份)。理想情况下,我们为PROD和PRE-PROD环境保存数据库的备份。然而,大多数机构并没有为低环境(开发,测试)数据库保留备份,因为这些数据库中的数据不很重要,比不上维持一个备份所产生的额外费用。
当没有可用备份时,我们讨论从丢失的UNDO数据文件恢复数据库的两种情形。I will discuss two scenarios related to recovering a database from a UNDO datafile loss when there is no backup available.
情形1:数据库关机,处于维护的一致状态。维修后,不知何故UNDO数据文件失踪或者被损坏。我们需要恢复数据库,并使它处于功能状态。
情形 2: 数据库崩溃,处于不一致状态。启动时,发现UNDO数据文件丢失或损坏。
当数据库处于一致状态
一直以来,该数据库处于一致状态,我们不需要用UNDO 或 REDO数据(因为没有必要实例恢复)来打开数据库。我可以装入数据库(我无法打开数据库,因为在尝试访问UNDO数据文件时DBWR会出错),改变UNDO管理为手动(回到SYSTEM表空间 ROLLBACK 段的原状),在MOUNT状态下删除UNDO数据文件(就是丢失),然后打开数据库。一旦用MANUAL ROLLBACK 段打开数据库,我们就可以用简单的“CREATE UNDO TABLESPACE” 命令创建一个新的UNDO表空间,并将其分配到数据库中,可以恢复到AUTO UNDO 管理。
这里,我只是模拟UNDO数据文件丢失,同时数据库处于一致状态。我们来看一下数据库中当前的数据文件列表。
—//
—// list of datafiles //—
—//
sys@LABDB> select name from v$datafile;
NAME
————————————————
+DATA/LABDB/DATAFILE/system.257.860815555
/app/oracle/data/prodcdb/users1.dbf
+DATA/LABDB/DATAFILE/sysaux.256.860815491
+DATA/LABDB/DATAFILE/undotbs1.259.860815623
+DATA/LABDB/DATAFILE/users.258.860815621
关闭数据库,使之处于一致状态.
—//
—// bringing down database in consistent state //—
—//
sys@LABDB> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
sys@LABDB>
手动删除UNDO数据文件,模拟UNDO数据文件丢失。
—//
—// simulating UNDO loss //—
—//
[oracle@labserver ~]$ asmcmd
ASMCMD> cd +DATA/LABDB/DATAFILE/
ASMCMD> ls
SYSAUX.256.860815491
SYSTEM.257.860815555
UNDOTBS1.259.860815623
USERS.258.860815621
ASMCMD> rm UNDOTBS1.259.860815623
ASMCMD>
现在,试着启动数据库。
—//
—// not able to locate UNDO file //—
—//
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 4 – see DBWR trace file
ORA-01110: data file 4: ‘+DATA/LABDB/DATAFILE/undotbs1.259.860815623’
正如预期的那样,DBWR不能够识别记录在控制文件中的UNDO数据文件。我们将UNDO管理从自动更改为手动。
—//
—// change UNDO management to MANUAL //—
—//
SQL> show parameter undo
NAME TYPE VALUE
———————————— ———– ——————————
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> alter system set undo_management=MANUAL scope=spfile;
System altered.
现在,试着启动数据库。
—//
—// not able to start database //—
—//
SQL> startup force
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 4 – see DBWR trace file
ORA-01110: data file 4: ‘+DATA/LABDB/DATAFILE/undotbs1.259.860815623’
我们还是收到了DBWR错误,因为UNDO数据文件条目位于控制文件中。我们放下丢失的UNDO数据文件,并试着打开数据库。
—//
—// drop missing UNDO file //—
—//
SQL> alter database datafile 4 offline drop;
Database altered.
SQL> alter database open;
Database altered.
这里,数据库回到运行状态。但是它现在使用回滚段(而不是UNDO),因为我们已经将UNDO管理改变了为手动。
我们可以删除并重建丢失的UNDO表空间,或者完全可以创造一个新的UNDO表空间,并将其分配给数据库进行自动UNDO管理。
—//
—// recreate UNDO with AUTO management //—
—//
SQL> drop tablespace UNDOTBS1;
Tablespace dropped.
SQL> create undo tablespace UNDOTBS1;
Tablespace created.
SQL> alter system set undo_management=AUTO scope=spfile;
System altered.
SQL> startup force
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
Database opened.
SQL> show parameter UNDO
NAME TYPE VALUE
———————————— ———– ——————————
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
数据库现在已经完全回到操作状态,UNDO管理为自动。
我们再来看一下其他恢复情形,其中数据库处于不一致的状态。
当数据库处于不一致状态
注:若没有咨询Oracle支持,请不要尝试此方法,因为这种方法涉及改变未公开的数据库参数并有可能导致数据逻辑不一致
我们检查一下可用的数据文件列表:
—//
—// list of datafiles //—
—//
SQL> select name from v$datafile;
NAME
———————————————
+DATA/LABDB/DATAFILE/system.257.860815555
/app/oracle/data/prodcdb/users1.dbf
+DATA/LABDB/DATAFILE/sysaux.256.860815491
+DATA/LABDB/DATAFILE/undotbs1.424.866401917
+DATA/LABDB/DATAFILE/users.258.860815621
针对数据库,我们执行一些DML
—//
—// perform uncommitted DMLs //—
—//
SQL> insert into TEST_REDACT.CREDIT_CARD_INFO (ENROLL_DATE,CARD_NO,EXP_DATE,CARD_STR)
2 values (sysdate,1234123412341234,sysdate+365,’1234-1234-1234-1234′);
1 row created.
SQL> insert into TEST_REDACT.CREDIT_CARD_INFO (ENROLL_DATE,CARD_NO,EXP_DATE,CARD_STR)
2 values (sysdate,5678567856785678,sysdate+365,’5678-5678-5678-5678′);
1 row created.
—// Note, I have not committed the changes //—
—// Lets bring down the database in a INCONSISTENT state with SHUT ABORT //—
SQL> shut abort
ORACLE instance shut down.
SQL>
现在,手动删除UNDO数据文件以模拟的它丢失。Now, lets simulate the loss of UNDO datafile by manually deleting it.
—//
—// simulate loss of UNDO file //—
—//
[oracle@labserver ~]$ asmcmd
ASMCMD> cd +DATA/LABDB/DATAFILE
ASMCMD> ls
SYSAUX.256.860815491
SYSTEM.257.860815555
UNDOTBS1.424.866401917
USERS.258.860815621
ASMCMD> rm UNDOTBS1.424.866401917
现在我们来尝试,是否能打开数据库。
—//
—// DB startup is failing //—
—//
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 4 – see DBWR trace file
ORA-01110: data file 4: ‘+DATA/LABDB/DATAFILE/undotbs1.424.866401917’
跟之前的情况一样,DBWR不能够识别UNDO数据文件。
我们使用同样的方法,就是之前已经用于一致状态的数据库的方法,即把UNDO管理改为手动。
—//
—// change UNDO management to MANUAL //—
—//
SQL> show parameter undo
NAME TYPE VALUE
———————————— ———– ——————————
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> alter system set undo_management=MANUAL scope=spfile;
System altered.
—//
—// drop missing UNDO file //—
—//
SQL> alter database datafile 4 offline drop;
Database altered.
—//
—// start database //—
—//
SQL> shut immediate
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
Database opened.
我们使用这一种方法就可以将数据库带回运行状态,无论数据库处于一致或不一致的的状态。
真的是这样吗?回想一下,在数据库进入不一致状态之前,针对数据库我们所做的交易(未提交的更新)。我们看一下,从表中查询时会发现什么。
—//
—// not able to query database //—
—//
SQL> select * from TEST_REDACT.CREDIT_CARD_INFO;
select * from TEST_REDACT.CREDIT_CARD_INFO
*
ERROR at line 1:
ORA-00376: file 4 cannot be read at this time
ORA-01110: data file 4: ‘+DATA/LABDB/DATAFILE/undotbs1.424.866401917’
什么?不能查询执行交易的表。该数据库正在寻找丢失的UNDO数据文件。
但为什么?这是因为在更新表的同时,数据一致快照的读取在UNDO段被捕获。
我们看看是否能够摆脱数据快照,并查看当前的数据块中有什么。
—//
—// active rollback segments exist //—
—//
SQL> drop tablespace UNDOTBS1;
drop tablespace UNDOTBS1
*
ERROR at line 1:
ORA-01548: active rollback segment ‘_SYSSMU11_2842692639$’ found, terminate dropping tablespace
不,我们不被允许删除UNDO表空间,因为它有活性回滚段。我们来看看丢失的UNDO数据文件中都有什么回滚段。
—//
—// list of active rollback segments //—
—//
SQL> select segment_name, tablespace_name, status from dba_rollback_segs where tablespace_name=’UNDOTBS1′;
SEGMENT_NAME TABLESPACE_NAME STATUS
—————————— —————————— —————-
_SYSSMU11_2842692639$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU12_3631842673$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU13_543390606$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU14_1141270304$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU15_4256630628$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU16_1706077410$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU17_2943159071$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU18_4202619447$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU19_437051883$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU20_3541319746$ UNDOTBS1 NEEDS RECOVERY
10 rows selected.
尝试删除这些丢失的回滚段。
—//
—// not allowed to drop active rollback segments //—
—//
SQL> select ‘drop rollback segment “‘||segment_name||'”;’ from dba_rollback_segs where tablespace_name=’UNDOTBS1′;
‘DROPROLLBACKSEGMENT”‘||SEGMENT_NAME||'”;’
——————————————————-
drop rollback segment “_SYSSMU11_2842692639$”;
drop rollback segment “_SYSSMU12_3631842673$”;
drop rollback segment “_SYSSMU13_543390606$”;
drop rollback segment “_SYSSMU14_1141270304$”;
drop rollback segment “_SYSSMU15_4256630628$”;
drop rollback segment “_SYSSMU16_1706077410$”;
drop rollback segment “_SYSSMU17_2943159071$”;
drop rollback segment “_SYSSMU18_4202619447$”;
drop rollback segment “_SYSSMU19_437051883$”;
drop rollback segment “_SYSSMU20_3541319746$”;
10 rows selected.
SQL> drop rollback segment “_SYSSMU11_2842692639$”;
drop rollback segment “_SYSSMU11_2842692639$”
*
ERROR at line 1:
ORA-30025: DROP segment ‘_SYSSMU11_2842692639$’ (in undo tablespace) not allowed
不允许删除活性回滚段。
这里,我们需要将丢失的UNDO数据文件中的这些活性回滚段标记为离线。一旦回滚段被标记为离线,我们很容易就可以将其关闭。但是,如何将它们标记离线呢。
可以通过一个名为_offline_rollback_segments的未公开参数来完成。列出需要被标记为离线的所有回滚段(从上一步中找到),分配这个隐藏的参数。
—//
—// mark active rollback segments as OFFLINE //—
—//
SQL> alter system set “_offline_rollback_segments”=’_SYSSMU11_2842692639$’,’_SYSSMU12_3631842673$’,’_SYSSMU13_543390606$’,’_SYSSMU14_1141270304$’,’_SYSSMU15_4256630628$’,’_SYSSMU16_1706077410$’,’_SYSSMU17_2943159071$’,’_SYSSMU18_4202619447$’,’_SYSSMU19_437051883$’,’_SYSSMU20_3541319746$’ scope=spfile;
System altered.
—//
—// restart database //—
—//
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
Database opened.
现在,我们轻易就可以删除属于丢失的UNDO数据文件的回滚段。
—//
—// drop all the marked active rollback segments //—
—//
SQL> select ‘drop rollback segment “‘||segment_name||'”;’ from dba_rollback_segs where tablespace_name=’UNDOTBS1′;
‘DROPROLLBACKSEGMENT”‘||SEGMENT_NAME||'”;’
——————————————————-
drop rollback segment “_SYSSMU11_2842692639$”;
drop rollback segment “_SYSSMU12_3631842673$”;
drop rollback segment “_SYSSMU13_543390606$”;
drop rollback segment “_SYSSMU14_1141270304$”;
drop rollback segment “_SYSSMU15_4256630628$”;
drop rollback segment “_SYSSMU16_1706077410$”;
drop rollback segment “_SYSSMU17_2943159071$”;
drop rollback segment “_SYSSMU18_4202619447$”;
drop rollback segment “_SYSSMU19_437051883$”;
drop rollback segment “_SYSSMU20_3541319746$”;
10 rows selected.
SQL> drop rollback segment “_SYSSMU11_2842692639$”;
drop rollback segment “_SYSSMU12_3631842673$”;
drop rollback segment “_SYSSMU13_543390606$”;
drop rollback segment “_SYSSMU14_1141270304$”;
drop rollback segment “_SYSSMU15_4256630628$”;
drop rollback segment “_SYSSMU16_1706077410$”;
drop rollback segment “_SYSSMU17_2943159071$”;
drop rollback segment “_SYSSMU18_4202619447$”;
drop rollback segment “_SYSSMU19_437051883$”;
drop rollback segment “_SYSSMU20_3541319746$”;
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
Rollback segment dropped.
SQL>
现在,我们可以删除丢失的UNDO表空间,并为数据库自动UNDO管理创建新的UNDO表空间。
—//
—// recreate missing UNDO with AUTO management //—
—//
SQL> drop tablespace UNDOTBS1;
Tablespace dropped.
SQL> create undo tablespace UNDOTBS2;
Tablespace created.
SQL> show parameter undo
NAME TYPE VALUE
———————————— ———– ——————————
temp_undo_enabled boolean FALSE
undo_management string MANUAL
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> alter system set undo_tablespace=’UNDOTBS2′ scope=spfile;
System altered.
SQL> alter system set undo_management=AUTO scope=spfile;
System altered.
—//
—// restart database //—
—//
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
Database opened.
SQL>
现在,我们看看丢失UNDO段的表怎么了。
—//
—// validate database can be queried //—
—//
SQL> select * from TEST_REDACT.CREDIT_CARD_INFO;
CUST_ID ENROLL_DA CARD_NO EXP_DATE CARD_STR
———- ——— —————————— ——— ——————————
1021 15-DEC-14 5678567856785678 15-DEC-14 5678-5678-5678-5678
1020 15-DEC-14 1234123412341234 15-DEC-15 1234-1234-1234-1234
1001 08-NOV-14 1285145836589848 08-NOV-17 1285-1458-3658-9848
1002 08-NOV-14 7844896487984154 08-NOV-17 7844-8964-8798-4154
1003 08-NOV-14 8554884663181228 08-NOV-17 8554-8846-6318-1228
1004 08-NOV-14 9487545796548985 08-NOV-17 9487-5457-9654-8985
我们有未提交的数据。这是因为运用了UNDO,但没有UNDO来回滚未提交的事务。数据库现在回到操作状态。但是,由于丢失了活性回滚段,数据库在未提交的事务中发生变化。
现在,我们可以从参数文件重置未公开的参数,从而摆脱掉它。
—//
—// reset undocumented parameter //—
—//
SQL> alter system reset “_offline_rollback_segments”;
System altered.
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 626327552 bytes
Fixed Size 2291472 bytes
Variable Size 276826352 bytes
Database Buffers 343932928 bytes
Redo Buffers 3276800 bytes
Database mounted.
Database opened.
SQL> show parameter undo
NAME TYPE VALUE
———————————— ———– ——————————
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2
SQL>
结论
我们总能恢复丢失的UNDO数据文件,即使没有可用的备份。但是,我们可能在数据库中收到不需要(不一致)的数据,这取决于数据库的运行状态。
Comment