Suppose you have accidentally removed a datafile from
your production database? First thing, DON’T PANIC! There’s an easy way to
recover deleted datafiles, for as long as your database remains up. The
procedure below works on linux, however this method conceivably can work for
other platforms.
This procedure will even work if your database is in
NOARCHIVELOG mode.
First let’s create a tablespace.
SQL> create tablespace test
datafile '/data/oracle/app/oracle/oradata/TESTDB/test1.dbf' size 10M;
Tablespace created.
SQL> conn test/test
Connected.
SQL> create table test_table
(key number(1));
Table created.
SQL> insert into test_table
values (7);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test_table;
KEY
----------
7
So we have a schema test with a simple table that was
created in the test datafile (this was default tablespace of test user). Now we
are going to remove this test datafile that is in the
/data/oracle/app/oracle/oradata/TESTDB directory:
[oracle@localhost fd]$ rm –rf
/data/oracle/app/oracle/oradata/TESTDB/test1.dbf
It’s really gone. Let’s test we can’t read from that
table again:
[oracle@localhost fd]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0
Production on Tue Apr 23 10:50:23 2013
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning option
SQL> conn test/test
Connected.
SQL> select * from test_table;
KEY
----------
7
SQL> conn / as sysdba
Connected.
SQL> conn test/test
Connected.
SQL> select * from test_table;
select * from test_table
*
ERROR at line 1:
ORA-01116: error in opening database file 6
ORA-01110: data file 5: '/data/oracle/app/oracle/oradata/TESTDB/test1.dbf’
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
For a simple table already buffered, you can still retrieve the data from
cache, but as soon as you are forced to attempt a read from disk you are going
to error. Oops! That’s not good. So what are the options? flashback database,
was my first thought when this happened for real, but that was not available,
backups? In this situation still you can recover you datafile by below steps.
For ARCHIVELOG
DATABASE:
First find a PID of a process we know would have a File Descriptor
open for the file we have just removed. Database writer is a good candidate:
[oracle@NVMBD1BZY150D00 TESTDB]$ ps -ef |grep
dbw
oracle 43643 1 0 13:39 ?
00:00:00 ora_dbw0_TESTDB
We could do an lsof on this PID to confirm this is the case:
[oracle@NVMBD1BZY150D00 TESTDB]$
/usr/sbin/lsof -p 43643
COMMAND PID USER FD TYPE DEVICE
SIZE/OFF NODE NAME
oracle 43643 oracle rtd DIR
253,0 4096 2 /
oracle 43643 oracle DEL REG 0,4
31227916 /SYSV00000000
oracle 43643 oracle mem REG
253,0 5624 8323305 /lib64/libaio.so.1.0.1
oracle 43643 oracle mem CHR 1,5
4014 /dev/zero
oracle 43643 oracle mem REG
253,4 58949 14403358
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libnque11.so
oracle 43643 oracle mem REG
253,4 1544 14395587
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
oracle 43643 oracle mem REG
253,0 65928 8323102 /lib64/libnss_files-2.12.so
oracle 43643 oracle mem REG
253,0 22536 8323474 /lib64/libdl-2.12.so
oracle 43643 oracle mem REG
253,4 153574 21258376
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libocrutl11.so
oracle 43643 oracle mem REG
253,4 3319072 21258375
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libocrb11.so
oracle 43643 oracle mem REG
253,4 1590995 21258374
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libocr11.so
oracle 43643 oracle mem REG 253,4
12755 14402512 /data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libskgxn2.so
oracle 43643 oracle mem REG
253,4 17319952 21258371
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libhasgen11.so
oracle 43643 oracle mem REG
253,4 161764 14402492
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libdbcfg11.so
oracle 43643 oracle mem REG
253,4 228765 21258373
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libclsra11.so
oracle 43643 oracle mem REG
253,4 7955322 21258383 /data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libnnz11.so
oracle 43643 oracle mem REG
253,4 1010297 14403515
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libskgxp11.so
oracle 43643 oracle mem REG
253,4 589359 21258391 /data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libcell11.so
oracle 43643 oracle mem REG
253,4 12259 14402220
/data/oracle/app/oracle/product/11.2.0/dbhome_1/lib/libodmd11.so
oracle 43643 oracle 0r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 1w CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 2w CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 3r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 4r CHR 1,5
0t0 4014 /dev/zero
oracle 43643 oracle 5r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 6r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 7u REG
253,4 1544 14395587
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
oracle 43643 oracle 8r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 9r CHR 1,3
0t0 4012 /dev/null
oracle 43643 oracle 10r CHR 1,5
0t0 4014 /dev/zero
oracle 43643 oracle 11w REG
253,4 2396 14680217 /data/oracle/app/oracle/admin/TESTDB/bdump/alert_TESTDB.log
oracle 43643 oracle 12u REG
253,4 1544 14395587
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
oracle 43643 oracle 13r REG
253,4 1101312 32800880
/data/oracle/app/oracle/product/11.2.0/dbhome_1/rdbms/mesg/oraus.msb
oracle 43643 oracle 14r DIR 0,3
0 16643132 /proc/43643/fd
oracle 43643 oracle 15r CHR 1,5
0t0 4014 /dev/zero
oracle 43643 oracle 16u REG
253,4 1544 14395587
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
oracle 43643 oracle 17uR REG
253,4 24 14395352 /data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/lkTESTDB
oracle 43643 oracle 20u IPv6
16643553 0t0 UDP *:61571
oracle 43643 oracle 21r REG
253,4 1101312 32800880
/data/oracle/app/oracle/product/11.2.0/dbhome_1/rdbms/mesg/oraus.msb
oracle 43643 oracle 256u REG
253,4 9846784 14532752 /data/oracle/app/oracle/oradata/TESTDB/control01.ctl
oracle 43643 oracle 257u REG
253,4 9846784 14532753 /data/oracle/app/oracle/oradata/TESTDB/control02.ctl
oracle 43643 oracle 258uW REG
253,4 104865792 14532757 /data/oracle/app/oracle/oradata/TESTDB/system.dbf
oracle 43643 oracle 259uW REG
253,4 104865792 14532758 /data/oracle/app/oracle/oradata/TESTDB/user04.dbf
oracle 43643 oracle 260uW REG
253,4 104865792 14532759 /data/oracle/app/oracle/oradata/TESTDB/sysaux.dbf
oracle 43643 oracle 261uW REG
253,4 524296192 14532760 /data/oracle/app/oracle/oradata/TESTDB/undo.dbf
oracle 43643 oracle 262uW REG
253,4 1048584192 14532761 /data/oracle/app/oracle/oradata/TESTDB/temp1.dbf
oracle 43643
oracle 263uW REG 253,4 1073750016 14532816
/data/oracle/app/oracle/oradata/TESTDB/test1.dbf (deleted)
Missed out lots of /dev/shm entries in the above. We can
see on the last line, the /tmp/test01.dbf datafile and we see it’s marked as
deleted. We can also see it has a file descriptor 263. You can also see this
from the following directory:
[oracle@NVMBD1BZY150D00 TESTDB]$ ls -ltar
/proc/43643/fd/
total 0
dr-xr-xr-x. 7 oracle oinstall 0
Dec 12 13:39 ..
dr-x------. 2 oracle oinstall 0
Dec 12 13:39 .
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 9 -> /dev/null
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 8 -> /dev/null
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 7 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 6 -> /dev/null
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 5 -> /dev/null
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 4 -> /dev/zero
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 3 -> /dev/null
lrwx------. 1 oracle oinstall 64 Dec 12
15:20 263 ->
/data/oracle/app/oracle/oradata/TESTDB/test1.dbf (deleted)
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 262 -> /data/oracle/app/oracle/oradata/TESTDB/temp1.dbf
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 261 -> /data/oracle/app/oracle/oradata/TESTDB/undo.dbf
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 260 -> /data/oracle/app/oracle/oradata/TESTDB/sysaux.dbf
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 259 -> /data/oracle/app/oracle/oradata/TESTDB/user04.dbf
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 258 -> /data/oracle/app/oracle/oradata/TESTDB/system.dbf
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 257 -> /data/oracle/app/oracle/oradata/TESTDB/control02.ctl
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 256 -> /data/oracle/app/oracle/oradata/TESTDB/control01.ctl
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 21 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/rdbms/mesg/oraus.msb
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 20 -> socket:[16643553]
l-wx------. 1 oracle oinstall
64 Dec 12 15:20 2 -> /dev/null
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 17 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/lkTESTDB
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 16 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 15 -> /dev/zero
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 14 -> /proc/43643/fd
lr-x------. 1 oracle oinstall
64 Dec 12 15:20 13 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/rdbms/mesg/oraus.msb
lrwx------. 1 oracle oinstall
64 Dec 12 15:20 12 ->
/data/oracle/app/oracle/product/11.2.0/dbhome_1/dbs/hc_TESTDB.dat
l-wx------. 1 oracle oinstall
64 Dec 12 15:20 11 ->
/data/oracle/app/oracle/admin/TESTDB/bdump/alert_TESTDB.log
lr-x------. 1 oracle oinstall 64 Dec 12 15:20 10 -> /dev/zero
l-wx------. 1 oracle oinstall 64 Dec 12 15:20 1 -> /dev/null
lr-x------. 1 oracle oinstall 64 Dec 12 15:20 0 -> /dev/null
Where we have used the PID of the dbw process.
Again we see the file is marked as deleted and again it’s
FD 263. Now this is the idea Frits mentioned and we can start actually
recovering the data:
[oracle@NVMBD1BZY150D00 TESTDB]$ cd
/proc/43643/fd/
From the /proc/43643/fd/ directory I ran a cat on the
File Descriptor number and sent it to another filename test1_tmp.dbf. Now you
have recovered the data, you can switch the tablespace to use this datafile:
SQL>alter database datafile '/data/oracle/app/oracle/oradata/TESTDB/test1.dbf'
offline;
Database altered.
SQL> alter database rename file
'/data/oracle/app/oracle/oradata/TESTDB/test1.dbf' to
'/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf';
Database altered.
SQL> alter database datafile
'/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf' online;
alter database datafile
'/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf' online
*
ERROR at line 1:
ORA-01113: file 5 needs media
recovery
ORA-01110: data file 5:
'/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf'
SQL> recover datafile '/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf'
Media recovery complete.
SQL> alter database datafile
'/data/oracle/app/oracle/oradata/TESTDB/test1_tmp.dbf' online;
Database altered.
SQL> select * from test.test_table;
KEY
----------
7
I hope this article helped you. Your suggestions/feedback are most welcome.
Keep learning... Have a great day!!!