[20151028]linux下删除数据文件的恢复细节4

[20151028]linux下删除数据文件的恢复细节4

--前几天一直在做删除数据文件的恢复测试,中间遇到许多问题自己无法解决,从我个人讲我不主张使用句柄的方式来恢复,而更愿意
--使用rman的方式,这种情况仅仅适合非归档模式。
--前几天的测试非常混乱,我自己都不知道为什么在删除数据文件的情况下有时候执行alter system checkpoint数据库会直接crash,有
--时候为什么有不会。我再把整个恢复过程做一个总结:

1.测试环境:
SCOTT@test> @ &r/ver1

PORT_STRING                    VERSION        BANNER
------------------------------ -------------- ----------------------------------------------------------------
x86_64/Linux 2.4.xx            10.2.0.4.0     Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi

RMAN> report schema;
using target database control file instead of recovery catalog
Report of database schema
List of Permanent Datafiles
===========================
File Size(MB) Tablespace           RB segs Datafile Name
---- -------- -------------------- ------- ------------------------
1    480      SYSTEM               ***     /mnt/ramdisk/test/system01.dbf
2    35       UNDOTBS1             ***     /mnt/ramdisk/test/undotbs01.dbf
3    250      SYSAUX               ***     /mnt/ramdisk/test/sysaux01.dbf
4    5        USERS                ***     /mnt/ramdisk/test/users01.dbf
5    100      EXAMPLE              ***     /mnt/ramdisk/test/example01.dbf

List of Temporary Files
=======================
File Size(MB) Tablespace           Maxsize(MB) Tempfile Name
---- -------- -------------------- ----------- --------------------
1    20       TEMP                 32767       /mnt/ramdisk/test/temp01.dbf

SCOTT@test> create table tj (id number,name varchar2(20)) tablespace example;
Table created.

SCOTT@test> insert into tj values (1,'aaaa');
1 row created.

SCOTT@test> commit ;
Commit complete.

--测试前我做了1个冷备份。

2.测试:
--session 1:
SCOTT@test> col spid new_value v_spid
SCOTT@test> @ &r/spid

       SID    SERIAL# SPID   C50
---------- ---------- ------ --------------------------------------------------
       149          3 3210   alter system kill session '149,3' immediate;

SCOTT@test> select rowid,tj.* from tj ;
ROWID                      ID NAME
------------------ ---------- --------------------
AAAM7JAAFAAAAP2AAA          1 aaaa

SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
--无输出。因为数据已经在buffer cache,无需打开对应的文件句柄。

SCOTT@test> alter system flush buffer_cache ;
System altered.

SCOTT@test> select rowid,tj.* from tj ;
ROWID                      ID NAME
------------------ ---------- --------------------
AAAM7JAAFAAAAP2AAA          1 aaaa

SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
lrwx------ 1 oracle oinstall 64 Oct 28 09:08 10 -> /mnt/ramdisk/test/example01.dbf

3.开始删除数据文件:
$ rm /mnt/ramdisk/test/example01.dbf
/bin/rm: remove regular file `/mnt/ramdisk/test/example01.dbf'? y

--session 1:
SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
lrwx------ 1 oracle oinstall 64 Oct 28 09:08 10 -> /mnt/ramdisk/test/example01.dbf (deleted)

--可以发现句柄依旧存在,也就是session 1可以访问对应的数据文件。甚至可以dml操作数据库.
SCOTT@test> select rowid,tj.* from tj ;
ROWID                      ID NAME
------------------ ---------- --------------------
AAAM7JAAFAAAAP2AAA          1 aaaa

SCOTT@test> insert into tj values (2,'bbbb');
1 row created.

SCOTT@test> commit ;
Commit complete.

--网络上介绍的许多方法就是这个使用通过linux删除文件一些进程文件句柄没有释放的特性来恢复,但是这个时候一些已经打开句柄的
--进程读写文件完全没有没有影响,如果使用这种方式拷贝文件,实际上相当于要热备份文件而没有把数据文件表空间设置为热备份模式
--理论讲这种方式存在一些问题,虽然测试没有出错,但是并不表示适合真实的情况.

--我以前的提到必须先讲表空间设置为只读模式,然后在拷贝,这样才能获得一致的数据文件备份。但是我忽略一点,这是网友指出的问
--题,新进入的会话无法执行alter tablespace example read only的,会出现如下错误:

--session 2:
SCOTT@test> alter tablespace example read only ;
alter tablespace example read only
*
ERROR at line 1:
ORA-01116: error in opening database file 5
ORA-01110: data file 5: '/mnt/ramdisk/test/example01.dbf'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3

--因为要执行上面的命令,必须先获得该文件的句柄,而这个适合文件已经删除,另外在session 1,执行上面的命令没有问题,因为句柄已经
--打开.这就面临一个问题,我想到的解决方式通过链接欺骗oracle这个文件是存在的.步骤如下:

$ ps -ef | grep ora_dbw[0-9]_test
oracle    3168     1  0 09:05 ?        00:00:00 ora_dbw0_test
oracle    3170     1  0 09:05 ?        00:00:00 ora_dbw1_test
oracle    3172     1  0 09:05 ?        00:00:00 ora_dbw2_test

$ ls -l /proc/3168/fd | grep example
lrwx------ 1 oracle oinstall 64 2015-10-28 09:28:54 22 -> /mnt/ramdisk/test/example01.dbf (deleted)

--注意最好选择ora_dbw之类的后台进程,因为前台的进程退出,会释放文件句柄.

$ ln -s  /proc/3168/fd/22 /mnt/ramdisk/test/example01.dbf

--session 2:

SCOTT@test> alter tablespace example read only ;
Tablespace altered.

--这样执行就ok了.然后再删除链接,使用拷贝命令代替原来的链接.

$ rm /mnt/ramdisk/test/example01.dbf
/bin/rm: remove symbolic link `/mnt/ramdisk/test/example01.dbf'? y
$ cp  /proc/3168/fd/22 /mnt/ramdisk/test/example01.dbf

--这个时候不能直接执行alter tablespace example read write ;,因为恢复的文件i节点与原来已经不同,也就是原来删除的句柄没有释
--放,我这里又犯了一个低级错误.而且在这里困惑很久.回到session 1:

--session 1:
SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
lrwx------ 1 oracle oinstall 64 Oct 28 09:08 10 -> /mnt/ramdisk/test/example01.dbf (deleted)

--实际上要释放这个句柄必须将数据文件offline,如果我在session 2执行alter datafile datafile 5 offline,我回到session 1执行
--host ls -l /proc/&v_spid/fd | grep example,发现句柄一直没释放,这个是我当时测试昏惑的地方,我以为是某个后台进程擦操作释
--放句柄,我等很久根本不会释放,实际上你只要执行一些sql命令就会释放句柄(大家可以自行测试). 正确的恢复是:

alter database datafile 5 offline; -- 说明:这里加入 offline drop 与offline 是一样的,除非数据库是非归档模式,必须加drop参数.
recover datafile 5               -- 这一部实际上是多余的,因为前面已经将表空间设置为只读,
alter database datafile 5 online;
alter tablespace example read write ;

--这样就完成了恢复.

4.下面演示错误的恢复方式:
--如果跳过offline ,online这些步骤,直接设置表空间读写,就出现奇怪的问题,旧的会话打开的文件句柄指向删除的文件,而新打开的会
--话文件句柄指向新建立的数据文件.实际上还有一种方式在设置read write前.删除已经打开文件删除文件句柄的经常,注意不能杀后台
--进程,这样有点粗暴,不提倡使用.

# lsof | grep -i example01.dbf | grep deleted
oracle     3168    oracle   22uR     REG               0,18   104865792     602277 /mnt/ramdisk/test/example01.dbf (deleted)
oracle     3174    oracle   25u      REG               0,18   104865792     602277 /mnt/ramdisk/test/example01.dbf (deleted)
oracle     3178    oracle   19u      REG               0,18   104865792     602277 /mnt/ramdisk/test/example01.dbf (deleted)
oracle     3210    oracle   10u      REG               0,18   104865792     602277 /mnt/ramdisk/test/example01.dbf (deleted)
oracle     3301    oracle   15u      REG               0,18   104865792     602277 /mnt/ramdisk/test/example01.dbf (deleted)

--下面演示错误的恢复方式:
--session 2:
SCOTT@test> alter tablespace example read write ;
Tablespace altered.

--session 1:
SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
lrwx------ 1 oracle oinstall 64 Oct 28 09:08 10 -> /mnt/ramdisk/test/example01.dbf (deleted)

--可以发现删除的文件句柄没有释放.

SCOTT@test> update tj set name='AAAA' where id=1;
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> host ls -l /proc/&v_spid/fd | grep example
lrwx------ 1 oracle oinstall 64 Oct 28 09:08 10 -> /mnt/ramdisk/test/example01.dbf (deleted)

--可以发现操作的文件是删除的文件.

--session 2:
SCOTT@test> select rowid,tj.* from tj ;

ROWID                      ID NAME
------------------ ---------- --------------------
AAAM7JAAFAAAAP0AAA          2 bbbb
AAAM7JAAFAAAAP2AAA          1 AAAA

--我们也可以看到修改结果.如果我们执行刷新buffer cache,再看就出现问题了.

SCOTT@test> alter system flush buffer_cache ;
System altered.

SCOTT@test> select rowid,tj.* from tj ;
ROWID                      ID NAME
------------------ ---------- --------------------
AAAM7JAAFAAAAP0AAA          2 bbbb
AAAM7JAAFAAAAP2AAA          1 aaaa

--注意看ID=1的记录变成了小写,这样整个数据库就乱套了.切记这种恢复必须要offline+online这个步骤.

5.这样的数据库无法正常关闭.

SYS@test> shutdown immediate ;
ORA-01122: database file 5 failed verification check
ORA-01110: data file 5: '/mnt/ramdisk/test/example01.dbf'
ORA-01208: data file is an old version - not accessing current version

SYS@test> alter database datafile 5 offline ;
alter database datafile 5 offline
*
ERROR at line 1:
ORA-01145: offline immediate disallowed unless media recovery enabled
--不能offline.

SYS@test> select open_mode from v$database ;
OPEN_MODE
----------
READ WRITE

SYS@test> alter system checkpoint ;
alter system checkpoint
                       *
ERROR at line 1:
ORA-03113: end-of-file on communication channel

--直接crash,运气好的可以恢复,不好就出现我前面的情况,出现如下错误:

ORA-00283: recovery session canceled due to errors
ORA-12801: error signaled in parallel query server P005
ORA-00600: internal error code, arguments: [3020], [6], [837], [1], [93], [2614], [16], []
ORA-10567: Redo is inconsistent with data block (file#)

--补充恢复过程:
SYS@test> startup
ORACLE instance started.
Total System Global Area  486539264 bytes
Fixed Size                  2084872 bytes
Variable Size             138416120 bytes
Database Buffers          335544320 bytes
Redo Buffers               10493952 bytes
Database mounted.
ORA-01113: file 5 needs media recovery
ORA-01110: data file 5: '/mnt/ramdisk/test/example01.dbf'

SYS@test> recover datafile 5;
Media recovery complete.

SYS@test> alter database open ;
Database altered.

SYS@test> select rowid,tj.* from scott.tj ;
ROWID                      ID NAME
------------------ ---------- ------
AAAM7JAAFAAAAP0AAA          2 bbbb
AAAM7JAAFAAAAP2AAA          1 AAAA

--总结:
1.这种方式仅仅适合非归档模式.
2.首先先确定删除文件句柄:
$ ps -ef | grep ora_dbw[0-9]_test
oracle    3168     1  0 09:05 ?        00:00:00 ora_dbw0_test
oracle    3170     1  0 09:05 ?        00:00:00 ora_dbw1_test
oracle    3172     1  0 09:05 ?        00:00:00 ora_dbw2_test

$ ls -l /proc/NNNN/fd | grep example
lrwx------ 1 oracle oinstall 64 2015-10-28 09:28:54 22 -> /mnt/ramdisk/test/example01.dbf (deleted)

--确定删除文件句柄.

3.使用ln 命令欺骗oracle,假设文件存在:
$ ln -s  /proc/NNNN/fd/MMMM /mnt/ramdisk/test/example01.dbf

4.执行如下:
alter tablespace example read only ;
$ rm /where/path/ln_datafile.dbf
$ cp  /proc/NNNN/fd/MMMM /mnt/ramdisk/test/example01.dbf

alter database datafile N offline; -- 说明:这里加入 offline drop 与offline 是一样的,除非数据库是非归档模式,必须加drop参数.
recover datafile N;                -- 这一部实际上是多余的,因为前面已经将表空间设置为只读,
alter database datafile N online;
==在这里可以加入检查:# lsof | grep -i example01.dbf | grep deleted
alter tablespace example read write ;

5.检查恢复情况,我建议最好关闭数据库看看.

时间: 2024-10-28 16:32:28

[20151028]linux下删除数据文件的恢复细节4的相关文章

[20151025]linux下删除数据文件的恢复细节3

[20151025]linux下删除数据文件的恢复细节3.txt --以前曾经写过一篇关于 --链接:http://blog.itpub.net/267265/viewspace-763969/ --里面提到实际上这种方式对于生产系统不是很合适,而且生产系统情况非常复杂,不可能出现删除数据文件时没有事务产生. --这种方式仅仅适合no archivelog的模式(没有办法的选择),我当时还提到这种方式一定要快,因为我的测试执行 alter system --checkpoint;,数据库直接cr

[20151023]linux下删除数据文件的恢复细节2

[20151023]linux下删除数据文件的恢复的一些细节问题(补充).txt --以前曾经写过一篇关于 --链接:http://blog.itpub.net/267265/viewspace-763969/ --里面提到实际上这种方式对于生产系统不是很合适,而且生产系统情况非常复杂,不可能出现删除数据文件时没有事务产生. --这种方式仅仅适合no archivelog的模式(没有办法的选择),我当时还提到这种方式一定要快,因为我的测试执行 alter system --checkpoint;

[20130614]linux下删除数据文件的恢复的一些细节问题.txt

[20130614]linux下删除数据文件的恢复的一些细节问题.txt 前天看了链接:http://space.itpub.net/26015009/viewspace-763506 我仅仅做一些测试以及补充,以及注意的细节问题,实际上最好的方法依旧是使用rman备份恢复. 1.测试环境: --session 1 SQL> @ver BANNER --------------------------------------------------------------------------

Oracle数据库如何在开启状态下删除数据文件

数据库在open的时候数据文件被从操作系统直接删除 因为在linux系统中,之前打开过该文件的进程仍然持有相应的文件句柄,所指向的文件仍然可以读写, 文件描述符可以从/proc目录中得到 如果关闭数据库,则该句柄会消失 实际实验中发现dbw0进程开启后就会持有所有数据文件的句柄,但只有数据库对文件进行过写入操作之后才算是真正的持有句柄文件,未执行过写入操作的的文件在被从操作系统删除后数据库并不能继续对该文件进行读写操作 在虚拟机中实验过程如下: 以exmple表空间为例进行示范 (一) 1.重启

Linux下将数据文件的指定域读取到shell脚本中

这个例子说明了怎样在Linux下shell脚本中从数据文件读取特定的域(field)并进行操作.例如,假设文件employees.txt的格式是{employee-name}:{employee-id}:{department-name},以冒号进行划分,如下所示. $ cat employees.txt Emma Thomas:100:Marketing Alex Jason:200:Sales Madison Randy:300:Product Development Sanjay Gupt

【故障处理】DG环境主库丢失归档情况下数据文件的恢复

[故障处理]DG环境主库丢失归档情况下数据文件的恢复 1  BLOG文档结构图     2  前言部分   2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① BBED的编译 ② BBED修改文件头让其跳过归档从而可以ONLINE(重点) ③ OS命名格式转换为ASM的命名格式 ④ DG环境中备库丢失数据文件的情况下的处理过程(重点) ⑤ 数据文件OFFLINE后应立即做一次RECOVER操作 ⑥ BBED环境

Linux下删除文件下彻底删除文件

  在linux中删除文件与文件夹我们可以直接使用rm就可以删除了,彻底删除文件或文件夹我们可以使用shred命令来完成,下面我给大家介绍介绍. Linux删除文件夹命令 linux删除目录很简单,很多人还是习惯用rmdir,不过一旦目录非空,就陷入深深的苦恼之中,现在使用rm -rf命令即可. 直接rm就可以了,不过要加两个参数-rf 即:rm -rf 目录名字 删除目录.文件 rm(remove) 功能说明:删除文件或目录. 语 法:rm [-dfirv][--help][--version

探索ORACLE之RMAN_07单个数据文件丢失恢复

探索ORACLE之RMAN_07单个数据文件丢失恢复 作者:吴伟龙   Name:Prodence Woo QQ:286507175  msn:hapy-wuweilong@hotmail.com   备份的终极目的是为了更好的将数据恢复和还原过来,在前面的章节中我们已经重点谈完了RMAN的备份,实际上也穿插的谈了些复杂的完整恢复.当然在这节当中我们将会由浅入深的详细谈谈在几种不同情况下的数据库恢复. 1.     数据文件的丢失恢复 1.1    在wwl表空间上创建5张表,并添加数据. SQ

数据文件坏删除数据文件

数据 没有简单的方法来删除表空间的数据文件,唯一的方法是删除整个定义的表空间,步骤有下面(前提是这个数据文件上的数据是不需要了): 如果数据库运行在非归档模式: 1. MOUNT数据库 - startup mount2. 删除数据文件 - alter database datafile xxx offline drop3. 打开(OPEN)数据库 - alter database open 4. 查看属于该表空间的所有对象:        select owner, segment_name,