如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!
诗檀软件专业数据库修复团队
服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com
Frits Hoogland已经在博客中写过在linux上恢复删除的文件的问题,正如Frits 在a comment on my blog中提到的,文中他还提到了关于这个问题的 metalink 说明。
该说明的ID 是: 444749.1 “Retrieve deleted files on Unix / Linux using File Descriptors”。我去了,看了看他描述的程序。.
虽然它解释了如何恢复删除的文件,但是该程序使数据库处于不连贯的状态,它会损坏你的数据库,查询会随机产生错误的结果,这取决于高速缓存的使用和数据库的繁忙程度et cetera.
(在你阅读细节之前,我想要指出没有全面回顾metalink 说明,正如在说明的一开始就指出的那样🙂
“该文献通过Oracle Support’s Rapid Visibility (RaV) 过程传递给你, 所以不属于独立的技术回顾。”
说明中概述的过程描述了如何恢复删除的文件,如何将其置于删除文件的相同位置 ,问题是它不包含使文件离线/在线,因此数据库最后会有文件的两个不同拷贝:
- 删除文件由数据库写入者打开,任何其他用户过程从文件读取 (连接)。
- 新的,恢复的文件由所有新的会话或者不需要从文件读取的现存的会话打开。
这个状态的问题是所有的写入操作将经过数据库写入者,因此会最终存在于删除的文件中,它们也会存在于 Oracle高速缓冲缓存区,只要它们在高速缓冲缓存区 ,但是如果它们变旧不存在于高速缓冲缓存区,“新”的会话将会读取恢复的文件,这样就不会看到这些变化。
这里是带有内嵌解释的测试案例:
/ra5a/orabkp/test/TEST/datafile> sqlplus test/test
SQL*Plus: Release 10.2.0.3.0 – Production on Thu Nov 8 12:45:40 2007
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Release 10.2.0.3.0 – 64bit Production
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL> select file_name from dba_data_files where tablespace_name=’LOST’;
FILE_NAME
—————————————————
/ra5a/orabkp/test/TEST/datafile/lost.dbf
这是设置,我们知道删除哪个文件。
这是刚开始启动的数据库我们需要成倍使用会话以最好的展示效果,我们称当前会话为“SESSION A”。
运行该查询,打开当前会话中的lost.dbf 文件, 加载高速缓冲缓存:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL> !rm /ra5a/orabkp/test/TEST/datafile/lost.dbf
We can still query the table as it is in the Oracle buffer cache:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
高速缓冲缓存刷新之后,我们仍旧可以查询表, 因为当前会话打开了文件处理(正如数据库写入者做的那样)。
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL>
Now let’s start another session and see what happens. We will call this one “SESSION B”.
/app/oracle> sqlplus test/test
SQL*Plus: Release 10.2.0.3.0 – Production on Thu Nov 8 12:50:17 2007
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Release 10.2.0.3.0 – 64bit Production
现在移除了文件,但是我们仍旧可以从Oracle高速缓冲缓存查询表:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
但是, 刷新缓存,我们将不能查询表,因为该会话不能找到我们之前删除的文件:
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from lost_table;
select count(*) from lost_table
*
ERROR at line 1:
ORA-01116: error in opening database file 6
ORA-01110: data file 6: ‘/ra5a/orabkp/test/TEST/datafile/lost.dbf’
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
SQL>
为了好玩, 我们返回到“SESSION A”, 仍旧打开了文件处理,我们可以读取它,加载高速缓冲缓存:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL>
现在我们可以在一次从SESSION B读取 (不能打开文件):
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
如Metalink Note:444749.1描述的那样,现在我们可以实现修复:
/app/oracle> cat /proc/23937/fd/23 > /ra5a/orabkp/test/TEST/datafile/lost.dbf
/app/oracle> sqlplus test/test
SQL*Plus: Release 10.2.0.3.0 – Production on Thu Nov 8 12:54:10 2007
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Release 10.2.0.3.0 – 64bit Production
连接到一个崭新的会话,我们可以查询表(仍旧从高速缓冲缓存):
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
到这一点上都对了,是不是? 表从新旧会话都是可读取的,即便在刷新缓存之后错误。数据库处于一个非连续的状态,这里是一个测试。
Back in SESSION A (with the open file)
SQL>
SQL> insert into lost_table select * From lost_table where rownum <=1;
1 row created.
SQL> commit;
提交完成。
我们插入一行,现在我们数数,观察它:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50071
在 “SESSION B”中, 我们也能看到它(通过高速缓冲缓存)。
SQL>
SQL> select count(*) from lost_table;
COUNT(*)
———-
50071
但是如果我们刷新缓存:
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
…我们看到旧数据 — 没有改变。 这是因为数据库写入者过程写入到我们已经删除的文件,当我们 “恢复它”时,我们复原了那个文件的一个新“实体”,也就是, 我们复制了当前内容到一个新的文件,但是旧文件还是在那儿,这就是变化发生的地方。
在my first item on this中,我的解决方法是创建一个符号连接到删除的文件,因此使用同样的文件。
为进一步显示是如何出错的 — 即便我们仍旧打开了正确的文件,如果我们查询表,我们将从高速缓冲缓存读取,从打开不正确的文件的Oracle会话填充:
SQL> select count(*) from lost_table;
COUNT(*)
———-
50070
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from lost_table;
COUNT(*)
———-
50071
刷新缓存,再一次读取“正确” 数据。
即便你在“SESSION B”中插入数据 (带有 “新”文件的那一个), 它仍旧写入到旧文件中,因为数据库写入者过程是写入变化。
这些是很简单的案例来证明将会产生的混乱,现在考虑交易,为不存在的数据撤销数据和新旧文件的部分结果,我甚至不会提到读取和写入的直接路径。
丢失的最重要一步是使文件离线,恢复它,再一次使它在线,通过使文件离线,数据库写入(和所有其它的过程)将会为文件释放处理,实体将不再存在,恢复文件将应用丢失的所有变化。
Comment