What if a data file of the NonSystem tablespace is missing?

遇到如下这么一道题目:

In ARCHIVELOG mode, the loss of a datafile for any tablespace other than the SYSTEM or UNDO

tablespace affects which objects in the database?

A. The loss affects only objects whose extents reside in the lost datafile.

B. The loss affects only the objects in the affected tablespace, and work can continue in other

tablespaces.

C. The loss will not abort the instance, but will prevent other transactions in any tablespace

other than SYSTEM or UNDO until the affected tablespace is recovered.

D. The loss affects only those users whose default tablespace contains the lost or damaged

datafile. 

给的答案是B,我个人认为A应该也是可以的。  也就是如果一个非系统表空间包含多个数据文件,如果其中一个数据文件丢失了,这个时候访问这个表空间里的表会出错吗? 我觉得如果访问的那个表只要不是存在丢失的那个数据文件上就没有问题的。

测试如下,

 首先创建一个表空间test1, 并且给这个表空间设置2个数据文件test1.dbf 和test2.dbf。 然后在这个表空间上创建一个测试表test1, 如下所示


sys
@ORCL> drop tablespace test1 including contents and datafiles;

Tablespace dropped.

sys
@ORCL> create tablespace test1 datafile 'E:\app\fangyu\oradata\orcl\test1.dbf' size 1m;

Tablespace created.


sys
@ORCL> alter tablespace test1 add datafile 'E:\app\fangyu\oradata\orcl\test2.dbf' size 1m;

Tablespace altered.

sys
@ORCL> create table test1(id numbertablespace test1;

Table created.

现在来查看下新增加的两个数据文件的ID是多少,



sys
@ORCL> select file_idfile_name, status, online_status from dba_data_files where tablespace_name
='TEST1';

   
FILE_ID FILE_NAME            STATUS    ONLINE_STATUS
---------- -------------------- --------- -------
         9 E:\APP\FANGYU\ORADAT AVAILABLE ONLINE
           A\ORCL\TEST1.DBF

        
10 E:\APP\FANGYU\ORADAT AVAILABLE ONLINE
           A\ORCL\TEST2.DBF


sys
@ORCL>

sys
@ORCL>

  可以看到test1.dbf的数据文件号是9, 而test2.dbf的数据文件号是10。 现在向表test1里面插入一条数据,通过其rowid查看这个表中的数据存在哪个数据文件上,(通过调用函数dbms_rowid.rowid_relateive_fno来查找,注意通过函数chartorowid把字符串转成rowid类型)


sys
@ORCL> insert into test1 values(1);

1 row created.

sys
@ORCL> commit;

Commit complete.

sys
@ORCL> select id, rowid from test1;

        ID ROWID
---------- ------------------
         1 AAAR/wAAKAAAAAPAAA

sys
@ORCL> select dbms_rowid.rowid_relative_fno(chartorowid('AAAR/wAAKAAAAAPAAA')) from dual;

DBMS_ROWID.ROWID_RELATIVE_FNO(CHARTOROWID(
'AAAR/WAAKAAAAAPAAA'))
----------------------------------------------------------------
                                                              10

从结果看出,表test1现在存在于数据文件10,也就是test2.dbf上。那么,如果这个时候我们把test1.dbf删除了,应该不会影响到访问表test1的。测试如下,

注意到windows平台下,数据文件都被oracle.exe锁定住了,因此不能在数据库运行的状态下把数据文件test1.dbf删除或者重命名。因此先shutdown instance,


sys
@ORCL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
sys
@ORCL>

 这个时候将test1.dbf改名为test11.dbf, 重新打开数据库。可以预见,在open阶段应该会报错的,如下所示,


sys
@ORCL> startup
ORACLE instance started.

Total System Global Area  
535662592 bytes
Fixed Size                  
1334380 bytes
Variable Size             
264242068 bytes
Database Buffers          264241152 bytes
Redo Buffers                
5844992 bytes
Database mounted.
ORA
-01157cannot identify/lock data file 9 - see DBWR trace file
ORA
-01110: data file 9'E:\APP\FANGYU\ORADATA\ORCL\TEST1.DBF'

这个时候不要去restore/recover这个数据文件,因为我们要看看在丢失数据文件test1.dbf的情况下,表test1能不能被访问,这个时候可以先将test1.dbf 设置成offline,从而打开数据库,


sys
@ORCL> alter database datafile 9 offline;

Database altered.

sys
@ORCL> alter database open;

Database altered.

 这个时候来访问下表test1看看,


sys
@ORCL> select * from test1;

        ID
----------
         1

sys
@ORCL>

可以看到这个表是可以正常被访问的,因为数据文件10是online的。 这个时候我们看看数据文件的状态信息,



sys
@ORCL> select file_idfile_name, status, online_status from dba_data_files where tablespace_name
='TEST1';

   
FILE_ID FILE_NAME            STATUS    ONLINE_STATUS
---------- -------------------- --------- -------
         9 E:\APP\FANGYU\ORADAT AVAILABLE OFFLINE
           A\ORCL\TEST1.DBF

        
10 E:\APP\FANGYU\ORADAT AVAILABLE ONLINE
           A\ORCL\TEST2.DBF


sys
@ORCL>

 从column ONLINE_STATUS看出test1.dbf是offline状态。但是注意列status没有变化,还都是available的!那么STATUS和ONLINE_STATUS这两列表示什么意思,查看文档得到结果如下,

STATUSVARCHAR2(9) File status: AVAILABLE or INVALID (INVALID means that the file number is not in use, for example, a file in a tablespace that was dropped)
ONLINE_STATUSVARCHAR2(7) Online status of the file:
  • SYSOFF

  • SYSTEM

  • OFFLINE

  • ONLINE

  • RECOVER

 因为test1.dbf并没有被drop,只是被置成offline了,所以satus列还是显示available, 而不是invalid. 

在recover数据文件test1.dbf之前,先来查看下数据文件头中的SCN号码,


sys
@ORCL> select file#, creation_change#, checkpoint_change#, last_change# from v$datafile where fil
e# 
in (910);

     
FILE# CREATION_CHANGE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ---------------- ------------------ ------------
         9          3439107            3439940      3439940
        
10          3439147            3439943

sys
@ORCL> select file#, checkpoint_change# from v$datafile_header where filein (910);

     
FILE# CHECKPOINT_CHANGE#
---------- ------------------
         9                  0
        
10            3439943

sys
@ORCL>

注意v$datafile中的change#是从control file里面获取的,而v$datafile_header中的change#是从数据文件头获取的,因此对于file 9 (test1.dbf),在v$datafile_header里面的checkpoint_change#显示是0,因为系统找不到这个数据文件。从数据文件10可以看出当前数据库中数据文件的checkpoint_change#是3439943,比file 9中记录的3439940要大。 现在在操作系统级别将test11.dbf改成会test1.dbf,然后将这个数据文件重新online, 


sys
@ORCL> alter database datafile 9 online;

Database altered.

sys
@ORCL> select file#, creation_change#, checkpoint_change#, last_change# from v$datafile where fil
e# 
in (910);

     
FILE# CREATION_CHANGE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ---------------- ------------------ ------------
         9          3439107            3441957
        
10          3439147            3439943

sys
@ORCL> select file#, checkpoint_change# from v$datafile_header where filein (910);

     
FILE# CHECKPOINT_CHANGE#
---------- ------------------
         9            3441957
        
10            3439943

sys
@ORCL> recover datafile 9;
ORA
-00283: recovery session canceled due to errors
ORA
-01124: cannot recover data file 9 - file is in use or recovery
ORA
-01110: data file 9'E:\APP\FANGYU\ORADATA\ORCL\TEST1.DBF'

可以看到将test1.dbf ONLINE以后,它的checkpoint_change#要比其他数据文件的checkpoint_change#要大,说明数据库已经把这个数据文件的状态更新了,也没有必要去recover. 如果这个时候recover会出错! 应该在offline的状态下进行recovery, 然后再进行online操作的。(其实这个时候recover也没有实际的工作要做)


sys@ORCL> alter database datafile 9 offline;

Database altered.

sys@ORCL> recover datafile 9;
Media recovery complete.
sys@ORCL> alter database datafile 9 online;

Database altered.

 虽然这个时候test1.dbf的checkpoint_change#与其他数据文件不一致,在下次instance重新启动的时候,应该会被re-sync的,


sys
@ORCL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
sys
@ORCL> startup
ORACLE instance started.

Total System Global Area  
535662592 bytes
Fixed Size                  
1334380 bytes
Variable Size             
264242068 bytes
Database Buffers          264241152 bytes
Redo Buffers                
5844992 bytes
Database mounted.
Database opened.
sys
@ORCL> select file#, creation_change#, checkpoint_change#, last_change# from v$datafile where fil
e# 
in (910);

     
FILE# CREATION_CHANGE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ---------------- ------------------ ------------
         9          3439107            3442917
        
10          3439147            3442917

sys
@ORCL> select file#, checkpoint_change# from v$datafile_header where filein (910);

     
FILE# CHECKPOINT_CHANGE#
---------- ------------------
         9            3442917
        
10            3442917

sys
@ORCL>

可以看到数据库现在处于一致状态! 最后把这个测试表空间删除,


sys
@ORCL> drop tablespace test1 including contents and datafiles;

Tablespace dropped.

sys
@ORCL>

 从这个测试来看,只要你访问的表所在的数据文件没有丢失,那么这个表是不会受到它所在的表空间中其他数据文件丢失的影响的。




--------------------------------------
Regards,
FangwenYu
原文地址:https://www.cnblogs.com/fangwenyu/p/1725775.html