(一)问题背景
最近在生产环境中,开发人员误 *** 作,使用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 createdsqlselect count(*) from test01; COUNT(*)---------- @H_502_166@14
(ⅠⅠ)表test02,持续往里面写入数据
创建表test02create table test02( col1 number,col2 varchar2(@H_502_166@30),col4 date,col5 100) );创建随机数据插入存储过程create or replace procedure p_insert_test02 isBEGIN FOR i IN @H_502_166@1..@H_502_166@10000 LOOP insert into test02(col1,col2,col3,col4,col5) values ((round(dbms_random.value(@H_502_166@1,@H_502_166@100000000)) dual),(10000,1)">select dbms_random.string('a',1)">25) 85) dual)); commit; END LOOP;end p_insert_test02;制定job,没隔30s执行一次上面的存储过程declarejob1 ;beginsys.dbms_job.submit(job => job1,what => p_insert_test02;' sysdate,interval sysdate + 30/(1440*60)'); 每隔30s向test02表插入10000笔随机数据;/
(4.2)对数据库进行完全备份
rman target /RMAN> run {allocate channel c1 type disk;allocate channel c2 type ;sql alter system archive log currentbackup database format /databaseBackup/full_db_%Ubackup archivelog all format /databaseBackup/archlog_%Ucurrent controlfile format /databaseBackup/controlfile_%Ubackup 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 thread#,SEQUENCE#,name,ROW_NUMBER() OVER(PARTITION BY thread# ORDER BY SEQUENCE# DESC) rn V$ARCHIVED_LOG)WHERE rn=@H_502_166@1;结果为:
@L_301_1@
即thread1上的归档日志最大序列号为67,thread2上的归档日志最大序列号为48(这里因为个人电脑开较多虚拟机太卡,所以只开了节点1,节点2就没有日志生成,并不影响本次实验结果的准确性)。
(4.4)模拟test01表被truncate,记下时间
select sysdate dual;SYSDATE-----------------@H_502_166@2019-@H_502_166@0927 @H_502_166@19:@H_502_166@37:@H_502_166@31sql sqltruncate test01;table truncated.
(4.5)数据库正常运行,产生大量归档
上一次备份到了sequence=57的日志,上一次备份后又生成了25个日志,这里生成大量日志是为了模拟生产数据库这次交易的情况。
(4.6)开发人员发现表数据被truncate
开发人员发现程序报错,查看表test01,发现数据全没了,开发人员确认数据被自己删除(假设)。
(4.7)DBA执行异机恢复
思路整理:
本次恢复,需要将test01表恢复到truncate之前,我们需要有执行truncate *** 作之前的数据库全备和归档备份。第一次全备归档日志文件之备份到了thread1=57,thread2=48,在执行全被之后,又生成了许多的日志文件,我们要将数据库恢复到truncate之前(这里以我们记录的时间@H_502_166@ 为恢复点),那么我们还需要新的日志来做恢复,需要的日志如下:
thread1:日志57~67肯定需要,日志67~82不一定需要;
thread2:由于节点未开启,不需要日志来做恢复。
step1:将生产库的备份集传到测试库
[oracle@node1 databaseBackup]$ scp * 192.168.10.66:/databaseBackup/
step2:对恢复需要的归档日志进行再次备份,得到缺少的归档日志
run {allocate channel c1 type /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/adumpaudit_trail=dbcompatible=11.2.0.4.0control_files=+DATA/prodb/controlfile/current.260.1019830577db_block_size=8192db_create_file_dest=+DATAdb_domain=''db_name=prodbdiagnostic_dest=/u01/app/oracledispatchers=(PROTOCol=TCP) (SERVICE=prodbXDB)enable_ddl_logging=TRUElog_archive_dest_1=LOCATION=+archlog_archive_format=%t_%s_%r.dbfopen_cursors=300pga_aggregate_target=399507456processes=200remote_login_passwordfile=exclusivesessions=225sga_target=1199570944prodb.undo_tablespace=UNDOTBS1[oracle@test dbs]$ lshc_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 sysdbasql*Plus: Release 0.4.0 Production on Fri Sep 27 20:58:15 2019copyright (c) 1982,2013 startup nomount;ORACLE instance started.Total System Global Area 1202556928 bytesFixed Size 2252704 bytesVariable Size 402653280 bytesDatabase Buffers 788529152 bytesRedo Buffers 9121792 bytessql>
step5:将数据库添加到HA中,以便可以使用ASM存储
[oracle@test ~]$ srvctl add database -d prodb -o /u01/app/oracle/product/0/db_1
step6:恢复控制文件,修改pfile文件,重新启动数据库到mount状态
RMANrestore controlfile from "/databaseBackup/controlfile_0lucr7m2_1_1";
注意:此时存在一个问题,我们在构造pfile文件的时候,里面填写了控制文件的位置,这个位置是生产库上的位置,我们执行控制文件恢复后,需要对参数文件中的control_files参数进行修改,修改方法如下:
--首先,确认contril file在asm中的位置,
ASMCMD> pwd+data/prodb/controlfileASMCMD> ls -ltType Redund Striped Time Sys nameCONTRolfile UNPROT FINE SEP 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 /17:26 0 - 64bit ProductionWith the Partitioning,automatic Storage Management,olAP,Data Miningand Real Application Testing optionssql> shutdown immediateORA-01507: database not mountedORACLE instance shut down.sql> startup mountORACLE instance started.Total System Global Area bytesDatabase mounted.sql>
step7:注册新的归档日志备份集到备库的控制文件中
RMAN> catalog backuppIEce "/databaseBackup/archlog_20190927_0nucrcd2_1_1";RMAN> catalog backuppIEce /databaseBackup/archlog_20190927_0oucrcg5_1_1/databaseBackup/archlog_20190927_0pucrcjj_1_1";
step8:恢复数据库到truncate之前
RMAN>sqlALTER SESSION SET NLS_LANGUAGE=''AMERICAN'';RMAN>sqlALTER 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:确认数据是已经否恢复回来
先以只读方式打开数据库,如果有问题,还可以重新执行恢复sqlalter database open read onlyDatabase altered.确认数据是否找回来sql lijiaman.test01; -------- @H_502_166@14
step10:如果没问题,关闭数据库,以resetlogs方式打开
shutdown immediate; closed. dismounted.ORACLE instance shut down.sql startup mountORACLE instance started.Total System Global Area @H_502_166@ bytesFixed Size @H_502_166@ bytesVariable Size @H_502_166@ bytesDatabase Buffers @H_502_166@ bytesRedo Buffers @H_502_166@ mounted.sqlopen resetlogs;Database altered.恢复完成。
(4.8)将恢复的数据导入到生产环境
可以使用expdp/impdp或者是dblink将数据从测试库导入到生产库中。
【完】
总结以上是内存溢出为你收集整理的oracle异机恢复测试全部内容,希望文章能够帮你解决oracle异机恢复测试所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)