之前寫過一篇刪除oracle home目錄的blog,參考:
Linux 平台誤刪 home oracle 根目錄的解決方法
http://blog.csdn.net/tianlesoftware/article/details/43794273
本篇是這邊的引深,本來應該是年前整理的,拖到年後了。
模擬現狀:
數據庫在正常運行,誤操作,直接rm 掉了數據文件。
測試環境:
[oracle@dg1 trace]$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.1(Santiago)
Oracle 11.2.0.3 單實例。
[oracle@dg1 ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production onWed Aug 27 18:36:32 2014
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise EditionRelease 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Miningand Real Application Testing options
SQL>
這個問題也要分2種情況,一種是歸檔模式,一種是非歸檔模式,歸檔模式處理就容易很多了。但現在很多由開發人員管理的庫是非歸檔,並且也缺乏專業的運維技能,誤操作的概率也會增加很多。
SQL> create tablespace dropspacedatafile '/u01/dropspace01.dbf' size 100m;
Tablespace created.
SQL> create user ahzhixinidentified by ahzhixin default tablespace dropspace;
User created.
SQL> grantconnect,resource,dba to ahzhixin;
Grant succeeded.
SQL> conn ahzhixin/ahzhixin
Connected.
SQL> create table test1 as select * fromall_users;
Table created.
SQL> create table test2 as select * fromall_users;
Table created.
SQL> create table test3 as select * fromall_users;
Table created.
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /u01/archivelog
Oldest online log sequence 83
Next log sequence to archive 85
Current log sequence 85
SQL>
在操作系統上直接刪除數據文件:
[oracle@dg1 u01]$ rm-rf /u01/dropspace01.dbf
此時數據庫還是正常運行,我們查詢我們之前創建的幾張表:
SQL> select count(1) from test1;
COUNT(1)
----------
31
SQL> select count(1) from test2;
COUNT(1)
----------
31
SQL> select count(1) from test3;
COUNT(1)
----------
31
--insert 也沒有問題:
SQL> insert into test1 select * fromall_users;
31 rows created.
SQL> commit;
Commit complete.
SQL> select count(1) from test1;
COUNT(1)
----------
62
至少從目前看,一切都是正常。 這裡正常也是因為我們的操作系統是Linux,當數據文件從操作系統級別被rm掉,但之前打開該文件的進程仍然持有相應的文件句柄,所以指向的文件仍然可以讀寫,並且該文件的文件描述符可以從/proc目錄中獲得,也可以利用這個句柄恢復文件。
如果在這個時候,重啟了數據庫或者操作系統,那麼句柄就會消失,也就只能通過掃描磁盤進行文件恢復。
dbwr進程會打開所有數據文件的句柄,在proc目錄中可以查到這些數據文件的信息,目錄名是進程PID,fd表示文件描述符。
檢查dbwr的進程PID:
[oracle@dg1 trace]$ ps -ef|grep dbw0|grep-v grep
oracle 9964 1 0 00:49 ? 00:00:03 ora_dbw0_dave
[oracle@dg1 trace]$ cd /proc/9964/fd
[oracle@dg1 fd]$ ls -l
這裡的259 就是我們刪掉的數據文件。<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD48cD4gPC9wPjxwPi8v1rG902NwuMO+5LH6zsS8/sP7u9jUrc671sOjujwvcD48cD5bb3JhY2xlQGRnMSBmZF0kIGNwIDI1OS91MDEvZHJvcHNwYWNlMDEuZGJmPC9wPjxwPltvcmFjbGVAZGcxIGZkXSQ8L3A+PHA+IDwvcD48cD4gPC9wPjxwPtLyzqrK/b7dv+LSu9axysdvcGVutcSjrMTHw7RTQ07Ssrvhsru2z7XEseS7r6OsztLDx2Nws/bAtLXEyv2+3c7EvP66zcr9vt2/4rWxx7C1xNDFz6Kyu9K71sKjrMv50tTO0sPH0OjSqr340NByZWNvdmVyo7o8L3A+PHA+IDwvcD48cD5TUUwmZ3Q7IGFsdGVyIGRhdGFiYXNlIGRhdGFmaWxl"/u01/dropspace01.dbf' offline;
Database altered.
SQL> recover datafile'/u01/dropspace01.dbf';
Media recovery complete.
SQL> alter database datafile'/u01/dropspace01.dbf' online;
Database altered.
SQL>
恢復正常。
//文件存在:
[oracle@dg1 u01]$ ls -la/u01/dropspace01.dbf
-rw-r----- 1 oracle oinstall 104865792 Aug27 21:41 /u01/dropspace01.dbf
//重啟數據庫:
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 814227456 bytes
Fixed Size 2232760 bytes
Variable Size 490737224 bytes
Database Buffers 318767104 bytes
Redo Buffers 2490368 bytes
Database mounted.
Database opened.
SQL>
也正常。 這裡有2個注意的問題:數據庫是歸檔模式,數據庫或者操作系統沒有重啟。這2點非常關鍵。 也正式如此,才讓操作比較簡單。
如果是非歸檔模式,那就要復雜很多了。
在非歸檔模式下,如果刪除了數據文件,並且又觸發了CKPT,那麼CKPT 會直接把整個實例中斷掉,也就是說,如果是比較繁忙的數據庫,如果誤刪除數據文件,實例可能會中斷,一旦實例中斷,那麼用之前講的通過句柄恢復就沒有可能性了。
當然也有另一種可能性,就是刪除數據文件之後,可以先通過句柄恢復,然後用expdp導出數據,盡可能的挽救部分數據。 這個動作就是與時間賽跑的過程了。
總之生產環境,操作一定要小心,還有要開歸檔,除非數據允許丟失。