(一)问题背景

最近在生产环境中,开发人员误操作,使用truncate将oracle数据库某个表的数据全部删除了,在删除之后,开发人员发现自己闯祸了,于是联系值班的DBA进行紧急数据恢复。

经过分析,表被truncate后,使用一般的闪回表、闪回查询、闪回事物等方法,是不可能将数据找回来的,可以使用闪回数据库、闪回数据归档的方法来进行恢复,但是通常在生产环境中,都不会开启这2个特性,所以剩下的只有使用RMAN进行数据恢复了。

对于使用RMAN进行数据恢复,可以在生产环境上直接进行,也可以恢复到其它机器上。

  • 直接在生产环境上恢复:①需要停止生产数据库;②数据库需要保持一致性,比如说,我需要将数据库恢复到12:00,那么数据库中其他表的数据也将恢复到12点,有可能会丢失较多数据;③如果恢复过程中出现其它问题也比较麻烦,耽误了生产业务执行。
  • 恢复到其它机器上:②不需要停生产库;②仅仅丢失truncate表的数据,比如说,我需要将数据库恢复到12:00,那么我只需将整个库在测试环境上恢复到12点,再将我们丢失表的数据通过DB_LINK或数据泵等方式恢复到生产环境,生产环境其它表的数据是不受影响的;③恢复失败,并不会影响到生产库。

所以,经过一番考虑,决定将数据库恢复到其它机器上,然后再将truncate表的数据导回到生产环境。

此次恢复操作是同事做的,在恢复过程中,由于流程不熟悉,查资料耽误了一些时间(大约20分钟),虽然数据库恢复完成了,但没有达到快速恢复的要求。思考了一下,假如自己来做,能否在开发人员焦急等待的情况下,自己毫不慌乱、快速稳定的完成数据库恢复?确实是不可能的。一方面恢复流程不熟练,毕竟数据库恢复操作一年也不可能遇到几次,另一方面在用户及开发人员催促的情况下,DBA也很容易慌张,影响效率。因此最好的方式是:提前演练、写好操作流程。当故障发生时,照着文档操作,以最快的速度恢复生产。

(二)环境准备

  生产环境 异机环境
操作系统 RedHat6.7 RedHat6.7
数据库版本 11.2.0.4(RAC,2个节点) 11.2.0.4(单节点)
db_name prodb prodb
instance_name prodb1、prodb2 prodb
数据库安装情况 安装GI+数据库软件+创建数据库 安装GI+数据库软件 (不用创建数据库)
磁盘组信息 OCR   : 3*1GB,normal
DATA :3*5GB,external
ARCH :  1*5GB,external
OCR   : 3*1GB,normal
DATA :3*5GB,external
ARCH :  1*5GB,external

备注:为了方便,在后续环境中,生产环境数据库简称“生产库”,异机环境的数据库简称“测试库”。

(三)测试方案

(四)详细执行过程

(4.1)创建测试表

这里创建了2个测试表,作用分别如下:

lijiaman.test01:用于做truncate测试的表,最后在测试库需要进行test01表的恢复。

lijiaman.test02:用于模拟数据库事务,对该表不断执行插入操作,使得数据库产生大量归档日志。

(Ⅰ)表test01,一共有14笔数据。

SQL> CREATE TABLE test01 AS SELECT * FROM scott.emp;
Table created SQL> select count(*) from test01;
COUNT(*)
----------
14

(ⅠⅠ)表test02,持续往里面写入数据

--创建表test02
create table test02
(
col1 number,
col2 number,
col3 varchar2(30),
col4 date,
col5 varchar2(100)
); --创建随机数据插入存储过程
create or replace procedure p_insert_test02 is
BEGIN
FOR i IN 1..10000 LOOP
insert into test02(col1,col2,col3,col4,col5)
values
((select round(dbms_random.value(1, 100000000)) from dual),
(select round(dbms_random.value(10000, 100000000)) from dual),
(select dbms_random.string('a', 25) from dual),
sysdate,
(select dbms_random.string('a', 85) from dual));
commit;
END LOOP;
end p_insert_test02; --制定job,没隔30s执行一次上面的存储过程
declare
job1 number;
begin
sys.dbms_job.submit(job => job1,
what => 'p_insert_test02;',
next_date => sysdate,
interval => 'sysdate + 30/(1440*60)'); --每隔30s向test02表插入10000笔随机数据
commit;
end;
/

(4.2)对数据库进行完全备份

rman target /

RMAN> run {
allocate channel c1 type disk;
allocate channel c2 type disk;
sql' alter system archive log current';
backup database format '/databaseBackup/full_db_%U';
sql' alter system archive log current';
backup archivelog all format '/databaseBackup/archlog_%U';
backup current controlfile format '/databaseBackup/controlfile_%U';
backup spfile format '/databaseBackup/spfile_%U';
release channel c1;
release channel c2;
}

生成的备份集如下:

[oracle@node1 databaseBackup]$ ls -l
total 4136752
-rw-r----- 1 oracle asmadmin 1451128832  Sep 27 19:27 archlog_0iucr7hg_1_1
-rw-r----- 1 oracle asmadmin 1462116352  Sep 27 19:27 archlog_0jucr7hh_1_1
-rw-r----- 1 oracle asmadmin     1406464   Sep 27 19:27 archlog_0kucr7lr_1_1
-rw-r----- 1 oracle asmadmin   18841600   Sep 27 19:28 controlfile_0lucr7m2_1_1
-rw-r----- 1 oracle asmadmin  805953536   Sep 27 19:25 full_db_0eucr7f7_1_1
-rw-r----- 1 oracle asmadmin  477528064   Sep 27 19:25 full_db_0fucr7f7_1_1
-rw-r----- 1 oracle asmadmin   18841600   Sep 27 19:25 full_db_0gucr7h3_1_1
-rw-r----- 1 oracle asmadmin        98304   Sep 27 19:25 full_db_0hucr7ha_1_1
-rw-r----- 1 oracle asmadmin        98304   Sep 27 19:28 spfile_0mucr7m5_1_1

确认归档日志备份情况,可以看到,本次全备份归档日志备份到了thread1:57,thread2:48。

RMAN> list archivelog all;

List of Archived Log Copies for database with db_unique_name PRODB
=====================================================================

Key     Thrd  Seq     S  Low Time
------- ---- ------- - ---------
3            1    6       A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_1_seq_6.258.1019832847
......
100        1     57      A 27-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_27/thread_1_seq_57.355.1020108489

1           2     1       A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_2_seq_1.256.1019830885
......
80         2     48      A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_2_seq_48.335.1019838555

(4.3)数据库正常运行,产生大量归档

由于日志序列号是递增的(以resetlogs打开数据库例外),因此查询每个实例上生成的最大日志即可

SELECT *
FROM
(SELECT thread#,
SEQUENCE#,
NAME,
ROW_NUMBER() OVER(PARTITION BY thread# ORDER BY SEQUENCE# DESC) rn
FROM V$ARCHIVED_LOG)
WHERE rn=1;

结果为:

即thread1上的归档日志最大序列号为67,thread2上的归档日志最大序列号为48(这里因为个人电脑开较多虚拟机太卡,所以只开了节点1,节点2就没有日志生成,并不影响本次实验结果的准确性)。

(4.4)模拟test01表被truncate,记下时间

SQL> select sysdate from dual;

SYSDATE
-------------------
2019-09-27 19:37:31 SQL>
SQL> truncate table test01; Table truncated.

(4.5)数据库正常运行,产生大量归档

上一次备份到了sequence=57的日志,上一次备份后又生成了25个日志,这里生成大量日志是为了模拟生产数据库这次交易的情况。

(4.6)开发人员发现表数据被truncate

开发人员发现程序报错,查看表test01,发现数据全没了,开发人员确认数据被自己删除(假设)。

(4.7)DBA执行异机恢复

思路整理:

本次恢复,需要将test01表恢复到truncate之前,我们需要有执行truncate操作之前的数据库全备和归档备份。第一次全备归档日志文件之备份到了thread1=57,thread2=48,在执行全被之后,又生成了许多的日志文件,我们要将数据库恢复到truncate之前(这里以我们记录的时间2019-09-27 19:37:31 为恢复点),那么我们还需要新的日志来做恢复,需要的日志如下:

thread1:日志57~67肯定需要,日志67~82不一定需要;

thread2:由于节点未开启,不需要日志来做恢复。

step1:将生产库的备份集传到测试库

[oracle@node1 databaseBackup]$ scp * 192.168.10.66:/databaseBackup/

step2:对恢复需要的归档日志进行再次备份,得到缺少的归档日志

run {
allocate channel c1 type disk;
sql' alter system archive log current';
backup archivelog all format '/databaseBackup/archlog_20190927_%U';
release channel c1;
}

得到的归档日志备份集如下:

-rw-r----- 1 oracle asmadmin 1621476864 Sep 27 20:50 archlog_20190927_0nucrcd2_1_1
-rw-r----- 1 oracle asmadmin 1643560960 Sep 27 20:51 archlog_20190927_0oucrcg5_1_1
-rw-r----- 1 oracle asmadmin 1581030912 Sep 27 20:53 archlog_20190927_0pucrcjj_1_1

传送到备库上
[oracle@node1 databaseBackup]$ scp archlog_20190927_0* 192.168.10.66:/databaseBackup/
step3:根据生产库的pfile,构造一个测试库的pfile

[oracle@test dbs]$ pwd
/u01/app/oracle/product/11.2.0/db_1/dbs [oracle@test dbs]$ vim init initprodb.ora
# 添加如下信息
audit_file_dest='/u01/app/oracle/admin/prodb/adump'
audit_trail='db'
compatible='11.2.0.4.0'
control_files='+DATA/prodb/controlfile/current.260.1019830577'
db_block_size=8192
db_create_file_dest='+DATA'
db_domain=''
db_name='prodb'
diagnostic_dest='/u01/app/oracle'
dispatchers='(PROTOCOL=TCP) (SERVICE=prodbXDB)'
enable_ddl_logging=TRUE
log_archive_dest_1='LOCATION=+arch'
log_archive_format='%t_%s_%r.dbf'
open_cursors=300
pga_aggregate_target=399507456
processes=200
remote_login_passwordfile='exclusive'
sessions=225
sga_target=1199570944
prodb.undo_tablespace='UNDOTBS1' [oracle@test dbs]$ ls
hc_prodb.dat hc_testdb1.dat hc_testdb.dat init.ora initprodb.ora lkTESTDB

创建pfile里面涉及到的路径:

[oracle@test ~]$ mkdir -p /u01/app/oracle/admin/prodb/adump

step4:将备库启动到nomount状态

[oracle@test ~]$ export ORACLE_SID=prodb
[oracle@test ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.4.0 Production on Fri Sep 27 20:58:15 2019 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to an idle instance. SQL> startup nomount;
ORACLE instance started. Total System Global Area 1202556928 bytes
Fixed Size 2252704 bytes
Variable Size 402653280 bytes
Database Buffers 788529152 bytes
Redo Buffers 9121792 bytes
SQL>

step5:将数据库添加到HA中,以便可以使用ASM存储

[oracle@test ~]$ srvctl add database -d prodb -o /u01/app/oracle/product/11.2.0/db_1

step6:恢复控制文件,修改pfile文件,重新启动数据库到mount状态

RMAN> restore controlfile from "/databaseBackup/controlfile_0lucr7m2_1_1";

注意:此时存在一个问题,我们在构造pfile文件的时候,里面填写了控制文件的位置,这个位置是生产库上的位置,我们执行控制文件恢复后,需要对参数文件中的control_files参数进行修改,修改方法如下:

--首先,确认contril file在asm中的位置,

ASMCMD> pwd
+data/prodb/controlfile
ASMCMD> ls -lt
Type Redund Striped Time Sys Name
CONTROLFILE UNPROT FINE SEP 27 21:00:00 Y current.256.1020114329

--接下来,修改pfile文件的control_files参数

[oracle@test ~]$ cd $ORACLE_HOME/dbs
[oracle@test dbs]$ vim initprodb.ora
# 改control_files位置
control_files='+data/prodb/controlfile/current.256.1020114329'

--重启数据库到mount状态

[oracle@test ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri Sep 27 21:17:26 2019

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

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options SQL> shutdown immediate
ORA-01507: database not mounted ORACLE instance shut down.
SQL> startup mount
ORACLE instance started. Total System Global Area 1202556928 bytes
Fixed Size 2252704 bytes
Variable Size 402653280 bytes
Database Buffers 788529152 bytes
Redo Buffers 9121792 bytes
Database mounted.
SQL>

step7:注册新的归档日志备份集到备库的控制文件中

RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0nucrcd2_1_1";
RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0oucrcg5_1_1";
RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0pucrcjj_1_1";

step8:恢复数据库到truncate之前

RMAN>SQL"ALTER SESSION SET NLS_LANGUAGE=''AMERICAN''";
RMAN>SQL"ALTER SESSION SET NLS_DATE_FORMAT=''YYYY-MM-DD HH24:MI:SS''";
RUN{
SET UNTIL TIME '2019-09-27 19:37:31';
RESTORE DATABASE;
RECOVER DATABASE;
}

step9:确认数据是已经否恢复回来

--先以只读方式打开数据库,如果有问题,还可以重新执行恢复
SQL> alter database open read only;
Database altered. --确认数据是否找回来
SQL> select count(*) from lijiaman.test01;
COUNT(*)
----------
14

step10:如果没问题,关闭数据库,以resetlogs方式打开

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down. SQL> startup mount
ORACLE instance started. Total System Global Area 1202556928 bytes
Fixed Size 2252704 bytes
Variable Size 402653280 bytes
Database Buffers 788529152 bytes
Redo Buffers 9121792 bytes
Database mounted. SQL> alter database open resetlogs; Database altered.

恢复完成。

(4.8)将恢复的数据导入到生产环境

可以使用expdp/impdp或者是dblink将数据从测试库导入到生产库中。

【完】

oracle异机恢复测试的更多相关文章

  1. rman恢复方案和oracle异机恢复

    这篇文章主要介绍了rman恢复方案和oracle异机恢复,需要的朋友可以参考下 注:①恢复的前提是已经做好备份②完全恢复数据库是数据库遇到故障,在恢复时候没有丢失任何已经提交事物数据的恢复不完全恢复数 ...

  2. ORACLE 异机恢复

    有时候需要将大的数据库发布到客户现场或转移机器时,不得不考虑在异机上恢复已经调整.测试好的库. dumpdp 全备的方法虽然易用,但在处理对象.索引.空间的时候异常的出错,比如:见有些公司,建表.索引 ...

  3. 使用NBU进行oracle异机恢复

    windows平台的异机恢复,目录不同 1.异机环境准备安装oracle介质安装nbu客户端在异机主机的host文件中添加nbu server主机和原主机信息 2.恢复spfile文件 C:\> ...

  4. Oracle异机恢复

    RMAN异机恢复注意事项:1.RMAN 异机恢复的时候,db_name必须相同. 如果说要想改成其他的实例名,可以在恢复成功后,用nid 命令修改. 实例名的信息会记录到控制文件里,所以如果在恢复的时 ...

  5. Oracle之使用rman进行异机恢复测试记录

    本次测试目的是从生产数据库导出rman备份然后在测试数据库恢复 1,拷贝备份至相应目录 2,进入rman rman target \ 3,关闭数据库 shutdown 4,以nomount模式启动数据 ...

  6. oracle异机恢复参考官方文档

    How to use Rman Duplicate on ASM/RAC/OMF/Single Instance (Doc ID 840647.1) How to perform Rman dupli ...

  7. oracle异机恢复 open resetlogs 报:ORA-00392

    参考文档:ALTER DATABASE OPEN RESETLOGS fails with ORA-00392 (Doc ID 1352133.1) 打开一个克隆数据库报以下错误: SQL> a ...

  8. Hyper-V安装Oracle Linux6_4 Oracle db 12c并使用rman做异机恢复

    本文记录在Windows Server 2012 R2上安装Oracle Enterprise Linux 6.4以及使用RMAN进行进行异机恢复的过程. Windows服务器增加Hyper-V功能 ...

  9. Oracle 单实例 迁移到 RAC 实例 -- 使用RMAN 异机恢复

    Oracle 官网有关单实例迁移到RAC的一个步骤说明: How to Convert 10g Single-Instance database to 10g RAC using Manual Con ...

随机推荐

  1. NuGet的安装和使用

    好久没有用NuGet了.今天项目中正好有需要.因长时间不用,所以还要去网上看攻略,索性记录下来免得再出现类似情况.(我是一个比较懒得人,不喜欢写博客园,平时都随手整理到本地PC上.以后要努力改掉这个坏 ...

  2. python相关性算法解决方案(rest/数据库/json/下载)

    1. 场景描述 一直做java,因项目原因,需要封装一些经典的算法到平台上去,就一边学习python,一边网上寻找经典算法代码,今天介绍下经典的相关性算法,算法原理就不介绍了,只从代码层面进行介绍,包 ...

  3. 设计模式(C#)——09外观模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321 前言       在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然 ...

  4. HDU 4685

    题意略. 思路: 本题和POJ1904颇为相似,只是那个最大匹配没有现成的,要我们自己求出来.并且要给每一个单身的王子/公主现找一个虚拟的对象. 这也是合乎情理的,王子每一次换一个公主时,可能会导致某 ...

  5. P1613 跑路 倍增思想 + 邻接矩阵

    题意 给定一个有向图,每条边的花费为1.现在有一个空间跑路器,可以走2^k长度的路,只用花1秒的时间.问从1走到n最少的时间.n <= 50, k <= 64. 思路 这道题说是倍增,但是 ...

  6. gym/102021/K GCPC18 背包dp算不同数和的可能

    gym/102021/K 题意: 给定n(n<=60)个直线 ,长度<=1000; 可以转化为取 计算 ans = (sum  + 10 - g) / ( n + 1)  在小于5的条件下 ...

  7. 洛谷P1240-诸侯安置+递推非搜索

    诸侯安置 这道题是一题递推题,一开始自己不知道,用了搜索,只过了三个样例: 两两相同的合并, 成 1,1,3,3,5,5........n*2-1; 然后我们会容易发现一种不同与搜索的动态规划做法. ...

  8. 并发、线程的基本概念&线程启动结束

    并发.进程.可执行程序.进程.线程的基本概念 1.并发 并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段 ...

  9. POJ2084 Game of Connections 卡特兰数 关于卡特兰数经典的几个问题

    Game of Connections Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9128   Accepted: 44 ...

  10. Java连载27-有返回值的方法注意点

    一.方法注意点 (1)方法的调用不一定再main方法中,可以在其他方法中进行调用,只要是程序执行到的位置,都可以去调用其他方法. (2)方法调用的时候,实参和形参要求个数对应相同,数据类型对应相同,方 ...