oracle手工管理的不完全恢复

广大2年前技术文章630

一)使用当前控制文件做不完全恢复

示例1: 恢复过去某个时间点误删除的table(基于时间点的不完全恢复)

前提:在这个状态下先在OS下做一个数据文件和控制文件的冷备。
SQL> shutdown immediate;
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.dbf  /u01/back
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.ctl  /u01/back
[oracle@orcl  ~]$ startup

1)环境:scott用户在user表空间下有个t1表

SQL> select * from scott.t1;

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

2)误删除了t1表,并purge了。
SQL> drop table scott.t1 purge;
SQL> set linesize 300;
col member for a50;
col name  for a50;
select thread#,group#,bytes/1024/1024/1024 GB,status from v$log;

SQL> alter system switch logfile;
SQL> select name from v$archived_log;
NAME
--------------------------------------------------------------------------------
/u01/arch_std/1_74_1102346968.arch
/u01/arch_std/1_75_1102346968.arch     drop table t1 purge的日志条目切换到此归档日志里了。


3)通过logmr 找出误操作的ddl命令的timestamp 或 san,然后做一个不完全恢复。
建目录、设置参数
$>mkdir -p /home/oracle/logmnrtest
SQL> alter system set utl_file_dir='/home/oracle/logmnrtest' scope=spfile;
SQL> startup force;
SQL> show parameter utl_file_dir
NAME                                  TYPE        VALUE
------------------------------------ ----------- ------------------------------
utl_file_dir                          string      /home/oracle/logmnrtest
指定logmnr目录
execute dbms_logmnr_d.build('dict.ora','/home/oracle/logmnrtest',dbms_logmnr_d.store_in_flat_file);
添加第一条日志条目
execute dbms_logmnr.add_logfile(logfilename=>'/u01/arch_std/1_74_1102346968.arch',options=>dbms_logmnr.new);
添加后续日志条目
execute dbms_logmnr.add_logfile(logfilename=>'/u01/arch_std/1_75_1102346968.arch',options=>dbms_logmnr.addfile);
解析日志条目
execute dbms_logmnr.start_logmnr(dictfilename=>'/home/oracle/logmnrtest/dict.ora',options=>dbms_logmnr.ddl_dict_tracking);
查看v$logmnr_contents视图
col sql_redo for a60;
select username,scn,to_char(timestamp,'yyyy-mm-dd hh24:mi:ss') time,sql_redo from v$logmnr_contents WHERE table_name='T1' and lower(sql_redo) like 'drop table%';

USERNAME                              SCN TIME                SQL_REDO
------------------------------ ---------- ------------------- ------------------------------------------------------------
SYS                               5943017 2022-04-28 16:32:30 drop table scott.t1 purge;                        5926002 2022-04-28 15:46:07 drop table t1 purge;

关闭lognmr
SQL> execute dbms_logmnr.end_logmnr;

4)关闭数据库,删除所有dbf,准备做不完全恢复
SQL> shutdown abort

[oracle@orcl ~]$ cd /u01/app/oracle/oradata_std/orcl/
[oracle@orcl ~]$ rm *.dbf

5)还原所有备份的数据文件
[oracle@orcl ~]$ cp /u01/back/*.dbf /u01/app/oracle/oradata_std/orcl/

6)根据log miner提供的信息,做基于时间点的不完全恢复

SQL> startup
ORACLE instance started.
Total System Global Area 3206836224 bytes
Fixed Size                  2257520 bytes
Variable Size             721423760 bytes
Database Buffers         2466250752 bytes
Redo Buffers               16904192 bytes
Database mounted.
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

SQL> recover database until time '2022-04-28 16:32:30';
Media recovery complete.

7)resetlogs方式打开数据库
SQL> alter database open resetlogs;

8)验证
SQL> select * from scott.t1;
        ID
----------
         1
 
9)看看在resetlogs后,日志sequence重置了。
SQL> select * from v$log;
SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES  BLOCKSIZE    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIM NEXT_CHANGE# NEXT_TIME
---------- ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------- ------------ ---------
         1          1          1  104857600        512          1 NO  CURRENT                5943010 28-APR-22   2.8147E+14
         2          1          0  104857600        512          1 YES UNUSED                       0                      0
         3          1          0  104857600        512          1 YES UNUSED                       0                      0

示例2:当前日志组损坏,造成数据库崩溃。

丢失的日志是最新的正在使用的,他们应该只执行虚假恢复,然后打开resetlogs。丢失当前日志的数据。

前提:在这个状态下先在OS下做一个数据文件和控制文件的冷备。
SQL> shutdown immediate;
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.dbf  /u01/back
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.ctl  /u01/back
[oracle@orcl  ~]$ startup

1、创建测试数据
session 1
SQL> create table scott.t2(id int);
SQL> insert into scott.t2 values(1);
SQL> commit;
SQL> alter system archive log current;
SQL> insert into scott.t2 values(2);
SQL> commit;
SQL> select * from scott.t2;
        ID
----------
         1   这条已经归档
         2 这条在当前日志中,没有归档

SQL> select group#,sequence#,status from v$log;
    GROUP#  SEQUENCE# STATUS
---------- ---------- ----------------
         1         22 CURRENT   查v$logfile知道group1是redo01.log
         2         20 INACTIVE
         3         21 ACTIVE

2、模拟redo丢失
session 2
[oracle@orcl orcl]$ rm redo01.log
session 1
SQL> shutdown abort
session 2

3、数据文件还原--测试也可以不执行这步
[oracle@orcl orcl]$ rm *.dbf
[oracle@orcl orcl]$ cp /u01/back/*.dbf  /u01/app/oracle/oradata_std/orcl/   还原所有数据文件备份

4、只能执行到mount状态
session 1
SQL> startup
ORA-00313: 无法打开日志组 1 (用于线程 1) 的成员 ORA-00312:
联机日志 1 线程 1: '/u01/app/oracle/oradata_std/orcl/redo01.log'

5、执行恢复
SQL> recover database  尝试完全恢复,用尽所有归档日志
SQL> recover database until cancel;
ORA-00279: 更改 1016334 (在 04/08/2016 15:45:03 生成) 对于线程 1 是必需的 ORA-00289:
建议: /u01/arch/orcl/arch_1_904564083_22.log   一定要确认一下这个日志是否是当前日志。
ORA-00280: 更改 1016334 (用于线程 1) 在序列 #22 中
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
cancel
Media recovery cancelled.

6、resetlogs方式启库
SQL> alter database open resetlogs;

7、验证测试数据,丢失了删除redo的数据
SQL> select * from scott.t2;
        ID
----------
         1

二)使用备份控制文件做不完全恢复

1)为什么会使用备份的控制文件?

当前控制文件全部损坏。

当控制文件全部损坏+数据文件损坏

2)使用备份的控制文件恢复数据库的语法:

recover database until [time|change] using backup controlfile;

[time|change]是可选的,就是说如果条件满足,仍然可以做到完全恢复。

接下来会有如下选项:

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}

此语法的出现是由于控制文件和当前日志不一致,当前日志的scn总是最新的,而控制文件可能是旧的或尚未更新的(类似shutdwon abort操作)。

AUTO:根据v$archived_log和在归档目的已经存在的归档日志前滚恢复,但不包括前滚current log;

filename:不在v$archived_log中的日志,指控制文件中受损的归档记录或current log

CANCEL:退出。

3)使用backup controlfile子句的恢复数据库之后,一律要使用alter database open resetlogs打开数据库。

示例1:控制文件和全部数据文件损坏

环境:当前控制文件损坏,数据文件损坏,有数据文件全备,但之后增加了表空间,并备份了配套的控制文件。

模式:所有数据文件备份(老)------(新建表空间abcd)-----备份控制文件(次新)------日志文件(新)

分析:新建表空间数据文件损坏, 全备里没有该数据文件的备份,控制文件有abcd的描述,当前控制文件又丢失,只能用备份的控制文件恢复。

SQL> shutdown immediate;
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.dbf  /u01/back
[oracle@orcl  ~]$ startup
1)环境:
SQL> select * from v$tablespace;
SQL> select GROUP#,SEQUENCE#,STATUS from v$log;

    GROUP#  SEQUENCE# STATUS    
---------- ----------------- ------------- --------------------------------------------------------------
     1         7            CURRENT
     2         5            INACTIVE
     3         6            INACTIVE

SQL> create tablespace abcd datafile '/u01/app/oracle/oradata_std/orcl//abcd01.dbf' size 5m;
SQL> create table scott.a1 (name char(10)) tablespace abcd;
SQL> insert into scott.a1 values('a');
SQL> commit;
SQL> select * from scott.a1;
NAME
----------
a

SQL> alter system switch logfile;

2)备份控制文件
SQL> alter database backup controlfile to '/u01/app/oracle/oradata_std/orcl/con.bak1';

3)模拟abcd01.dbf损坏和所有ctl损坏
[oracle@orcl ~]$rm /u01/app/oracle/oradata_std/orcl/abcd01.dbf   数据库open状态,删除abcd01.dbf数据文件
SQL> alter system flush buffer_cache;   db buffer 清空
SQL> select * from scott.a1;  换个session查看 a1表物理读失败

[oracle@orcl ~]$ rm *.ctl
[oracle@orcl ~]$ rm *.dbf


4)关闭数据库
SQL> shutdown abort;


5)恢复所有数据文件备份和备份的控制文件,准备做不完全恢复
[oracle@orcl ~]$ cp /u01/back/*.dbf  /u01/app/oracle/oradata_std/orcl/
[oracle@orcl ~]$ cp con.bak1 control01.ctl
[oracle@orcl ~]$ cp con.bak1 control02.ctl
[oracle@orcl ~]$ cp con.bak1 control03.ctl

SQL> startup
SQL> col name for a50;
SQL> select file#,checkpoint_change#,name from v$datafile;
     FILE# CHECKPOINT_CHANGE# NAME
---------- ------------------ --------------------------------------------------
         1            6676574 /u01/app/oracle/oradata_std/orcl/system01.dbf
         2            6676574 /u01/app/oracle/oradata_std/orcl/sysaux01.dbf
         3            6676601 /u01/app/oracle/oradata_std/orcl/abcd01.dbf
         4            6676574 /u01/app/oracle/oradata_std/orcl/user01.dbf
         5            6676574 /u01/app/oracle/oradata_std/orcl/example01.dbf
         6            6676574 /u01/app/oracle/oradata_std/orcl/test01.dbf
         7            6676574 /u01/app/oracle/oradata_std/orcl/undotbs01.dbf
SQL> select file#,checkpoint_change#  from v$datafile_header;
     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1            6676601
         2           6676601
         3                  0
         4            6676601
         5            6676601
         6            6676601
         7            6676601
可以看出:
file3 在控制文件里记录是abcd01.dbf,而与之对应的数据文件3是不存在的,

6)使用备份控制文件恢复
SQL> recover database using backup controlfile;
ORA-00283: 恢复会话因错误而取消
ORA-01110: 数据文件 3: '/u01/app/oracle/oradata_std/orcl/abcd01.dbf'
ORA-01157: 无法标识/锁定数据文件 3 - 请参阅 DBWR 跟踪文件
ORA-01110: 数据文件 3: '/u01/app/oracle/oradata_std/orcl/abcd01.dbf'
此错没有abcd表空间,但只要控制文件里记录了abcd就好办,方法是建一个datafile的空文件,而其中内容可由日志文件recover(前滚)时填补出来。

SQL> alter database create datafile '/u01/app/oracle/oradata_std/orcl/abcd01.dbf';
SQL> recover database using backup controlfile;   再次使用备份控制文件恢复
ORA-00308: 无法打开归档日志 '/u01/disk1/orcl/arch_1_804846837_9.log'
ORA-27037: 无法获得文件状态
Linux Error: 2: No such file or directory
Additional information: 3

archive日志前滚结束了,但当前日志里还有信息需要恢复
注意: 对于这个例子来说,一定要看清提示:如果提示的不是归档的日志(是当前日志),则要直接要输入filename 而不能输入auto,否则open时会失败。

SQL> recover database using backup controlfile;   再次使用备份控制文件恢复
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/oradata_std/orcl/redo03.log   哪一个日志是当前日志,需要尝试。
已应用的日志。
完成介质恢复。

7)resetlogs打开数据库

SQL> alter database open resetlogs;

8)验证
SQL> select * from scott.a1;
NAME
----------------------------------------
a

示例2:控制文件和之后的单个数据文件损坏

环境:当前控制文件损坏,新建表空间在备份控制文件之后

模式:全备(老)-----备份控制文件(次新)-----新建表空间abcd------日志文件(新)

分析:整个恢复过程中datafile结构有了变化,变化发生在备份控制文件之后,新增了表空间abcd。控制文件备份里没有此表空间记录,但日志里有。

SQL> shutdown immediate;
[oracle@orcl ~]$ cp /u01/app/oracle/oradata_std/orcl/*.dbf  /u01/back
[oracle@orcl  ~]$ startup
1)环境
SQL> drop tablespace abcd including contents and datafiles;
SQL> alter database backup controlfile to '/u01/app/oracle/oradata_std/orcl/con.bak';
控制文件备份中没有abcd表空间
SQL> create tablespace abcd datafile '/u01/app/oracle/oradata_std/orcl/abcd01.dbf' size 5m;
SQL> create table scott.r1 (id int) tablespace abcd ;
SQL> insert into scott.r1 values(1);
SQL> commit;

SQL> select * from v$tablespace;
SQL> select * from scott.r1;
        ID
----------
         1

SQL>select GROUP#,SEQUENCE#,STATUS from v$log;
    GROUP#    SEQUENCE#     STATUS
---------- ---------- --------------- ----------------------------------------------------
    1           1         CURRENT
    2           0         UNUSED
    3           0         UNUSED

2)模拟新建数据文件损坏
[oracle@orcl ~]rm abcd01.dbf
SQL>alter system flush buffer_cache;

SQL>select * from scott.r1;
ERROR at line 1:
ORA-01116: error in opening database file 5
ORA-01110: data file 5: '/u01/app/oracle/oradata_std/orcl/abcd01.dbf'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3

3)关闭数据库
SQL>shutdown abort

4)还原所有数据文件,以老控制文件替换当前控制文件
[oracle@orcl ~]$ cd /u01/app/oracle/oradata_std/orcl/
[oracle@orcl ~]$ rm *.ctl
[oracle@orcl ~]$ cp con.bak control01.ctl
[oracle@orcl ~]$ cp con.bak /u01/app/oracle/fast_recovery_area/orcl/control02.ctl


5)启动数据库
SQL> startup
ORACLE 例程已经启动。
......
数据库装载完毕。
ORA-01589: 要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选项

SQL> col name for a80;
select file#,checkpoint_change#,name from v$datafile;
select file#,checkpoint_change# from v$datafile_header;

6)使用备份控制文件恢复数据库
SQL> recover database using backup controlfile;
ORA-00279: 更改 6676343 (在 01/16/2013 14:11:39 生成) 对于线程 1 是必需的
ORA-00289: 建议: /u01/disk1/orcl/arch_1_804846837_4.log
ORA-00280: 更改 6676343 (用于线程 1) 在序列 #4 中

指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
auto
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/oradata_std/orcl/redo01.log
ORA-00283: 恢复会话因错误而取消
ORA-01244: 未命名的数据文件由介质恢复添加至控制文件
ORA-01110: 数据文件 3: '/u01/app/oracle/oradata_std/orcl/abcd01.dbf'
ORA-01112: 未启动介质恢复

SQL> select file#,checkpoint_change#,name from v$datafile;
     FILE# CHECKPOINT_CHANGE# NAME
---------- ------------------ --------------------------------------------------
         1            6678002 /u01/app/oracle/oradata_std/orcl/system01.dbf
         2            6678002 /u01/app/oracle/oradata_std/orcl/sysaux01.dbf
         3            6677999 /u01/oracle/dbs/UNNAMED00003   这是从日志回写到控制文件中的名字,需要重命名
         4            6678002 /u01/app/oracle/oradata_std/orcl/user01.dbf
         5            6678002 /u01/app/oracle/oradata_std/orcl/example01.dbf
         6            6678002 /u01/app/oracle/oradata_std/orcl/test01.dbf
         7            6678002 /u01/app/oracle/oradata_std/orcl/undotbs01.dbf

SQL> select file#,checkpoint_change# from v$datafile_header;
     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1            6678002
         2            6678002
         3                  0   这里需要建立一个空的数据文件。
         4            6678002
         5            6678002
         6            6678002
         7            6678002

7)建立数据文件并对控制文件中未知的数据文件重命名
SQL> alter database create datafile '/u01/oracle/dbs/UNNAMED00003' as '/u01/app/oracle/oradata_std/orcl/abcd01.dbf';


上面的命令一石二鸟,自动完成了两个动作
加了一个数据文件abcd01.dbf,
重命名控制文件UNNAMED00003为abcd01.dbf

SQL> select file#,checkpoint_change#,name from v$datafile;
     FILE# CHECKPOINT_CHANGE# NAME
---------- ------------------ --------------------------------------------------
         1            6678002 /u01/app/oracle/oradata_std/orcl/system01.dbf
         2            6678002 /u01/app/oracle/oradata_std/orcl/sysaux01.dbf
         3            6677999 /u01/app/oracle/oradata_std/orcl/abcd01.dbf
         4            6678002 /u01/app/oracle/oradata_std/orcl/user01.dbf
         5            6678002 /u01/app/oracle/oradata_std/orcl/example01.dbf
         6            6678002 /u01/app/oracle/oradata_std/orcl/test01.dbf
         7            6678002 /u01/app/oracle/oradata_std/orcl/undotbs01.dbf

建立数据文件前后的对比:
前:
SQL> select file#,checkpoint_change#,name from v$datafile;

     FILE# CHECKPOINT_CHANGE# NAME
---------- ------------------ --------------------------------------------------------------------------------
         1            5950651 /u01/app/oracle/oradata_std/orcl/system01.dbf
         2            5950651 /u01/app/oracle/oradata_std/orcl/sysaux01.dbf
         3            5950651 /u01/app/oracle/oradata_std/orcl/undotbs01.dbf
         4            5950651 /u01/app/oracle/oradata_std/orcl/users01.dbf
         5            5951310 /u01/app/oracle/product/11.2.0/dbhome_1/dbs/UNNAMED00005   

SQL> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1            5951312
         2            5951312
         3            5951312
         4            5951312
         5                  0
后:
SQL> select file#,checkpoint_change#,name from v$datafile;

     FILE# CHECKPOINT_CHANGE# NAME
---------- ------------------ --------------------------------------------------------------------------------
         1            5950651 /u01/app/oracle/oradata_std/orcl/system01.dbf
         2            5950651 /u01/app/oracle/oradata_std/orcl/sysaux01.dbf
         3            5950651 /u01/app/oracle/oradata_std/orcl/undotbs01.dbf
         4            5950651 /u01/app/oracle/oradata_std/orcl/users01.dbf
         5            5951310 /u01/app/oracle/oradata_std/orcl/abcd01.dbf

SQL> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1            5951312
         2            5951312
         3            5951312
         4            5951312
         5            5951310

            

SQL> recover database using backup controlfile;
ORA-00279: change 5950192 generated at 04/28/2022 18:54:33 needed for thread 1
ORA-00289: suggestion : /u01/arch_std/1_1_1103219970.arch
ORA-00280: change 5950192 for thread 1 is in sequence #1
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/app/oracle/oradata_std/orcl/redo01.log   --需要一个个测试那个redo文件
Log applied.
Media recovery complete.


SQL> set linesize 200;
col member for a50;
select v1.group#,member, sequence#, first_change# from v$log v1, v$logfile v2 where v1.group# =v2.group#;

    GROUP# MEMBER                                              SEQUENCE# FIRST_CHANGE#
---------- -------------------------------------------------- ---------- -------------
         1 /u01/app/oracle/oradata_std/orcl/redo01.log                 1       5950648   --scn号不一致,当前使用的redo,需要用这个恢复。
         3 /u01/app/oracle/oradata_std/orcl/redo03.log                 0             0
         2 /u01/app/oracle/oradata_std/orcl/redo02.log                 0             0

8)resetlogs打开数据库
SQL> alter database open resetlogs;

9)验证
SQL> select * from scott.r1;
        ID
----------
         1


相关文章

SQL Server优化入门系列(一)——快速定位阻塞SQL

SQL Server优化入门系列(一)——快速定位阻塞SQL

引言我们在运维数据库的时候,经常会面对这样的问题:数据库现在运行得怎么样有哪些会话在执行,当前状态是什么,在执行什么SQL哪些会话被阻塞,阻塞原因是什么会话是从哪些IP连接过来的,使用了什么账号通过这...

Hadoop3.2.4纠删码介绍(一)

Hadoop3.2.4纠删码介绍(一)

1、介绍纠删码是Hadoop3新加入的功能,之前的HDFS都是采用副本方式容错,默认情况下,一个文件有3个副本,可以容忍任意2个副本(DataNode)不可用,这样提高了数据的可用性,但也带来了2倍的...

minio存储桶命名规则

存储桶命名规则创建S3存储桶后,无法更改存储桶名称,因此请明智地选择名称。重要在2018年3月1日,我们更新了美国东部(弗吉尼亚北部)地区S3存储桶的命名约定,以匹配我们在所有其他全球AWS区域中使用...

Flink sql 集成hive metastore

Flink sql 集成hive metastore

1、前置条件**确认hive metastore版本(本次版本3.1.2) **hive metastore 部署成功hive依赖jar包分发到每个flink节点:/flink-1.13.6    ...

python脚本--检查域名证书到期时间

需要的依赖:pip install python-dateutil pip install pytzpython脚本内容:#!/usr/bin/env python3      import s...

Linux命令traceroute—追踪网络路由利器

说明:通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径。当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。