暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

非归档下误删数据文件的处理

原创 xws237yxc 2020-06-22
746

今天接到个电话,说某省的一个非归档数据库中,为某个表空间添加数据文件时误操作,加成了文件系统(数据库是使用裸设备做数据文件的),当时处理的方式是直接在os级rm掉了这个数据文件。结果在oem里面点击表空间的时候就报数据文件找不到了。然后,另一个同事将该数据文件执行offline drop后,在oem里面点击表空间不报错了。

但是这是否就正常了呢?

我们说,表空间就像一个容器,像一个空的水杯,一旦我们把水倒进水杯里面,我们就分辨不出那些水是第一次倒入的,哪些是第二次倒入的。我们也无法把已经倒进去的水区别开来,把最后一次倒入的水在倒出来。

我们检查了那个数据文件说涉及到的表空间,将这个表空间下的所有的表都count()一遍,如果没有报错,那么我们比较幸运,那个被rm掉的文件里面没有数据,如果有数据,那就比较惨了……count()的结果表明:我们就是属于那种不幸的情况。

我们首先考虑恢复数据,由于是非规定模式,redolog就显得比较重要了。如果redolog没有使用一圈的话,我们还能用redolog来进行恢复:
$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Mon Jun 22 10:13:58 2020

Copyright © 1982, 2013, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

10:14:31 SQL> archive log list
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination /oracle/app/oracle/product/11.2.0/db_1/dbs/arch
Oldest online log sequence 6
Current log sequence 8
10:14:45 SQL> select * from v$log;

GROUP#    THREAD#  SEQUENCE#      BYTES  BLOCKSIZE    MEMBERS ARC STATUS    FIRST_CHANGE# FIRST_TIME          NEXT_CHANGE# NEXT_TIME

     1          1          7   52428800        512          1 NO  INACTIVE        1308836 2020/06/19 10:07:55      1341088 2020/06/20 02:59:03
     2          1          8   52428800        512          1 NO  CURRENT         1341088 2020/06/20 02:59:03   2.8147E+14
     3          1          6   52428800        512          1 NO  INACTIVE        1268214 2020/06/15 13:25:29      1308836 2020/06/19 10:07:55

10:16:03 SQL> create tablespace test01 datafile ‘/oracle/data/xws/test01.dbf’ size 1m;

Tablespace created.

10:17:15 SQL> create table ogg.users tablespace test01 as select * from dba_users where 1=2;

Table created.

10:17:27 SQL> insert into ogg.users select * from dba_users;

32 rows created.

10:17:56 SQL> /

32 rows created.

10:17:57 SQL> /

32 rows created.

10:17:57 SQL> /

32 rows created.

10:17:58 SQL> /

32 rows created.

10:17:59 SQL> commit;

Commit complete.

10:18:13 SQL> select count(1) from ogg.user;
select count(1) from ogg.user
*
ERROR at line 1:
ORA-00903: invalid table name

10:18:28 SQL> select count(1) from ogg.users;

COUNT(1)

   160

10:18:38 SQL> select * from v$log;

GROUP#    THREAD#  SEQUENCE#      BYTES  BLOCKSIZE    MEMBERS ARC STATUS    FIRST_CHANGE# FIRST_TIME          NEXT_CHANGE# NEXT_TIME

     1          1          7   52428800        512          1 NO  INACTIVE        1308836 2020/06/19 10:07:55      1341088 2020/06/20 02:59:03
     2          1          8   52428800        512          1 NO  CURRENT         1341088 2020/06/20 02:59:03   2.8147E+14
     3          1          6   52428800        512          1 NO  INACTIVE        1268214 2020/06/15 13:25:29      1308836 2020/06/19 10:07:55

[oracle@mycat data]$ cd xws/
[oracle@mycat xws]$ ls
control01.ctl control02.ctl redo01.log redo02.log redo03.log sysaux01.dbf system01.dbf temp01.dbf test01.dbf undotbs01.dbf users01.dbf
[oracle@mycat xws]$
[oracle@mycat xws]$
[oracle@mycat xws]$ ll
total 1843208
-rw-r----- 1 oracle oinstall 9748480 Jun 22 10:19 control01.ctl
-rw-r----- 1 oracle oinstall 9748480 Jun 22 10:19 control02.ctl
-rw-r----- 1 oracle oinstall 52429312 Jun 22 07:15 redo01.log
-rw-r----- 1 oracle oinstall 52429312 Jun 22 10:19 redo02.log
-rw-r----- 1 oracle oinstall 52429312 Jun 22 07:15 redo03.log
-rw-r----- 1 oracle oinstall 566239232 Jun 22 10:11 sysaux01.dbf
-rw-r----- 1 oracle oinstall 796925952 Jun 22 10:11 system01.dbf
-rw-r----- 1 oracle oinstall 56631296 Jun 20 06:59 temp01.dbf
-rw-r----- 1 oracle oinstall 1056768 Jun 22 10:16 test01.dbf
-rw-r----- 1 oracle oinstall 104865792 Jun 22 10:11 undotbs01.dbf
-rw-r----- 1 oracle oinstall 197926912 Jun 22 07:15 users01.dbf
[oracle@mycat xws]$
[oracle@mycat xws]$
[oracle@mycat xws]$ rm -rf test01.dbf 注意生产不要去测试
[oracle@mycat xws]$ ls
control01.ctl control02.ctl redo01.log redo02.log redo03.log sysaux01.dbf system01.dbf temp01.dbf undotbs01.dbf users01.dbf

10:18:52 SQL> shutdown abort;
ORACLE instance shut down.
10:20:10 SQL> startup
ORACLE instance started.

Total System Global Area 242171904 bytes
Fixed Size 2252136 bytes
Variable Size 138412696 bytes
Database Buffers 96468992 bytes
Redo Buffers 5038080 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 5 - see DBWR trace file
ORA-01110: data file 5: ‘/oracle/data/xws/test01.dbf’

10:20:20 SQL> alter database datafile 5 offline drop;

Database altered.

10:21:34 SQL> alter database create datafile 5 as ‘/oracle/data/xws/test01.dbf’;

Database altered.

10:21:45 SQL> recover datafile 5;
Media recovery complete.
10:21:57 SQL> alter database open;

Database altered.

10:22:06 SQL> select count(1) from ogg.users;
select count(1) from ogg.users
*
ERROR at line 1:
ORA-00376: file 5 cannot be read at this time
ORA-01110: data file 5: ‘/oracle/data/xws/test01.dbf’

10:22:12 SQL> alter database datafile 5 online;

Database altered.

10:22:45 SQL> select count(1) from ogg.users;

COUNT(1)

   160

上述的这个情况是属于比较幸运的情况,我们的redolog还没有被重复利用,但是实际中遇到的情况往往是,等到发现数据文件误删报错,已经是好几天之外了,生产系统中redolog的切换,已经切换n次了。因此,在这里,我们只能尽量的挽回数据了:

首先查看被删除的数据文件涉及到哪几个表空间,将这些表空间里面的所有表都count一次,以确定有哪些表受到影响,如果是分区表,还比较好办些,分别count每一个分区的数据确认没有问题,将没有问题的数据进行exp备份,或者ctas到别的表。然后将表drop掉之后进行重建,注意重建的时候也要重新表的索引约束等等。如果对于非分区表,无法一个分区一个分区的进行测试,因此只能exp表,在exp的时候,会报错,但是无须理会,exp出来成一个文件后,可以imp到另一用户,重新本用户的表,在insert into table select * from user_b.table,注意索引和约束也要重建。

当然,重建表只是最低影响的处理,正确的处理方式应该是重建表空间,对表空间中的所有表都进行重建,但是这个工程量就比较大了……

最后修改时间:2020-06-22 14:34:56
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论