Oracle 没有备份如何恢复UNDO撤销表空间

如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!

诗檀软件专业数据库修复团队

服务热线 : 13764045638    QQ号:47079569    邮箱:service@parnassusdata.com

 

今天的文章是关于从丢失的UNDO数据文件中恢复数据库(如果没有可用的备份)。理想情况下,我们为PRODPRE-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

*

沪ICP备14014813号-2

沪公网安备 31010802001379号