在生产环境,总会发生数据库的数据文件被误删除的事情,如SA不懂得数据库,数据库的在线日志为redo01.log,还是cp备份后删除的,让人哭笑不得,数据文件命名为无dbf后缀等,都容易被误删除
       在操作系统层面被误rm的,如果及时发现,还是可以挽救的,下面举例说明下:

1、查询数据库版本和是否归档模式

SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE    11.1.0.7.0      Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
SQL> archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /archivelog
Oldest online log sequence     1
Next log sequence to archive   1
Current log sequence           1

2、fly用户创建表fly,fly表的记录数为1128432

SQL> conn fly/fly
Connected.
SQL> create table fly as select * from dba_objects;
Table created.
SQL> insert into fly select * from fly;
70527 rows created.
SQL> /
141054 rows created.
SQL> /
282108 rows created.
SQL> /
564216 rows created.
SQL> commit;
Commit complete.
SQL> select count(*) from fly;
COUNT(*)
----------
1128432

3、查看fly用户默认表空间的数据文件,用操作系统命令rm删除fly用户默认表空间下的所有数据文件

SQL> conn sys/oracle as sysdba
Connected.
SQL> select default_tablespace from dba_users where username='FLY';
DEFAULT_TABLESPACE
------------------------------
USERS
SQL> col file_name format a80
SQL> set linesize 200
SQL> select file_name from dba_data_files where tablespace_name='USERS';
FILE_NAME
--------------------------------------------------------------------------------
/home/oracle/oradata/fly/datafile/users02.dbf
/home/oracle/oradata/fly/datafile/user03.dbf
SQL> host rm /home/oracle/oradata/fly/datafile/users02.dbf
SQL> host rm /home/oracle/oradata/fly/datafile/user03.dbf

4、在fly用户下创建表fly007,报错了,注意及时多执行几次创建表的SQL语句,这边都只显示user02.dbf数据文件不存在了,接下来的恢复中,我们肯定要考虑到到底被误删除了几个数据文件

SQL> conn fly/fly
Connected.
SQL> create table fly007 as select * from dba_objects;
create table fly007 as select * from dba_objects
*
ERROR at line 1:
ORA-01116: error in opening database file 20
ORA-01110: data file 20: '/home/oracle/oradata/fly/datafile/users02.dbf'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3

5、查看该文件是否仍旧被某些进程打开着

fly007:~ # lsof | grep /home/oracle/oradata/fly/datafile/users02.dbf
oracle    22297     oracle   32uW     REG                8,2  209723392    1410008 /home/oracle/oradata/fly/datafile/users02.dbf (deleted)
oracle    22301     oracle   42u      REG                8,2  209723392    1410008 /home/oracle/oradata/fly/datafile/users02.dbf (deleted)
oracle    22309     oracle   30u      REG                8,2  209723392    1410008 /home/oracle/oradata/fly/datafile/users02.dbf (deleted)
oracle    22317     oracle   32u      REG                8,2  209723392    1410008 /home/oracle/oradata/fly/datafile/users02.dbf (deleted)

6、数据库的dbwr进程会打开所有的数据文件,包括控制文件,查看dbwr进程的PID为22297

fly007:~ # ps -ef | grep dbw0 | grep -v grep
oracle   22297     1  0 21:21 ?        00:00:00 ora_dbw0_fly

 

误删除数据文件恢复原理
        当进程打开了某个文件时,只要该进程仍旧保持打开该文件,即使将该文件删除了,该进程仍然可以向打开该文件时提供给它的文件描述符进行读取和写入操作。在/proc 目录下,包含了反映内核和进程树的各种文件。/proc目录挂载的是在内存中所映射的一块区域,所以这些文件和目录并不存在于磁盘中,因此当我们对这些文件进行读取和写入时,实际上是在从内存中获取相关信息。大多数与lsof 相关的信息都存储于以进程的PID 命名的目录中,即/proc/1116 中包含的是PID 为1116的进程的信息。每个进程目录中存在着各种文件,它们可以使得应用程序简单地了解进程的内存空间、文件描述符列表、指向磁盘上的文件的符号链接和其他系统信息。lsof 程序使用该信息和其他关于内核内部状态的信息来产生其输出。所以lsof 可以显示进程的文件描述符和相关的文件名等信息。也就是我们通过访问进程的文件描述符可以找到该文件的相关信息。
        当系统中的某个文件被意外的删除了,只要这个时候系统中还有进程正在访问该文件,那么我们就可以通过lsof从/proc目录下恢复该文件的内容

 

7、进入到dbwr进程的fd(文件描述符)目录下,需要确定被删除的数据文件是不是只有一个user02.dbf,结果发现不是的,10,25,32为fd(文件描述符)

fly007:~ # cd /proc/22297/fd
fly007:/proc/22297/fd # ls -l | grep delete
lrwx------ 1 oracle oinstall 64 Dec  6 21:26 10 -> /home/oracle/product/11g/db/dbs/lkinstfly (deleted)
lrwx------ 1 oracle oinstall 64 Dec  6 21:26 25 -> /home/oracle/oradata/fly/datafile/user03.dbf (deleted)
lrwx------ 1 oracle oinstall 64 Dec  6 21:26 32 -> /home/oracle/oradata/fly/datafile/users02.dbf (deleted)
fly007:/proc/22297/fd # ls -l /home/oracle/oradata/fly/datafile/user03.dbf
/bin/ls: /home/oracle/oradata/fly/datafile/user03.dbf: No such file or directory

8、拷贝对应文件描述符为被误删除的数据文件绝对路径,以下使用root拷贝,注意加上-p参数

fly007:/proc/22297/fd # cp -p 32 /home/oracle/oradata/fly/datafile/users02.dbf
fly007:/proc/22297/fd # cp -p 25 /home/oracle/oradata/fly/datafile/user03.dbf

9、在数据库中进行recover datafile恢复操作,数据没有丢失,完全恢复

fly007:/proc/22297/fd # su - oracle
oracle@fly007:~> sqlplus /nolog
SQL*Plus: Release 11.1.0.7.0 - Production on Fri Dec 6 21:56:45 2013
Copyright (c) 1982, 2008, Oracle.  All rights reserved.
SQL> conn sys/oracle as sysdba
Connected.
SQL> alter database datafile '/home/oracle/oradata/fly/datafile/users02.dbf' offline;
Database altered.
SQL> alter database datafile '/home/oracle/oradata/fly/datafile/user03.dbf' offline;
Database altered.
SQL> recover datafile '/home/oracle/oradata/fly/datafile/users02.dbf';
Media recovery complete.
SQL> recover datafile '/home/oracle/oradata/fly/datafile/user03.dbf';
Media recovery complete.
SQL> alter database datafile '/home/oracle/oradata/fly/datafile/users02.dbf' online;
Database altered.
SQL> alter database datafile '/home/oracle/oradata/fly/datafile/user03.dbf' online;
Database altered.
SQL> conn fly/fly
Connected.
SQL> select count(*) from fly;
COUNT(*)
----------
1128432
SQL> create table fly007 as select * from dba_objects;
Table created.

      数据文件被误删除后,如果关闭数据库,则dbw0进程消失,没有了持续打开误删除文件的进程,就不可以通过此方法进行恢复,因此在数据库出现问题的时候,如果不确认情况的复杂程度,千万不要随便关闭数据库。重启数据库往往是没有意义的,甚至是致命的,另外,若控制文件被rm了,通过这种方式是无法恢复的
      同时,通过linux的rm删除了数据文件,甚至连归档日志都全部删除了,只要数据库没有崩溃,dbw0进程还在,就可以将数据完全恢复,和是否有归档日志没有关系,但是和是否开启了归档是有区别的,后续继续讨论操作系统层面误删除数据库数据文件的恢复