Linux下利用檔案描述符恢復的成功失敗實驗
資料誤刪除是作為初級運維人員常常遇到的“低階錯誤”,一些有經驗的老手有時也在疲勞、不冷靜的情況下“馬失前蹄”。一旦誤刪除資料檔案,儘快採用影響最小、最迅速的手段恢復資料庫是第一要務。
恢復資料的方法很多,比如冷熱備份、閃回資料庫等等,如果是直接從作業系統OS層面刪除資料檔案,在Linux/Unix環境下,有一些優選手段可以使用。其中之一就是檔案描述符(File Description)。
1、聊聊File Description
不同的作業系統,在實現CPU管理、記憶體管理和儲存檔案管理的時候,採用不同的方式手段。
在Linux和Unix裡面,採用檔案描述符進行檔案管理。一個程式要開啟檔案,是呼叫作業系統核心功能,核心返回一個檔案描述符。對檔案的讀寫操作也透過這個描述符進行操作。作業系統刪除一個檔案的時候,是要確定檔案所有檔案描述符都是釋放掉之後,才會最後刪除。
我們的誤操作,如果是發生在正在執行的資料庫系統中,檔案雖然在作業系統上刪除不可見了。但是資料庫Oracle程式中還會保有一些存在的檔案描述符,借用這些檔案描述符,我們是可能找到檔案資訊,來恢復資料檔案的。
所以,一旦發生了誤刪除動作,切忌三點:心態冷靜、斷開應用、維護現場不關庫。
但是,在實際中,這種可以快速恢復的技術,並不是百分之百成功的。使用檔案描述符恢復資料需要資料庫不能關閉、資料庫程式不能“自動剔除”資料檔案等。本文從兩個實驗著手,介紹一下操作方法和前提。
2、實驗環境搭建
我們選擇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中,更容易出現誤刪除的情況。
3、一次“不成功”的實驗
首先是一次不成功的實驗。運維生產環境中,我們的原則永遠是穩定。危險不確定的事情場景,一定要避免。哪怕不做、不修、不最佳化,也不要讓業務系統的可用性去冒險。
實驗環境中,我們總能夠發現很多知識和現象。首先,我們嘗試刪除資料檔案,確認檔案位置。
[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%有效。如果時間很長,或者進行過很多特殊操作,這個微弱的檔案描述符是會消失的!
下面我們進行一次成功的實驗。
4、一次“成功”的實驗
我們藉助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
恢復完成,實驗成功。
5、結論
本篇文章的書寫,有一半目的是揭示檔案內部的執行機制,另一半是記錄下Linux下使用檔案描述符FD來恢復資料的方法。我們說,從運維角度看,直接繞過資料庫對OS進行檔案操作是非常不成熟的做法,無論是出於什麼目的。很多致命的錯誤都是一系列的rm造成的。願文章描述的場景永不會在所有運維生產系統中出現!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29067253/viewspace-2151757/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用rman做資料檔案丟失的恢復實驗
- 基於檔案描述符的恢復
- 恢復之利用備份在所有控制檔案丟失情況下恢復(四)
- 恢復之利用備份在所有控制檔案丟失情況下恢復(三)
- 恢復之利用備份在所有控制檔案丟失情況下恢復(二)
- 恢復之利用備份在所有控制檔案丟失情況下恢復(一)
- 備份恢復實驗(1)丟失部分控制檔案
- 恢復案例:歸檔模式下丟失全部資料檔案的恢復模式
- RMAN基於備份控制檔案恢復失敗
- 檔案描述符恢復rm掉的dbf
- 歸檔模式下資料檔案丟失的恢復模式
- 【備份恢復】歸檔模式下丟失系統關鍵資料檔案 利用RMAN備份恢復模式
- 【恢復】Redo日誌檔案丟失的恢復
- 恢復丟失的控制檔案
- 【備份恢復】利用 備份控制檔案到指定目錄下的控制檔案 恢復控制檔案
- 【備份恢復】所有控制檔案丟失後 利用trace中的控制檔案備份執行恢復
- 在歸檔模式下丟失日誌檔案的恢復模式
- Linux下檔案描述符Linux
- 使用檔案描述符恢復誤刪除的資料檔案
- 控制檔案丟失恢復
- 【控制檔案丟失恢復】
- 剪下的檔案還能恢復嗎,恢復剪貼丟失的檔案
- oracle實驗記錄(恢復-丟失未備份資料檔案)Oracle
- 資料檔案丟失的恢復
- 控制檔案全部丟失的恢復
- 控制檔案部分丟失的恢復
- Oracle Password檔案丟失的恢復Oracle
- 控制檔案丟失的RMAN恢復
- 非歸檔無備份下控制檔案丟失的恢復
- 儲存互斥失敗導致資料丟失的資料恢復成功案例資料恢復
- 【備份恢復】非歸檔模式下丟失任意資料檔案 恢復操作模式
- 利用備份的控制檔案恢復
- oracle實驗記錄 (恢復-rman基於控制檔案的恢復)Oracle
- 控制檔案備份增加、破壞恢復系列實驗(下)
- 歸檔模式下丟失普通資料檔案並恢復模式
- 控制檔案丟失恢復(二)
- 控制檔案全部丟失恢復
- 備份與恢復--利用備份的控制檔案恢復