代码改变世界

己亥清爽恢复系列之数据文件2篇:非核心数据文件物理损坏或丢失(非关键表空间)

2019-05-17 17:56  askscuti  阅读(282)  评论(0编辑  收藏  举报

己亥清爽系列说明:清爽系列是作为恢复系列的基础篇,基于FS(File System)文件系统的手工还原恢复,也叫基于用户管理的还原恢复,来自于博客园AskScuti

实验说明:在有完全备份基础下,物理删除非关键系统数据文件,模拟介质损坏或丢失,并进行手工完全还原恢复操作。

基于版本:Oracle 11gR2 11.2.0.4 AskScuti

概念说明:请严格区分什么叫还原(Restore),什么叫恢复(Recover)

还原(Restore):如果是基于用户管理(手工)的还原恢复,需要用户主动在系统层面进行拷贝粘贴,这个操作过程称之为还原;如果是基于恢复管理器(RMAN)的恢复,则通过Restore命令进行还原(自动进行),后者不在基础篇讨论。

恢复(Recover):在完成还原动作之后,数据回到了还原点,但从这个还原点到宕机时间点之间的数据,就要利用归档日志和在线日志进行前滚,直至应用到宕机前最后一次commit提交的状态(完全恢复),或应用到指定的某个时间点(不完全恢复)。

目录

1. 备份(略)

2. 实验

  2.1 创建表空间 henry

  2.2 创建表 henry

  2.3 单独热备 henry 数据文件

  2.4 插入数据并提交

  2.5 手工删除物理文件

  2.6 继续插入数据并提交

  2.7 触发完全检查点刷数据

  2.8 先启库再修复

    2.8.1 将错误文件脱机并启动数据库

    2.8.2 还原数据文件

    2.8.3 恢复数据文件

    2.8.4 将数据文件联机

    2.8.5 验证数据

  2.9 先修复再启库

    2.9.1 还原数据文件

    2.9.2 恢复数据文件

    2.9.3 打开数据库

    2.9.4 验证数据

 

1. 备份(略)

基于手工冷备(冷备、脱机备份、一致性备份 是一个概念;热备、联机备份、非一致性备份 也是同一个概念)全库。点此处查看如何进行简单的手工冷备。

2. 实验

2.1 创建表空间 henry

SQL> select b.name,a.name,a.bytes/1024/1024 as MB from v$datafile a,v$tablespace b where a.ts#=b.ts#;

NAME    NAME                                      MB
------- ------------------------------------------ ---------
SYSTEM  /u01/app/oracle/oradata/PROD1/system01.dbf  720
SYSAUX  /u01/app/oracle/oradata/PROD1/sysaux01.dbf  570
UNDOTBS1 /u01/app/oracle/oradata/PROD1/undotbs01.dbf 95
USERS   /u01/app/oracle/oradata/PROD1/users01.dbf    5
EXAMPLE /u01/app/oracle/oradata/PROD1/example01.dbf 345.625

SQL> create tablespace henry datafile '/u01/app/oracle/oradata/PROD1/henry01.dbf' size 5m;

Tablespace created.

SQL> select b.name,a.name,a.bytes/1024/1024 as MB from v$datafile a,v$tablespace b where a.ts#=b.ts#;

NAME        NAME                                    MB
----------- ------------------------------------------ -------
SYSTEM      /u01/app/oracle/oradata/PROD1/system01.dbf 720
SYSAUX      /u01/app/oracle/oradata/PROD1/sysaux01.dbf 570
UNDOTBS1    /u01/app/oracle/oradata/PROD1/undotbs01.dbf 95
USERS       /u01/app/oracle/oradata/PROD1/users01.dbf   5
EXAMPLE     /u01/app/oracle/oradata/PROD1/example01.dbf 345.625
HENRY       /u01/app/oracle/oradata/PROD1/henry01.dbf   5

2.2 创建表 henry

SQL> create table henry(id number) tablespace henry;

Table created.

2.3 单独热备 henry 数据文件

因为第1步备份里面没有我们新创建的 henry 数据文件备份(如果新增的表空间没有备份,一样可以恢复,后面其它博文将进行实验说明)。另外,如果你在生产库,请严格按照手工热备方式来操作,请勿直接在系统层面进行 copy,运气不好,会造成 split block 的产生(Split Block将在后面其它博文单独进行说明)。

查看所有数据文件在控制文件中目前的 SCN 号,将 henry 表空间单独至于备份模式(注意,涉及到局部检查点,henry 表空间进入备份模式,触发局部检查点,对应数据文件的 SCN 号就会变为最新),还可以通过 v$backup 查看当前几号文件可以进行备份,最后,拷贝完成后,将 henry 表空间 end backup。

SQL> select a.file#,a.ts#,b.name,a.checkpoint_change#,a.last_change# from v$datafile a,v$tablespace b where a.ts#=b.ts#;

   FILE# TS#  NAME   CHECKPOINT_CHANGE# LAST_CHANGE#
-------  ---- ----  ------------------ ------------
     1    0  SYSTEM    1289476
     2    1  SYSAUX    1289476
     3    2  UNDOTBS1  1289476
     4    4  USERS     1289476
     5    6  EXAMPLE   1289476
     6    7  HENRY     1289476

6 rows selected.

SQL> alter tablespace henry begin backup;

Tablespace altered.

SQL> select a.file#,a.ts#,b.name,a.checkpoint_change#,a.last_change# from v$datafile a,v$tablespace b where a.ts#=b.ts#;

    FILE# TS#  NAME    CHECKPOINT_CHANGE# LAST_CHANGE#
--------- ----- ------- ------------------ ------------
     1    0   SYSTEM    1289476
     2    1   SYSAUX    1289476
     3    2   UNDOTBS1  1289476
     4    4   USERS     1289476
     5    6   EXAMPLE   1289476
     6    7   HENRY     1289512

6 rows selected.

SQL> select * from v$backup;

     FILE# STATUS  CHANGE#  TIME
---------- -------- -------- -----------------
     1 NOT ACTIVE   0
     2 NOT ACTIVE   0
     3 NOT ACTIVE   0
     4 NOT ACTIVE   0
     5 NOT ACTIVE   0
     6 ACTIVE       1289512 2019-05-17 16:14:57

6 rows selected.

SQL> !cp /u01/app/oracle/oradata/PROD1/henry01.dbf /u01/app/oracle/backup/

SQL> alter tablespace henry end backup;

Tablespace altered.

将 henry 表空间 end backup 后,我们发出完全检查点命令,让所有文件 SCN 号追平。

SQL> alter system checkpoint;

System altered.

SQL> select a.file#,a.ts#,b.name,a.checkpoint_change#,a.last_change# from v$datafile a,v$tablespace b where a.ts#=b.ts#;

   FILE# TS#  NAME     CHECKPOINT_CHANGE# LAST_CHANGE#
-------- ---- --------- ------------------ ------------
     1   0   SYSTEM    1289578
     2   1   SYSAUX    1289578
     3   2   UNDOTBS1  1289578
     4   4   USERS     1289578
     5   6   EXAMPLE   1289578
     6   7   HENRY     1289578

6 rows selected.

2.4 插入数据并提交

SQL> insert into henry select object_id from dba_objects where rownum<51;

50 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from henry;

  COUNT(*)
----------
    50

表 henry,是在 SYS 用户下面,但使用的是 henry 表空间。

SQL> select owner,table_name,tablespace_name from dba_tables where table_name='HENRY';

OWNER TABLE_NAME TABLESPACE_NAME
----- ---------- ---------------
SYS   HENRY      HENRY

2.5 手工删除物理文件

SQL> !rm -rf /u01/app/oracle/oradata/PROD1/henry01.dbf

请思考:底层物理文件丢失或者损坏之后,是否可以继续往 henry 表中插入数据?是否可以正常提交数据?

2.6 继续插入数据并提交

SQL> select count(*) from henry;

  COUNT(*)
----------
    50

SQL> insert into henry values(666);

1 row created.

SQL> insert into henry values(888);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into henry values(999);

1 row created.

SQL> select count(*) from henry;

  COUNT(*)
----------
    53

可以继续操作,这本身没有什么稀奇的,因为所有操作都是在内存中进行的,现阶段和物理文件无关。需要注意的一点是:commit 提交操作是触发 LGWR 进程写日志,和 DBWR 写不写数据没半毛钱关系。请仔细留意上面最后一条语句查询的行数:53

2.7 触发完全检查点刷数据

这时,手工触发完全检查点,作用是:将当前数据库缓冲区(db buffer cache)中的所有缓存数据刷入到磁盘中

SQL> alter system checkpoint;
alter system checkpoint
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 14894
Session ID: 1 Serial number: 11

请思考:为什么会报错?(根据具体环境而定,有些机器会话暂时没反应过来)重启数据库?一样报错。因为将缓存数据写入物理磁盘,前提是要找到 henry 表空间所对应的 henry01.dbf 物理文件,而该文件被彻底删除,所以报错。

[oracle@henry ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri May 17 15:23:24 2019

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  417546240 bytes
Fixed Size               2228944 bytes
Variable Size            293604656 bytes
Database Buffers         117440512 bytes
Redo Buffers              4272128 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/u01/app/oracle/oradata/PROD1/henry01.dbf'

2.8 先启库再修复

2.8.1 将错误文件脱机并启动数据库

有些时候,非核心数据文件丢失,可能情况不太紧急,所以,为了不影响数据库其它业务,可将有问题的文件先脱机,然后将数据库启动,回头再处理丢失的文件。

SQL> select * from v$recover_file;

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

SQL> alter database datafile 6 offline;

Database altered.

SQL> alter database open;

Database altered.

2.8.2 还原数据文件

数据库启动之后,再回头处理丢失的文件。将 henry01.dbf 还原,查看 v$recover_file 得知,需要恢复。

SQL> !cp /u01/app/oracle/backup/henry01.dbf /u01/app/oracle/oradata/PROD1/

SQL> select * from v$recover_file;

FILE#  ONLINE  ONLINE_STATUS  ERROR CHANGE# TIME
----- -------- -------------- ----- ------- --------------------
6    OFFLINE  OFFLINE              1289512 2019-05-17 16:14:57

2.8.3 恢复数据文件

SQL> recover datafile 6;
Media recovery complete.
SQL> alter database datafile 6 online;

2.8.4 将数据文件联机

SQL> alter database datafile 6 online;

2.8.5 验证数据 

SQL> select count(*) from henry;

  COUNT(*)
----------
    52

请思考:为何是52条?2.6小节查的明明是53条。因为完全恢复是恢复到最后一次 commit 提交时的状态,2.6小节最后一次提交是再插入 999 前做的 commit,最后一条 999 因为没能提交,所以介质恢复将回滚掉 999 。

2.9 先修复再启库

也可以在 mount 状态下,先进行修复,完成修复后,再启动数据库。操作和 2.8 小节一致,仅顺序不一样。

删除文件,重启数据库,报错:

SQL> !rm -rf /u01/app/oracle/oradata/PROD1/henry01.dbf

SQL> startup force;
ORACLE instance started.

Total System Global Area  417546240 bytes
Fixed Size               2228944 bytes
Variable Size            293604656 bytes
Database Buffers         117440512 bytes
Redo Buffers              4272128 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '/u01/app/oracle/oradata/PROD1/henry01.dbf'

2.9.1 还原数据文件

SQL> !cp /u01/app/oracle/backup/henry01.dbf /u01/app/oracle/oradata/PROD1/

2.9.2 恢复数据文件

SQL> select * from v$recover_file;

FILE# ONLINE ONLINE_STATUS  ERROR CHANGE#   TIME
----- ------ -------------- ----- ---------- --------------------
6   ONLINE  ONLINE               1288907   2019-05-17 17:36:24

SQL> recover datafile 6;
Media recovery complete.

2.9.3 打开数据库

SQL> alter database open;

Database altered.

2.9.4 验证数据

SQL> select count(*) from henry;

  COUNT(*)
----------
    52