今天接到个电话,说某省的一个非归档数据库中,为某个表空间添加数据文件时误操作,加成了文件系统(数据库是使用裸设备做数据文件的),当时处理的方式是直接在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/