无备份情况下恢复数据文件
如果新建了数据文件之后,还没备份的情况下,数据文件丢失。可以通过控制文件和数据字典的帮助下,通过重做日志文件恢复。仅限普通数据文件,且归档日志,重做日志不缺失的情况下。
--前提:数据库运行在archivelog模式下。且从穿件数据文件到丢失这一段时间的归档日志,重做日志必须都存在。
1、新建一个包含5m大小数据文件的表空间,然后在其上创建对象 插入数据。然后模拟数据文件损坏或者丢失(这两种情况,都可以当做数据文件丢失来处理)
SQL> create tablespace test_tbs3 datafile '/u01/app/oracle/oradata/orcl/test_tbs03.dbf' size 5m;
Tablespace created.
SQL> create table test_b (id number,name varchar2(10)) tablespace test_tbs3;
Table created.
SQL> begin
2 for i in 1..1000 loop
3 insert into test_b values(i,'ABC'||i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> select count(1) from test_b;
COUNT(1)
----------
1000
2、关闭数据库,将test_tbs03.dbf删除,然后启动数据库
SQL> startup
ORACLE instance started.
Total System Global Area 709836800 bytes
Fixed Size 2231752 bytes
Variable Size 444596792 bytes
Database Buffers 260046848 bytes
Redo Buffers 2961408 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 12 - see DBWR trace file
ORA-01110: data file 12: '/u01/app/oracle/oradata/orcl/test_tbs03.dbf'
--由于新建的表空间,并没有立即对数据库备份。现在就是备份情况下恢复数据文件
恢复步骤:
1、使用alter database create dafafile 创建空白数据文件
2、通过recover datafile 命令,利用归档日志和重做日志,恢复自数据文件创建以来的修改。
#恢复
SQL> startup mount --现将数据库启动至mount状态
ORACLE instance started.
Total System Global Area 709836800 bytes
Fixed Size 2231752 bytes
Variable Size 444596792 bytes
Database Buffers 260046848 bytes
Redo Buffers 2961408 bytes
Database mounted.
SQL> alter database create datafile 12; --创建一个空白的丢失的12号数据文件(创建数据文件的具体数据来自控制文件和数据字典)
Database altered.
SQL> recover datafile 12; --对12号数据文件应用日志,恢复其创建以来的操作
Media recovery complete.
SQL> alter database open;
Database altered.
--可以想象,假如对数据文件12上的对象,在创建或者操作的时候,使用nologging操作,那么重做日志将不会记录这部分数据的改变,那么将会丢失数据。
测试:
接着上面创建的表空间以及对象
检测一下当前对象的状态:
SQL> select logging from dba_tables where table_name='TEST_B';
LOG
---
YES
SQL> SELECT COUNT(1) FROM TEST_B;
COUNT(1)
----------
1000
--可以得出结论:在对表TEST_B插入的前1000行数据,是在logging模式下插入的,重做日志记录了这部分的变化。
现将表的模式修改为logging 然后用直接方式向表中再插入1000行数据。
SQL> alter table test_b nologging;
Table altered.
SQL> insert /*+ append */ into test_b select * from test_b;
1000 rows created.
SQL> commit;
Commit complete.
SQL> select count(1) from test_b;
select count(1) from test_b
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 12, block # 136)
ORA-01110: data file 12: '/u01/app/oracle/oradata/orcl/test_tbs03.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option
--此时,数据库能打开,但是能对表TEST_B上进行操作。
提示有坏块,之前介绍的方式检测坏块
[oracle@linusfay orcl]$ dbv file =/u01/app/oracle/oradata/orcl/test_tbs03.dbf
DBVERIFY: Release 11.2.0.3.0 - Production on Tue Aug 13 12:05:24 2013
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
DBVERIFY - Verification starting : FILE = /u01/app/oracle/oradata/orcl/test_tbs03.dbf
DBV-00201: Block, DBA 50331784, marked corrupt for invalid redo application
DBV-00201: Block, DBA 50331785, marked corrupt for invalid redo application
DBV-00201: Block, DBA 50331786, marked corrupt for invalid redo application
DBVERIFY - Verification complete
Total Pages Examined : 640
Total Pages Processed (Data) : 5
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 133
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 502
Total Pages Marked Corrupt : 3
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 2155731 (0.2155731)
--试着修复
SQL> begin
2 dbms_repair.admin_tables (
3 table_name => 'REPAIR_TABLE',
4 table_type => dbms_repair.repair_table,
5 action => dbms_repair.create_action,
6 tablespace => 'SYSTEM');
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> declare
2 rpr_count int;
3 begin
4 rpr_count := 0;
5 dbms_repair.check_object (
6 schema_name => 'SYS',
7 object_name => 'TEST_B',
8 repair_table_name => 'REPAIR_TABLE',
9 corrupt_count => rpr_count);
10 dbms_output.put_line('repair count: ' || to_char(rpr_count));
11 end;
12 /
PL/SQL procedure successfully completed.
SQL> begin
2 dbms_repair.skip_corrupt_blocks (
3 schema_name => 'SYS',
4 object_name => 'TEST_B',
5 object_type => dbms_repair.table_object,
6 flags => dbms_repair.skip_flag);
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> select count(1) from test_b;
COUNT(1)
----------
1000 --丢失了后来插入的1000条数据
--通过使用dbms_repair包,设置跳过“坏块”,来“恢复”数据。但是这样做,看到了丢失了后来插入的1000条数据。因此,nologging模式下的操作一定要慎用。及时备份,不然有数据丢失的风险