今天接到個電話,說某省的一個非歸檔數據庫中,為某個表空間添加數據文件時誤操作,加成了文件系統(數據庫是使用裸設備做數據文件的),當時處理的方式是直接在os級rm掉了這個數據文件。結果在oem里面點擊表空間的時候就報數據文件找不到了。然后,另一個同事將該數據文件執行offline drop后,在oem里面點擊表空間不報錯了。
但是這是否就正常了呢?
我們說,表空間就像一個容器,像一個空的水杯,一旦我們把水倒進水杯里面,我們就分辨不出那些水是第一次倒入的,哪些是第二次倒入的。我們也無法把已經倒進去的水區別開來,把最后一次倒入的水在倒出來。
我們檢查了那個數據文件說涉及到的表空間,將這個表空間下的所有的表都count(*)一遍,如果沒有報錯,那么我們比較幸運,那個被rm掉的文件里面沒有數據,如果有數據,那就比較慘了……count(*)的結果表明:我們就是屬于那種不幸的情況。
我們首先考慮恢復數據,由于是非規定模式,redolog就顯得比較重要了。如果redolog沒有使用一圈的話,我們還能用redolog來進行恢復:
SQL
>
archive
log
list
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
上述的這個情況是屬于比較幸運的情況,我們的redolog還沒有被重復利用,但是實際中遇到的情況往往是,等到發現數據文件誤刪報錯,已經是好幾天之外了,生產系統中redolog的切換,已經切換n次了。因此,在這里,我們只能盡量的挽回數據了:
首先查看被刪除的數據文件涉及到哪幾個表空間,將這些表空間里面的所有表都count一次,以確定有哪些表受到影響,如果是分區表,還比較好辦些,分別count每一個分區的數據確認沒有問題,將沒有問題的數據進行exp備份,或者ctas到別的表。然后將表drop掉之后進行重建,注意重建的時候也要重新表的索引約束等等。如果對于非分區表,無法一個分區一個分區的進行測試,因此只能exp表,在exp的時候,會報錯,但是無須理會,exp出來成一個文件后,可以imp到另一用戶,重新本用戶的表,在insert into table select * from user_b.table,注意索引和約束也要重建。
當然,重建表只是最低影響的處理,正確的處理方式應該是重建表空間,對表空間中的所有表都進行重建,但是這個工程量就比較大了……
DBA切記:數據文件一旦加入表空間,切勿隨意刪除!!(特別是9i的數據庫,10g還能drop empty datafile。)
引用:http://www.oracleblog.cn/working-case/deal-with-delete-datafile-in-noarch-mode/