Linux下利用文件描述符恢复的成功失败实验

  

数据误删除是做为初级运维人员经常遇到的“低级错误”,一些有经验的老手有时也在疲劳、不冷静的状况下“马失前蹄”。一旦误删除数据文件,尽快采用影响最小、最迅速的手段恢复数据库是第一要务。数据库

恢复数据的方法不少,好比冷热备份、闪回数据库等等,若是是直接从操做系统OS层面删除数据文件,在Linux/Unix环境下,有一些优选手段可使用。其中之一就是文件描述符(File Description)。缓存

 

一、聊聊File Descriptionoracle

 

不一样的操做系统,在实现CPU管理、内存管理和存储文件管理的时候,采用不一样的方式手段。运维

在Linux和Unix里面,采用文件描述符进行文件管理。一个进程要打开文件,是调用操做系统内核功能,内核返回一个文件描述符。对文件的读写操做也经过这个描述符进行操做。操做系统删除一个文件的时候,是要肯定文件全部文件描述符都是释放掉以后,才会最后删除。dom

咱们的误操做,若是是发生在正在运行的数据库系统中,文件虽然在操做系统上删除不可见了。可是数据库Oracle进程中还会保有一些存在的文件描述符,借用这些文件描述符,咱们是可能找到文件信息,来恢复数据文件的。ide

因此,一旦发生了误删除动做,切忌三点:心态冷静、断开应用、维护现场不关库。工具

可是,在实际中,这种能够快速恢复的技术,并非百分之百成功的。使用文件描述符恢复数据须要数据库不能关闭、数据库进程不能“自动剔除”数据文件等。本文从两个实验着手,介绍一下操做方法和前提。优化

 

二、实验环境搭建spa

 

咱们选择Linux 2.6内核和Oracle 11g进行试验。注意:在生产环境下,绝对不能进行这样的实验。进行试验的时候,也须要完备的备份。操作系统

 

[oracle@bspdev ~]$ uname -a

Linux bspdev.localdomain 2.6.18-308.el5 #1 SMP Tue Feb 21 20:05:41 EST 2012 i686 i686 i386 GNU/Linux

 

SQL> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE 11.2.0.1.0 Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 – Production

 

建立专门的表空间、用户和数据表,用于进行试验。

 

SQL> create tablespace rmdtest datafile '/u01/oradata/WILSON/datafile/rmdtest01.dbf' size 1000m

  2  extent management local uniform size 1m

  3  segment space management auto;

 

Tablespace created

 

SQL> create user rmtest identified by rmtest default tablespace rmdtest;

User created

 

SQL> grant resource, connect to rmtest;

Grant succeeded

 

SQL> grant select any dictionary to rmtest;

Grant succeeded

 

SQL> create table rm_tab as select * from dba_objects;

Table created

 

SQL> insert into rm_tab select * from rm_tab;

72731 rows inserted

 

SQL> commit;

Commit complete

 

数据表T,在实验环境的表空间文件里面。

 

SQL> select tablespace_name, bytes/1024/1024 M from dba_segments where owner='RMTEST' and segment_name='RM_TAB';

TABLESPACE_NAME                         M

------------------------------ ----------

RMDTEST                                17

 

确保有一份好的备份!

 

RMAN> list backup;

 

List of Backup Sets

===================

BS Key  Type LV Size       Device Type Elapsed Time Completion Time

------- ---- -- ---------- ----------- ------------ ---------------

135     Full    1.39G      DISK        00:03:13     02-FEB-14     

        BP Key: 135   Status: AVAILABLE  Compressed: NO  Tag: TAG20140202T012300

(篇幅缘由,有省略……)

        Piece Name:

        Piece Name: /u01/flash_recovery_area/WILSON/autobackup/2014_02_02/o1_mf_s_838430779_9gtckx4s_.bkp

  SPFILE Included: Modification time: 02-FEB-14

  SPFILE db_unique_name: WILSON

  Control File Included: Ckp SCN: 5370719      Ckp time: 02-FEB-14

 

下面进行两次实验过程,模拟运行状态下数据文件被删除的场景。注意:因为操做系统差别性,Windows下是不会出现“运行打开的文件被删除”的场景的。因此,在Linux/AIX中,更容易出现误删除的状况。

 

三、一次“不成功”的实验

 

首先是一次不成功的实验。运维生产环境中,咱们的原则永远是稳定。危险不肯定的事情场景,必定要避免。哪怕不作、不修、不优化,也不要让业务系统的可用性去冒险。

实验环境中,咱们总可以发现不少知识和现象。首先,咱们尝试删除数据文件,确认文件位置。

 

[oracle@bspdev ~]$ cd /u01/oradata/WILSON/datafile/

[oracle@bspdev datafile]$ ls -l | grep rmdtest01.dbf

-rw-r----- 1 oracle oinstall 1048584192 Feb  2 02:14 rmdtest01.dbf

 

删除文件。

 

[oracle@bspdev datafile]$ rm rmdtest01.dbf

[oracle@bspdev datafile]$ ls -l

total 8121892

-rw-r----- 1 oracle oinstall   10493952 Feb  2 02:14 mvtbltest01.dbf

(篇幅缘由,有省略……)

-rw-r--r-- 1 oracle oinstall   10493952 Feb  2 02:14 tts_simple01.dbf

 

注意:此时数据文件虽然从OS中删除,可是咱们依然能够查询到数据!

 

SQL> select count(*) from rmtest.rm_tab;

  COUNT(*)

----------

    145462

 

对于这种现象,笔者认为两种可能性,一是buffer cache中的缓存数据信息,能够支持这种查询动做。另外一种可能性,就是因为文件描述符的存在,让数据文件没有被真正删除,还以某种方式存在于系统中,支持dbwr查询。

 

证实两种猜测,对buffer cache进行清理。

 

SQL> alter system flush buffer_cache;

System altered

 

SQL> alter system flush shared_pool;

System altered

 

--依然能够查询结果

SQL> select count(*) from rmtest.rm_tab;

  COUNT(*)

----------

    145462

 

可是,若是数据库以某种方式,发现了文件被删除,好比check point动做,就会引发不少自动化动做出现。

 

SQL> alter system checkpoint;

System altered

 

--alert log中信息以下:

Sun Feb 02 02:27:51 2014

Beginning global checkpoint up to RBA [0x1ef.2532.10], SCN: 5374358

Errors in file /u01/diag/rdbms/wilson/wilson/trace/wilson_ckpt_4814.trc:

ORA-01171: datafile 11 going offline due to error advancing checkpoint

ORA-01116: error in opening database file 11

ORA-01110: data file 11: '/u01/oradata/WILSON/datafile/rmdtest01.dbf'

ORA-27041: unable to open file

Linux Error: 2: No such file or directory

Additional information: 3

Completed checkpoint up to RBA [0x1ef.2532.10], SCN: 5374358

Sun Feb 02 02:27:52 2014

Checker run found 1 new persistent data failures

 

Check Point是Oracle内部控制的一件大事。通过check point,Oracle要保证全部数据文件、控制文件SCN信息保持一致,和日志文件在恢复时间点(RBA+SCN)达成一致。这个过程就强制回去访问到数据文件,结果文件丢失被发现。

此后,查询出错。

 

SQL> select count(*) from rmtest.rm_tab;

select count(*) from rmtest.rm_tab

 

ORA-00376: 此时没法读取文件 11

ORA-01110: 数据文件 11: '/u01/oradata/WILSON/datafile/rmdtest01.dbf'

 

注意:若是听任无论,Oracle自动的incremental checkpoint也会有相似的效果。同时,周期性的Global Check也会发现“文件丢失了”。

这个时候,咱们进行修复操做。使用文件描述符恢复文件的方法,第一步找到一个Oracle后台进程,最典型的就是dbwr。

 

[oracle@bspdev datafile]$ ps -ef | grep dbw

oracle    4806     1  0 02:12 ?        00:00:00 ora_dbw0_wilson

oracle    9076  4491  0 02:29 pts/0    00:00:00 grep dbw

 

使用lsof –p命令,找出dbwr进程对应的文件描述符信息。

 

[root@bspdev datafile]# lsof -p 4806

COMMAND  PID   USER   FD   TYPE DEVICE   SIZE/OFF      NODE NAME

oracle  4806 oracle  cwd    DIR  253,0       4096  10574090 /u01/oracle/dbs

oracle  4806 oracle  rtd    DIR  253,0       4096         2 /

oracle  4806 oracle  txt    REG  253,0  173515991  10579756 /u01/oracle/bin/oracle

(篇幅缘由,有省略……)

racle  4806 oracle   33uW  REG  253,0   10493952   2978999 /u01/oradata/WILSON/datafile/mvtbltest01.dbf

oracle  4806 oracle   34uW  REG  253,0   30416896    524875 /u01/oradata/WILSON/datafile/o1_mf_temp_7xt46489_.tmp

oracle  4806 oracle   35r   REG  253,0    1074176  10595009 /u01/oracle/rdbms/mesg/oraus.msb

 

里面包括了dbwr打开的全部文件描述符,咱们没有能看到删除的文件rmdtest01.dbf。文件描述符目录也没有相应的FD内容。说明:因为一些状况,Oracle进程将文件描述符删除了!

 

此时,咱们检查文件状态。

 

SQL> select online_status from dba_data_files where file_id=11;

 

ONLINE_STATUS

-------------

RECOVER

 

文件已经被offline,强制剔除文件体系了。仔细想起来,这个过程是check point的一个结果。

Check Point的最终效果,是全部数据文件在文件头标注相同的SCN记录,以前脏块被写入到数据文件中。若是一个数据文件实体不存在了,这个操做必定不能完成。Oracle选择了一种方法,就是强制将这个文件“剔除”。因此咱们在日志中,看到了下面一段内容。

 

ORA-01171: datafile 11 going offline due to error advancing checkpoint

 

被剔除的文件,Oracle关闭文件描述符也是能够理解的了。

这个实验失败,告诉咱们一个道理:使用文件描述符进行数据恢复,并非100%有效。若是时间很长,或者进行过不少特殊操做,这个微弱的文件描述符是会消失的!

下面咱们进行一次成功的实验。

 

四、一次“成功”的实验

 

咱们借助RMAN备份,恢复到实验前的状态。

 

[root@bspdev datafile]# ls

mvtbltest01.dbf               o1_mf_temp_7xt46489_.tmp

o1_mf_example_7xt46m9x_.dbf   o1_mf_undotbs1_7xt3yzl5_.dbf.bak

o1_mf_jpatest_87y6v8qc_.dbf   o1_mf_undotbs1_92l5b0v4_.dbf

o1_mf_nbscommo_820frtg1_.dbf  o1_mf_users_805nxydh_.dbf

o1_mf_nbscommo_820ft5y5_.dbf  rmdtest01.dbf

o1_mf_sysaux_7xt3yzkb_.dbf    tts_simple01.dbf

o1_mf_system_7xt3yzhj_.dbf

 

删除数据文件。

 

[root@bspdev datafile]# rm rmdtest01.dbf

rm: remove regular file `rmdtest01.dbf'? y

[root@bspdev datafile]# ls

mvtbltest01.dbf               o1_mf_system_7xt3yzhj_.dbf

o1_mf_example_7xt46m9x_.dbf   o1_mf_temp_7xt46489_.tmp

o1_mf_jpatest_87y6v8qc_.dbf   o1_mf_undotbs1_7xt3yzl5_.dbf.bak

o1_mf_nbscommo_820frtg1_.dbf  o1_mf_undotbs1_92l5b0v4_.dbf

o1_mf_nbscommo_820ft5y5_.dbf  o1_mf_users_805nxydh_.dbf

o1_mf_sysaux_7xt3yzkb_.dbf    tts_simple01.dbf

 

删除以后,借助文件描述符,咱们仍是能够查询的。

 

SQL> select count(*) from rmtest.rm_tab;

 

  COUNT(*)

----------

    145462

 

查找dbwr进程,肯定进程编号。

 

[root@bspdev datafile]# ps -ef | grep dbw

oracle    9405     1  0 02:45 ?        00:00:00 ora_dbw0_wilson

root      9716  4466  0 02:56 pts/0    00:00:00 grep dbw

 

使用lsof –p肯定文件描述符信息。

 

[root@bspdev datafile]# lsof -p 9405

COMMAND  PID   USER   FD   TYPE DEVICE   SIZE/OFF      NODE NAME

oracle  9405 oracle  cwd    DIR  253,0       4096  10574090 /u01/oracle/dbs

(篇幅缘由,有省略……)

oracle  9405 oracle   29uW  REG  253,0  209723392    525165 /u01/oradata/WILSON/datafile/o1_mf_nbscommo_820frtg1_.dbf

oracle  9405 oracle   30uW  REG  253,0  104865792    525166 /u01/oradata/WILSON/datafile/o1_mf_nbscommo_820ft5y5_.dbf

oracle  9405 oracle   31uW  REG  253,0  104865792    525484 /u01/oradata/WILSON/datafile/o1_mf_jpatest_87y6v8qc_.dbf

oracle  9405 oracle   32uW  REG  253,0   10493952    525541 /u01/oradata/WILSON/datafile/tts_simple01.dbf

oracle  9405 oracle   33uW  REG  253,0   10493952   2978999 /u01/oradata/WILSON/datafile/mvtbltest01.dbf

oracle  9405 oracle   34uW  REG  253,0   30416896    524875 /u01/oradata/WILSON/datafile/o1_mf_temp_7xt46489_.tmp

oracle  9405 oracle   35r   REG  253,0    1074176  10595009 /u01/oracle/rdbms/mesg/oraus.msb

oracle  9405 oracle   36uW  REG  253,0 1048584192   2979001 /u01/oradata/WILSON/datafile/rmdtest01.dbf (deleted)

 

注意:lsof是描述文件描述符最好的工具,其中包括FD列。咱们从dbwr的链接中,找到了rmdtest01.dbf的信息行。其中FD=36uw。这个36就表示了链接文件的名称。

 

联合dbwr的进程编号9405,咱们在目录/proc/9405/fd中找到全部的文件符。

 

 

[root@bspdev datafile]# cd /proc/9405/fd

[root@bspdev fd]# ls

0  10  12  14  16  18  2   21  23  25  27  29  30  32  34  36  5  7  9

1  11  13  15  17  19  20  22  24  26  28  3   31  33  35  4   6  8

 

Ls命令也能够列出信息。

 

 

[root@bspdev fd]# ls -l

total 0

lr-x------ 1 oracle oinstall 64 Feb  2 02:56 0 -> /dev/null

l-wx------ 1 oracle oinstall 64 Feb  2 02:56 1 -> /dev/null

lrwx------ 1 oracle oinstall 64 Feb  2 02:56 10 -> /u01/oracle/dbs/lkinstwilson (deleted)

lrwx------ 1 oracle oinstall 64 Feb  2 02:56 34 -> /u01/oradata/WILSON/datafile/o1_mf_temp_7xt46489_.tmp

lr-x------ 1 oracle oinstall 64 Feb  2 02:56 35 -> /u01/oracle/rdbms/mesg/oraus.msb

lrwx------ 1 oracle oinstall 64 Feb  2 02:56 36 -> /u01/oradata/WILSON/datafile/rmdtest01.dbf (deleted)

l-wx------ 1 oracle oinstall 64 Feb  2 02:56 9 -> /home/oracle/oradiag_oracle/diag/clients/user_oracle/host_1437849207_76/trace/ora_9293_3085993664.trm

 

这个36对应的文件还存在,就是已经被删除的那个rmdtest01.dbf文件。进行拷贝出来。

 

[root@bspdev fd]# cp 36 /u01/oradata/WILSON/datafile/rmdtest01res.dbf

[root@bspdev fd]#

 

拷贝出来以后,最好进行必定转换。先将其offline,以后进行控制文件中的rename动做,最后recover和online操做。具体流程常见笔者专门的文章(http://blog.itpub.net/17203031/viewspace-773628/)。

 

SQL> alter database datafile 11 offline;

Database altered

 

Rename操做。

 

--报错

SQL> alter database rename file '/u01/oradata/WILSON/datafile/rmdtest01.dbf' to '/u01/oradata/WILSON/datafile/rmdtest01res.dbf';

 

alter database rename file '/u01/oradata/WILSON/datafile/rmdtest01.dbf' to '/u01/oradata/WILSON/datafile/rmdtest01res.dbf'

 

ORA-01511: 重命名日志/数据文件时出错

ORA-01141: 重命名数据文件 11 时出错 - 未找到新文件 '/u01/oradata/WILSON/datafile/rmdtest01res.dbf'

ORA-01110: 数据文件 11: '/u01/oradata/WILSON/datafile/rmdtest01.dbf'

ORA-27041: 没法打开文件

Linux Error: 13: Permission denied

Additional information: 9

 

究其缘由,是拷贝权限为root,须要手工修改全部权信息。

 

[root@bspdev datafile]# ls -l | grep rmd

-rw-r----- 1 root   root     1048584192 Feb  2 03:01 rmdtest01res.dbf

[root@bspdev datafile]# chown oracle:oinstall rmdtest01res.dbf

[root@bspdev datafile]# ls -l | grep rmd

-rw-r----- 1 oracle oinstall 1048584192 Feb  2 03:01 rmdtest01res.dbf

 

Rename文件。

 

 

SQL> alter database rename file '/u01/oradata/WILSON/datafile/rmdtest01.dbf' to '/u01/oradata/WILSON/datafile/rmdtest01res.dbf';

Database altered

 

SQL> recover datafile 11;

Media recovery complete.

SQL> alter database datafile 11 online;

 

Database altered.

 

使用rman中的recovery advisor工具,来判断错误是否存在。

 

[oracle@bspdev ~]$ rman nocatalog

 

Recovery Manager: Release 11.2.0.1.0 - Production on Sun Feb 2 03:06:43 2014

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

RMAN> connect target /

 

connected to target database: WILSON (DBID=3906514064)

using target database control file instead of recovery catalog

 

RMAN> list failure;

no failures found that match specification

 

恢复完成,实验成功。

 

五、结论

 

本篇文章的书写,有一半目的是揭示文件内部的运行机制,另外一半是记录下Linux下使用文件描述符FD来恢复数据的方法。咱们说,从运维角度看,直接绕过数据库对OS进行文件操做是很是不成熟的作法,不管是出于什么目的。不少致命的错误都是一系列的rm形成的。愿文章描述的场景永不会在全部运维生产系统中出现!

相关文章
相关标签/搜索