一、问题背景:
5月20日客户反应某个系统两张表少数据,这两个表位于一套Oracle 19c RAC容器数据库的一个PDB中,需要使用备份将这两个表恢复到5月17日早上8点。首先这套库有三个PDB,加起来大小10T左右,全库恢复太浪费时间;出问题的PDB大小5T,只恢复一个PDB效率也不理想。最理想的方案就是tablespace point-in-time recovery (TSPITR),但是客户为了不影响生产,只认可异机恢复,所以只能手动的来实现TSPITR。
二、环境介绍
生产环境 Oracle 19.11 RAC+DG ,两个表被误删除部分数据,需要进行恢复,恢复到5月17日上午9点。
目标环境 单节点19c的数据库软件环境
准备工作:
1、完整备份 + 连续归档(当前环境为5月14日的全备+5月17日的增量+归档备份) NBU备份。
2、复制生产端的参数文件为pfile,目标端启动到mount状态
3、连接NUB备份正常,正确的驱动程序
三、操作流程
1、数据库实例启动到nomount状态
startup nomount pfile='/home/oracle/testdb20230520.ora';
提示:单价环境需要手动指定归档地址,如果需要恢复的数据量较大可能需要很多的归档空间,提前规划磁盘空间。
2、恢复控制文件
run
{allocate channel ch00 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
restore controlfile to '/oradata/testdb/CONTROLFILE/controlfile01' from 'cntrl_362787_1_1137101912';
release channel ch00;
}
3 转储cdb
数据文件目录提前创建好
run{allocate channel ch00 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch01 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch02 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch03 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
set newname for database to '/oradata/testdb/CDB/%b';
restore database root;
switch datafile all;
release channel ch00;
release channel ch01;
release channel ch02;
release channel ch03;
}
5 转储pdb1指定表空间
run{allocate channel ch00 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch01 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch02 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch03 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch04 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch05 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch06 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch07 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
set newname for datafile 294 to '/oradata/testdb/pdb1/%b';
set newname for datafile 297 to '/oradata/testdb/pdb1/%b';
set newname for datafile 411 to '/oradata/testdb/pdb1/%b';
set newname for datafile 412 to '/oradata/testdb/pdb1/%b';
set newname for datafile 413 to '/oradata/testdb/pdb1/%b';
set newname for datafile 414 to '/oradata/testdb/pdb1/%b';
set newname for datafile 415 to '/oradata/testdb/pdb1/%b';
set newname for datafile 416 to '/oradata/testdb/pdb1/%b';
set newname for datafile 417 to '/oradata/testdb/pdb1/%b';
set newname for datafile 418 to '/oradata/testdb/pdb1/%b';
set newname for datafile 419 to '/oradata/testdb/pdb1/%b';
set newname for datafile 420 to '/oradata/testdb/pdb1/%b';
set newname for datafile 421 to '/oradata/testdb/pdb1/%b';
set newname for datafile 422 to '/oradata/testdb/pdb1/%b';
set newname for datafile 423 to '/oradata/testdb/pdb1/%b';
set newname for datafile 424 to '/oradata/testdb/pdb1/%b';
set newname for datafile 425 to '/oradata/testdb/pdb1/%b';
set newname for datafile 426 to '/oradata/testdb/pdb1/%b';
set newname for datafile 427 to '/oradata/testdb/pdb1/%b';
set newname for datafile 428 to '/oradata/testdb/pdb1/%b';
set newname for datafile 429 to '/oradata/testdb/pdb1/%b';
set newname for datafile 430 to '/oradata/testdb/pdb1/%b';
set newname for datafile 431 to '/oradata/testdb/pdb1/%b';
set newname for datafile 432 to '/oradata/testdb/pdb1/%b';
set newname for datafile 433 to '/oradata/testdb/pdb1/%b';
set newname for datafile 434 to '/oradata/testdb/pdb1/%b';
set newname for datafile 435 to '/oradata/testdb/pdb1/%b';
set newname for datafile 436 to '/oradata/testdb/pdb1/%b';
set newname for datafile 437 to '/oradata/testdb/pdb1/%b';
set newname for datafile 438 to '/oradata/testdb/pdb1/%b';
set newname for datafile 439 to '/oradata/testdb/pdb1/%b';
set newname for datafile 440 to '/oradata/testdb/pdb1/%b';
set newname for datafile 441 to '/oradata/testdb/pdb1/%b';
set newname for datafile 490 to '/oradata/testdb/pdb1/%b';
set newname for datafile 491 to '/oradata/testdb/pdb1/%b';
set newname for datafile 492 to '/oradata/testdb/pdb1/%b';
set newname for datafile 296 to '/oradata/testdb/pdb1/%b';
restore tablespace "pdb1":system,"pdb1":undotbs1,"pdb1":undo_2,"pdb1":pdb1_fm;
switch datafile all;
switch tempfile all;
release channel ch00;
release channel ch01;
release channel ch02;
release channel ch03;
release channel ch04;
release channel ch05;
release channel ch06;
release channel ch07;
}
提示1:这里需要恢复的两个表自包含于一个表空间pdb1_FM,所以只需要恢复这一个表空间,再加上SYSTEM表空间和UNDO表空间,就可以将PDB拉起来。
提示2:因为是异机恢复,数据文件路径改变,这里需要查询需要恢复的表空间的所有数据文件的file_ID,执行set newname。转储完需要switch,将数据文件信息注册到控制文件。
6、开始recover
run{allocate channel ch00 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch01 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch02 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
allocate channel ch03 type 'sbt_tape';
send 'NB_ORA_SERV=bak-svr,NB_ORA_CLIENT=node1';
set until time "to_date('2023/05/17 08:00:00','yyyy/mm/dd hh24:mi:ss')";
recover database skip forever tablespace "pdb1":SYSAUX,"pdb1":TEMP,"pdb2":ts1,"pdb2"ts2,"pdb3"ts1;
release channel ch00;
release channel ch01;
release channel ch02;
release channel ch03;}
提示:这里指定跳过recover没有转储的自身PDB下表空间和其他没有恢复的PDB下的表空间。可以执行下列查询来生成跳过的表空间,没有open的PDB不会查询到,需要单独添加。
set pagesize 400;
set line 400
select '"'||b.name||'"'||':'||a.name||','
from v$tablespace a,v$containers b
where a.con_id=b.con_id
and b.name not in('CDB$ROOT','pdb1');
and a.name not in('pdb1_FM','UNDOTBS1','SYSTEM');
7、重新指定redo位置
select 'alter database rename file '||chr(39)||member||chr(39)||' to '||chr(39)||member||chr(39)||';'
from v$logfile ;
将redo日志文件位置指定到本地。
alter database rename file '+DATA/testdb/ONLINELOG/group_1.258.1076782375' to '/oradata/testdb/ONLINELOG/group_1.258.1076782375';
。。。
8、拉起CDB和PDB
alter database open resetlogs;
alter pluggable database pdb1 open;
9、确定要恢复的数据正常后可以将数据导回生产环境
两种方法:数据泵和DBLINK。
但是本次没有做全库的恢复,只做了指定表空间恢复,没有恢复SYSAUX而且也没有新建TEMP表空间,使用数据泵导出会报错,所以使用DBLINK。
创建PDB的监听和连接字符串
1)新建监听
LISTENER2=
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.88)(PORT = 1522))
)
)
SID_LIST_LISTENER2 =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME=testdb)
(SID_NAME=testdb)
(ORACLE_HOME='/u01/app/oracle/product/19.0.0/db_1')
)
)
执行:
lsnrctl start listener2
2)新建连接字符串
pdb1 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.88)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME =pdb1)
)
)
LISTENER_testdb=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.88)(PORT = 1522))
)
如果PDB监听无法注册 :
alter system set local_listener='LISTENER_testdb'
手动注册:
alter system register
3)生产端创建DBLINK
alter session set container=pdb1;
create public database link pdb1_rec connect to dump_user identified by "8Qllyhy!" using '192.168.18.88:1522/pdb1';
4)恢复数据
可以通过DBLINK将数据复制到新表里面,也可以将丢失的数据插入到原表。
5)删掉DBLINK
恢复完成后删除DBLINK
drop database link pdb1_rec;