[20151028]linux下刪除資料檔案的恢復細節4

lfree發表於2015-10-28
[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.檢查恢復情況,我建議最好關閉資料庫看看.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-1817084/,如需轉載,請註明出處,否則將追究法律責任。

相關文章