--======================
--  只读表空间的备份与恢复
--======================


一、只读表空间的特性

    使用只读表空间避免对静态数据的频繁备份

    当使用alter tablespace tbs read only时,数据文件会执行检查点进程(将所有脏缓冲区的内容写至磁盘),

        当前的SCN号会被标注,同时存储了SCN的数据文件头部被冻结.控制文件内也会记录该数据文件的冻结信息。

    可以清除只读表空间的对象


二、只读表空间的备份

    一般情况下,只读表空间只需要进行一次备份,即当表空间状态发生改变时应立即进行备份

    可以使用OS系统cp命令来备份或RMAN进行备份只读表空间

    使用RMAN时建议启用备份优化选项

        RMAN> CONFIGURE BACKUP OPTIMIZATION ON;


    只读表空间不支持热备

    SQL> alter tablespace tbs1 begin backup;

    alter tablespace tbs1 begin backup

    *

    ERROR at line 1:

    ORA-01642: begin backup not needed for read only tablespace 'TBS1'


三、只读表空间的还原与恢复

    还原与恢复只读表空间的问题在于控制文件如何控制只读表空间,分为下列三种情况:    

    ---------  ---------------  ----------------  -------------------------------------

    case           backup 1     crash status                   recovery

    ---------  ---------------  ----------------  -------------------------------------

    case 1        Read-Only        Read-Only      将备份的只读表空间复制到目的地(Restore)

    case 2        Read-Only        Read-Write     先Restore backup1,后recover(applied log )

    case 3        Read-Write       Read-only       先Restore backup1,后recover(applied log )


    只读表空间恢复时需要考虑的问题

        重建一个控制文件时

        重命名数据文件时

        使用一个备份的控制文件时


    下面对表空间tbs1置为只读后对比前后生成的重建控制文件的脚本       

SQL> alter database backup controlfile to trace as '/tmp/rectl1.sql';  

SQL> alter tablespace tbs1 read only;

SQL> alter database backup controlfile to trace as '/tmp/rectl2.sql';

SQL> ho diff /tmp/rectl1.sql /tmp/rectl2.sql
69,70c69
< '/u01/app/oracle/oradata/orcl/example01.dbf',
< '/u01/app/oracle/oradata/orcl/tbs01.dbf'
---
> '/u01/app/oracle/oradata/orcl/example01.dbf'
97a97,102
> -- Files in read-only tablespaces are now named.
> ALTER DATABASE RENAME FILE 'MISSING00006'
> TO '/u01/app/oracle/oradata/orcl/tbs01.dbf';
>
> -- Online the files in read-only tablespaces.
> ALTER TABLESPACE "TBS1" ONLINE;

    对比两者

        1.使用create controlfile命令时,datafile中未列出只读表空间的数据文件

        2.成功创建控制文件并打开后,使用alter database rename file命令重命名只读表空间的数据文件

        3.使用alter tablespace readonly_tablespacename online 将只读表空间联机


四、演示只读表空间变化的恢复过程        

    1. 演示整个过程为只读表空间的情况(对应前面描述的case 1)       

SQL> create table scott.tb1 tablespace tbs1                         
2 as select * scott.emp;

SQL> commit;

SQL> alter tablespace tbs1 read only;

SQL> select file#,name,enabled v$datafile where file#=6;

FILE# NAME ENABLED
---------- --------------------------------------------- ----------
6 /u01/app/oracle/oradata/orcl/tbs01.dbf READ ONLY

SQL> ho cp /u01/app/oracle/oradata/orcl/tbs01.dbf /tmp/tbs01.dbf

SQL> insert into scott.tb1(empno,ename) values(3333,'Thomas');

SQL> update scott.tb1 set sal=sal*1.2 where ename='SCOTT';

SQL> delete scott.tb1 where ename='SCOTT';
--执行上述三条命令,收到下列同样的错误提示
ORA-00372: file 6 cannot be modified at this time
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'

        从上面的演示可以看出对只读表空间内的数据作任何DML操作均不可用

        在 ​​Oracle 表空间与数据文件 ​​    一文中,可以对只读表空间作delete操作(版本是10.2.0.1.0),应该是数

        据库补丁的问题,    此版本为10.2.0.4.0。       

--使用vim 打开?/oradata/orcl/tbs01.dbf文件做任意操作来模拟破坏该只读表空间的数据文件    
--重启数据库后收到下面的错误提示
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'

SQL> ho cp /tmp/tbs01.dbf /u01/app/oracle/oradata/orcl/tbs01.dbf

SQL> alter database open;

SQL> select count(1) scott.tb1;

COUNT(1)
----------
16

    2. 演示由只读变为读写后发生损坏且只有只读备份的恢复情况(对应前面描述的case 2)      

SQL> alter tablespace tbs1 read write;                                                             

SQL> insert into scott.tb1(empno,ename) values(3333,'Thomas');

SQL> commit;

--使用vim 打开/u01/app/oracle/oradata/orcl/tbs01.dbf文件做任意操作来模拟破坏该读写表空间的数据文件
--重启数据库后未收到错误提示

SQL> insert into scott.tb1(empno,ename) values(4444,'Jackson');
insert into scott.tb1(empno,ename) values(4444,'Jackson')
*
ERROR at line 1:
ORA-00376: file 6 cannot be read at this time
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'

SQL> select * v$recover_file;

FILE# ONLINE ONLINE_ ERROR CHANGE# TIME
---------- ------- ------- ---------------- ---------- ---------
6 OFFLINE OFFLINE FILE NOT FOUND 0

SQL> ho cp /tmp/tbs01.dbf /u01/app/oracle/oradata/orcl/tbs01.dbf

SQL> recover datafile 6;
Media recovery complete.

SQL> alter tablespace tbs1 online;

Tablespace altered.
SQL> select * scott.tb1 where ename='Thomas';

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
3333 Thomas

    3. 演示由读写表空间变为只读表空间,且仅有读写表空间备份的恢复(对应前面描述的case 3)      

SQL> select file#,name,enabled  v$datafile where file#=6;                         

FILE# NAME ENABLED
---------- --------------------------------------------- ----------
6 /u01/app/oracle/oradata/orcl/tbs01.dbf READ WRITE

SQL> alter tablespace tbs1 begin backup;

SQL> ho cp /u01/app/oracle/oradata/orcl/tbs01.dbf /tmp/tbs01.dbf

SQL> alter tablespace tbs1 end backup;

SQL> delete scott.tb1 where empno=3333;

SQL> commit;

SQL> alter tablespace tbs1 read only;

--使用vim 打开?/oradata/orcl/tbs01.dbf文件做任意操作来模拟破坏该只读表空间的数据文件
--重启数据库后收到下面的错误提示

ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'

SQL> ho cp /tmp/tbs01.dbf /u01/app/oracle/oradata/orcl/tbs01.dbf

SQL> recover datafile 6;

SQL> alter database open;

SQL> select * scott.tb1 where ename='Thomas';

no rows selected

    4. 演示数据文件状态发生多次变化且在变化时没有任何备份的恢复处理(实际上使用日志来重新构造该数据文件)      

SQL> select file#,name,enabled  v$datafile where file#=6;                      

FILE# NAME ENABLED
---------- --------------------------------------------- ----------
6 /u01/app/oracle/oradata/orcl/tbs01.dbf READ WRITE

SQL> drop table scott.tb1;

SQL> commit;

SQL> alter tablespace tbs1 read only;

SQL> alter tablespace tbs1 read write;

SQL> create table scott.tb2 tablespace tbs1 as select * scott.emp;

SQL> commit;

SQL> alter system checkpoint;

[oracle@oradb orcl]$tail -n 50 $ORACLE_BASE/admin/orcl/bdump/alert_orcl.log
Errors in file /u01/app/oracle/admin/orcl/bdump/orcl_ckpt_40.trc:
ORA-01171: datafile 6 going offline due to error advancing checkpoint
ORA-01122: database file 6 failed verification check
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'
ORA-01251: Unknown File Header Version read for file number 6

SQL> select * v$recover_file;

FILE# ONLINE ONLINE_ ERROR CHANGE# TIME
---------- ------- ------- --------------- ---------- ---------
6 OFFLINE OFFLINE FILE NOT FOUND 0

SQL> select file#,name,status v$datafile where file#=6;

FILE# NAME STATUS
---------- --------------------------------------------- -------
6 /u01/app/oracle/oradata/orcl/tbs01.dbf RECOVER

SQL> alter database create datafile 6;

SQL> recover datafile 6;
Media recovery complete.

SQL> alter database datafile 6 online;

SQL> select count(1) scott.tb2;

COUNT(1)
----------
16

    5. 演示删除只读表空间上的对象     

SQL> select file#,name,enabled  v$datafile where file#=6;                       

FILE# NAME ENABLED
---------- --------------------------------------------- ----------
6 /u01/app/oracle/oradata/orcl/tbs01.dbf READ ONLY

SQL> select segment_name,segment_type,tablespace_name,owner dba_segments where
2 tablespace_name='TBS1' and segment_name='TB2';

SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME OWNER
-------------------- ------------------ ------------------------------ ----------
TB2 TABLE TBS1 SCOTT

SQL> drop table scott.tb2;

Table dropped.

五、总结

    1. 表空间置为只读后将减少数据的备份量

    2. 表空间置为只读后,不能对其中的对象执行任何DML操作

    3. 只读表空间内的对象可以被清除,因为drop命令更新了数据字典,而不更新对象本身

    4. 当表空间的状态发生变化时,应立即备份该表空间,以减少恢复工作

    5. 对于状态多次发生改变且未及时备份的情况,日志未损坏时,可以使用联机重做、归档日志来进行恢复

        使用下列命令来实现:

            删除受损的数据文件(rm dbfile.dbf)

            重建受损的数据文件(alter database create datafile n)

            进行介质恢复(recover datafile n)

            使受损的数据文件联机(alter database datafile n online)

    6. 演示中多为在mount状态下来恢复,生产环境中多在open状态下恢复,可以按下列步骤实现

          先将受损的只读表空间(数据文件)脱机(offline)

          使用备份的表空间(数据文件)来还原(restore)

          使用归档、联机日志进行介质恢复(recover)

          使恢复成功的表空间(数据文件)联机(online)

    7. 对于原始介质受损,不能恢复到原始位置的情况下,使用下面的命令实现

          alter database rename file '<dir1>' to '<dir2>';


六、 快捷参考

有关性能优化请参考

    ​​Oracle硬解析与软解析 ​

    ​​共享池的调整与优化(Sharedpool Tuning) ​

    ​​Buffercache 的调整与优化(一) ​

    ​​Oracle表缓存(cachingtable)的使用 ​


有关ORACLE体系结构请参考

    ​​Oracle表空间与数据文件 ​

    ​​Oracle密码文件 ​

    ​​Oracle参数文件 ​

    ​​Oracle联机重做日志文件(ONLINE LOG FILE) ​

    ​​Oracle控制文件(CONTROLFILE) ​

    ​​Oracle归档日志​

    ​​Oracle回滚(ROLLBACK)和撤销(UNDO) ​

    ​​Oracle数据库实例启动关闭过程 ​

    ​​Oracle10g SGA 的自动化管理 ​

    ​​Oracle实例和Oracle数据库(Oracle体系结构) ​


有关闪回特性请参考

    ​​Oracle闪回特性(FLASHBACK DATABASE) ​

    ​​Oracle闪回特性(FLASHBACK DROP & RECYCLEBIN) ​

    ​​Oracle闪回特性(Flashback Query、FlashbackTable) ​

    ​​Oracle闪回特性(Flashback Version、Flashback Transaction) ​


有关基于用户管理的备份和备份恢复的概念请参考

    ​​Oracle冷备份 ​

    ​​Oracle热备份 ​

    ​​Oracle备份恢复概念 ​

    ​​Oracle实例恢复 ​

    ​​Oracle基于用户管理恢复的处理 ​​(详细描述了介质恢复及其处理)

    ​​SYSTEM表空间管理及备份恢复 ​

    ​​SYSAUX表空间管理及恢复 ​


有关RMAN的备份恢复与管理请参考

    ​​RMAN 概述及其体系结构 ​

    ​​RMAN 配置、监控与管理 ​

    ​​RMAN 备份详解 ​

    ​​RMAN 还原与恢复 ​

    ​​RMANcatalog 的创建和使用 ​

    ​​基于catalog 创建RMAN存储脚本 ​

​基于catalog 的RMAN 备份与恢复​

​使用RMAN迁移文件系统数据库到ASM​

    ​​RMAN 备份路径困惑(使用plus archivelog时) ​


有关ORACLE故障请参考

    ​​ORA-32004的错误处理 ​

    ​​ORA-01658错误 ​

    ​​CRS-0215错误处理 ​

    ​​ORA-00119,ORA-00132 错误处理 ​

    ​​又一例SPFILE设置错误导致数据库无法启动 ​

    ​​对参数FAST_START_MTTR_TARGET= 0 的误解及设定 ​

    ​​SPFILE错误导致数据库无法启动(ORA-01565) ​


有关ASM请参考

    ​​创建ASM实例及ASM数据库 ​

    ​​ASM 磁盘、目录的管理 ​

    ​​使用 ASMCMD 工具管理ASM目录及文件 ​


有关SQL/PLSQL请参考

    ​​SQLPlus常用命令 ​

    ​​替代变量与SQL*Plus环境设置 ​

    ​​使用Uniread实现SQLplus翻页功能 ​

    ​​SQL 基础 -->SELECT 查询

    ​​SQL 基础 --> NEW_VALUE的使用

    ​​SQL 基础 --> 集合运算(UNION与UNION ALL)

    ​​SQL 基础 --> 常用函数

    ​​SQL 基础 --> 视图(CREATEVIEW)

    ​​SQL 基础 --> 创建和管理表

    ​​SQL 基础 --> 多表查询

    ​​SQL 基础 --> 过滤和排序

    ​​SQL 基础 --> 子查询

    ​​SQL 基础 --> 分组与分组函数

    ​​SQL 基础 --> 层次化查询(STARTBY ... CONNECT BY PRIOR)

    ​​SQL 基础 --> ROLLUP与CUBE运算符实现数据汇总

    ​​PL/SQL --> 游标

    ​​PL/SQL --> 异常处理(Exception)

    ​​PL/SQL --> 语言基础

    ​​PL/SQL --> 流程控制

    ​​PL/SQL --> PL/SQL记录

    ​​PL/SQL --> 包的创建与管理

    ​​PL/SQL --> 隐式游标(SQL%FOUND)

    ​​PL/SQL --> 包重载、初始化

    ​​PL/SQL --> DBMS_DDL包的使用

    ​​PL/SQL --> DML 触发器

    ​​PL/SQL --> INSTEAD OF 触发器

    ​​PL/SQL --> 存储过程

    ​​PL/SQL --> 函数

    ​​PL/SQL --> 动态SQL

    ​​PL/SQL --> 动态SQL的常见错误


有关ORACLE其它特性

    ​​Oracle常用目录结构(10g) ​

    ​​使用OEM,SQL*Plus,iSQL*Plus 管理Oracle实例 ​

    ​​日志记录模式(LOGGING、FORCE LOGGING 、NOLOGGING) ​

    ​​表段、索引段上的LOGGING与NOLOGGING ​

    ​​OralceOMF 功能详解 ​

    ​​Oracle用户、对象权限、系统权限 ​​ 

    ​​Oracle角色、配置文件 ​

    ​​Oracle分区表 ​

    ​​Oracle外部表 ​

    ​​使用外部表管理Oracle 告警日志(ALAERT_$SID.LOG) ​

    ​​簇表及簇表管理(Index clustered tables) ​

    ​​数据泵 EXPDP 导出工具的使用 ​

    ​​数据泵 IMPDP 导入工具的使用 ​

    ​​导入导出 Oracle 分区表数据 ​

    ​​SQL*Loader使用方法 ​

    ​​启用用户进程跟踪 ​

    ​​配置非默认端口的动态服务注册 ​

    ​​配置ORACLE 客户端连接到数据库 ​

    ​​systemsys,sysoper sysdba 的区别 ​

    ​​ORACLE_SID、DB_NAME、INSTANCE_NAME、DB_DOMIAN、GLOBAL_NAME ​

    ​​Oracle补丁全集 (Oracle 9i 10g 11g Path) ​

    ​​Oracle10.2.0.1 升级到10.2.0.4 ​

    ​​Oracle彻底 kill session ​