今天接到個(gè)電話,說某省的一個(gè)非歸檔數(shù)據(jù)庫中,為某個(gè)表空間添加數(shù)據(jù)文件時(shí)誤操作,加成了文件系統(tǒng)(數(shù)據(jù)庫是使用裸設(shè)備做數(shù)據(jù)文件的),當(dāng)時(shí)處理的方式是直接在os級rm掉了這個(gè)數(shù)據(jù)文件。結(jié)果在oem里面點(diǎn)擊表空間的時(shí)候就報(bào)數(shù)據(jù)文件找不到了。然后,另一個(gè)同事將該數(shù)據(jù)文件執(zhí)行offline drop后,在oem里面點(diǎn)擊表空間不報(bào)錯(cuò)了。
但是這是否就正常了呢?
我們說,表空間就像一個(gè)容器,像一個(gè)空的水杯,一旦我們把水倒進(jìn)水杯里面,我們就分辨不出那些水是第一次倒入的,哪些是第二次倒入的。我們也無法把已經(jīng)倒進(jìn)去的水區(qū)別開來,把最后一次倒入的水在倒出來。
我們檢查了那個(gè)數(shù)據(jù)文件說涉及到的表空間,將這個(gè)表空間下的所有的表都count(*)一遍,如果沒有報(bào)錯(cuò),那么我們比較幸運(yùn),那個(gè)被rm掉的文件里面沒有數(shù)據(jù),如果有數(shù)據(jù),那就比較慘了……count(*)的結(jié)果表明:我們就是屬于那種不幸的情況。
我們首先考慮恢復(fù)數(shù)據(jù),由于是非規(guī)定模式,redolog就顯得比較重要了。如果redolog沒有使用一圈的話,我們還能用redolog來進(jìn)行恢復(fù):
Database log mode ? ? ? ? ? ? ? No Archive Mode
Automatic archival ? ? ? ? ? ? ? Disabled
Archive destination ? ? ? ? ? ? / oradata / arch / oralocal
Oldest online log sequence ? ? ? 101
Current log sequence ? ? ? ? ? ? 103
SQL >
SQL > select * from v $ log ;
?
?? ? GROUP #? ? THREAD#? SEQUENCE#? ? ? BYTES? ? MEMBERS ARCHIV STATUS? ? ? ? ? ? ? ? ? ? ? ? ? ?FIRST_CHANGE# FIRST_TIME
-------- -- ---------- ---------- ---------- ---------- ------ -------------------------------- ------------- ------------
?? ? ? ? 1 ? ? ? ? ? 1 ? ? ? ? 103 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? CURRENT ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832673 08 - DEC - 07
?? ? ? ? 2 ? ? ? ? ? 1 ? ? ? ? 101 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832669 08 - DEC - 07
?? ? ? ? 3 ? ? ? ? ? 1 ? ? ? ? 102 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832671 08 - DEC - 07
?
SQL > create tablespace test datafile ' /oradata/test.dbf ' size 1 m ;
?
Tablespace created .
?
SQL > create table hr . xx tablespace test as select * from dba_users where 1 = 2 ;
?
Table created .
?
SQL > insert into hr . xx select * from dba_users ;
?
37 rows created .
?
SQL > /
?
37 rows created .
?
SQL > /
?
37 rows created .
?
SQL > /
?
37 rows created .
?
SQL > commit ;
?
Commit complete .
?
SQL > select count ( * ) from hr . xx ;
?
? COUNT ( * )
-------- --
?? ? ? 148
?
SQL > select * from v $ log ;
?
?? ? GROUP #? ? THREAD#? SEQUENCE#? ? ? BYTES? ? MEMBERS ARCHIV STATUS? ? ? ? ? ? ? ? ? ? ? ? ? ?FIRST_CHANGE# FIRST_TIME
-------- -- ---------- ---------- ---------- ---------- ------ -------------------------------- ------------- ------------
?? ? ? ? 1 ? ? ? ? ? 1 ? ? ? ? 103 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? CURRENT ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832673 08 - DEC - 07
?? ? ? ? 2 ? ? ? ? ? 1 ? ? ? ? 101 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832669 08 - DEC - 07
?? ? ? ? 3 ? ? ? ? ? 1 ? ? ? ? 102 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832671 08 - DEC - 07
?
SQL > !
[ oracle @ localdb ~]$ cd / oradata
[ oracle @ localdb oradata ]$ ll
total 1088
drwxr - xr - x ? 3 oracle dba ? ? 4096 Dec ? 6 15 : 42 arch
drwxr - xr - x ? 3 oracle dba ? ? 4096 Dec ? 6 15 : 37 cfile
drwxr - xr - x ? 3 oracle dba ? ? 4096 Dec ? 6 16 : 19 dfile
drwxr - xr - x ? 3 oracle dba ? ? 4096 Dec ? 6 15 : 37 lfile
drwx ---- --? 2 oracle dba? ?16384 Dec? 6 15:33 lost+found
- rw - r --- --? 1 oracle dba 1056768 Dec? 8 11:23 test.dbf
[ oracle @ localdb oradata ]$ rm test . dbf
[ oracle @ localdb oradata ]$ ll
total 48
drwxr - xr - x ? 3 oracle dba ? 4096 Dec ? 6 15 : 42 arch
drwxr - xr - x ? 3 oracle dba ? 4096 Dec ? 6 15 : 37 cfile
drwxr - xr - x ? 3 oracle dba ? 4096 Dec ? 6 16 : 19 dfile
drwxr - xr - x ? 3 oracle dba ? 4096 Dec ? 6 15 : 37 lfile
drwx ---- --? 2 oracle dba 16384 Dec? 6 15:33 lost+found
[ oracle @ localdb oradata ]$ exit
exit
?
SQL > select * from v $ log ;
?
?? ? GROUP #? ? THREAD#? SEQUENCE#? ? ? BYTES? ? MEMBERS ARCHIV STATUS? ? ? ? ? ? ? ? ? ? ? ? ? ?FIRST_CHANGE# FIRST_TIME
-------- -- ---------- ---------- ---------- ---------- ------ -------------------------------- ------------- ------------
?? ? ? ? 1 ? ? ? ? ? 1 ? ? ? ? 103 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? CURRENT ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832673 08 - DEC - 07
?? ? ? ? 2 ? ? ? ? ? 1 ? ? ? ? 101 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832669 08 - DEC - 07
?? ? ? ? 3 ? ? ? ? ? 1 ? ? ? ? 102 ? ? 10485760 ? ? ? ? ? 1 NO ? ? ? INACTIVE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 832671 08 - DEC - 07
?
SQL > shutdown abort ;
ORACLE instance shut down .
SQL >
SQL > startup
ORACLE instance started .
?
Total System Global Area ? 313860096 bytes
Fixed Size ? ? ? ? ? ? ? ? ? 1299624 bytes
Variable Size ? ? ? ? ? ? ? 276826968 bytes
Database Buffers ? ? ? ? ? ? 29360128 bytes
Redo Buffers ? ? ? ? ? ? ? ? 6373376 bytes
Database mounted .
ORA - 01157 : cannot identify / lock data file 6 - see DBWR trace file
ORA - 01110 : data file 6 : ' /oradata/test.dbf '
?
?
SQL > alter database datafile 6 offline ;
alter database datafile 6 offline
*
ERROR at line 1 :
ORA - 01145 : offline immediate disallowed unless media recovery enabled
?
?
SQL > alter database datafile 6 offline drop ;
?
Database altered .
?
SQL > alter database create datafile 6 as ' /oradata/test.dbf ' ;
?
Database altered .
?
?
SQL > recover datafile 6 ;
Media recovery complete .
SQL > alter database open ;
?
Database altered .
?
SQL > select count ( * ) from hr . xx ;
select count ( * ) from hr . xx
?? ? ? ? ? ? ? ? ? ? ? ?*
ERROR at line 1 :
ORA - 00376 : file 6 cannot be read at this time
ORA - 01110 : data file 6 : ' /oradata/test.dbf '
?
?
SQL > alter database datafile 6 online ;
?
Database altered .
?
SQL > select count ( * ) from hr . xx ;
?
? COUNT ( * )
-------- --
?? ? ? 148
上述的這個(gè)情況是屬于比較幸運(yùn)的情況,我們的redolog還沒有被重復(fù)利用,但是實(shí)際中遇到的情況往往是,等到發(fā)現(xiàn)數(shù)據(jù)文件誤刪報(bào)錯(cuò),已經(jīng)是好幾天之外了,生產(chǎn)系統(tǒng)中redolog的切換,已經(jīng)切換n次了。因此,在這里,我們只能盡量的挽回?cái)?shù)據(jù)了:
首先查看被刪除的數(shù)據(jù)文件涉及到哪幾個(gè)表空間,將這些表空間里面的所有表都count一次,以確定有哪些表受到影響,如果是分區(qū)表,還比較好辦些,分別count每一個(gè)分區(qū)的數(shù)據(jù)確認(rèn)沒有問題,將沒有問題的數(shù)據(jù)進(jìn)行exp備份,或者ctas到別的表。然后將表drop掉之后進(jìn)行重建,注意重建的時(shí)候也要重新表的索引約束等等。如果對于非分區(qū)表,無法一個(gè)分區(qū)一個(gè)分區(qū)的進(jìn)行測試,因此只能exp表,在exp的時(shí)候,會報(bào)錯(cuò),但是無須理會,exp出來成一個(gè)文件后,可以imp到另一用戶,重新本用戶的表,在insert into table select * from user_b.table,注意索引和約束也要重建。
當(dāng)然,重建表只是最低影響的處理,正確的處理方式應(yīng)該是重建表空間,對表空間中的所有表都進(jìn)行重建,但是這個(gè)工程量就比較大了……
DBA切記:數(shù)據(jù)文件一旦加入表空間,切勿隨意刪除!!(特別是9i的數(shù)據(jù)庫,10g還能drop empty datafile。)
引用:http://www.oracleblog.cn/working-case/deal-with-delete-datafile-in-noarch-mode/