很多时候人为误操作会对Oracle的数据造成影响,比如误删数据。当误操作发生时,通常有四个解决方法:
1.闪回数据库或闪回表
2.备份恢复
3.logminer挖掘redo
4.使用延时库
前三种方法都不是很完美:
闪回数据库影响较大,且事先需要开启库上的闪回。
闪回表或闪回版本查询使用方便,但在繁忙的数据库中很容易快照过旧。
备份恢复耗时长、影响大
logminer挖掘日志耗时耗力
此时如果事先有搭建延时备库的话,则可以很容易的从备库得到误删的数据。以下进行演示。
主库:
SQL> show parameter instance_name
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
instance_name string BDDEV2
备库:
SQL> show parameter instance_name
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
instance_name string BDTEST
现有表及数据如下:
SQL> select * from scott.tb_test;
ID AGE TM
---------- ---------- -----------------
1 2 20181203 14:22:14
2 3 20181203 14:22:14
3 4 20181203 14:22:14
4 5 20181203 14:22:14
5 6 20181203 14:22:14
6 7 20181203 14:22:14
7 8 20181203 14:22:14
8 9 20181203 14:22:14
9 10 20181203 14:22:14
10 11 20181203 14:22:14
10 rows selected.
此时备库是实时应用的:
SQL> SELECT * FROM V$DATAGUARD_STATS;
NAME VALUE UNIT TIME_COMPUTED DATUM_TIME
------------------------------ ------------------------------ ---------------------------------------- ------------------------------ ------------------------------
transport lag +00 00:00:00 day(2) to second(0) interval 12/03/2018 14:23:33 12/03/2018 14:23:33
apply lag +00 00:00:00 day(2) to second(0) interval 12/03/2018 14:23:33 12/03/2018 14:23:33
apply finish time +00 00:00:00.000 day(2) to second(3) interval 12/03/2018 14:23:33
estimated startup time 7 second 12/03/2018 14:23:33
备库转为延时库,延时60分钟:
SQL> alter database recover managed standby database cancel;
Database altered.
SQL> alter database recover managed standby database disconnect from session delay 60;
Database altered.
主库修改记录:
SQL> update scott.tb_test set age = 100,tm = sysdate where id = 10;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from scott.tb_test;
ID AGE TM
---------- ---------- -----------------
1 2 20181203 14:22:14
2 3 20181203 14:22:14
3 4 20181203 14:22:14
4 5 20181203 14:22:14
5 6 20181203 14:22:14
6 7 20181203 14:22:14
7 8 20181203 14:22:14
8 9 20181203 14:22:14
9 10 20181203 14:22:14
10 100 20181203 14:26:50
10 rows selected.
可看到,修改数据的时间为' 20181203 14:26:50 '。
此时删除表数据:
SQL> select sysdate from dual;
SYSDATE
-----------------
20181203 14:28:18
SQL> truncate table scott.tb_test;
Table truncated.
SQL> alter system switch logfile;
System altered.
此时主库中数据已经删除,备库中数据还停留在主库修改数据之前:
SQL> select * from scott.tb_test;
ID AGE TM
---------- ---------- -----------------
1 2 20181203 14:22:14
2 3 20181203 14:22:14
3 4 20181203 14:22:14
4 5 20181203 14:22:14
5 6 20181203 14:22:14
6 7 20181203 14:22:14
7 8 20181203 14:22:14
8 9 20181203 14:22:14
9 10 20181203 14:22:14
10 11 20181203 14:22:14
如果我们要恢复数据到update之后、truncate之前,则要手动前滚备库到指定时间点:
--备库操作
重启备库到mount:
SQL> startup force mount;
ORACLE instance started.
Total System Global Area 2.1379E+10 bytes
Fixed Size 2262656 bytes
Variable Size 2.0401E+10 bytes
Database Buffers 939524096 bytes
Redo Buffers 36073472 bytes
Database mounted.
手动前滚备库到指定时间点:
SQL> recover standby database until time '20181203 14:27:00';
ORA-00279: change 108456269 generated at 12/03/2018 14:26:50 needed for thread 1
ORA-00289: suggestion : /opt/app/oracle/archivelog_bdtest/1_248_987097214.dbf
ORA-00280: change 108456269 for thread 1 is in sequence #248
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
auto
Log applied.
Media recovery complete.
前滚完成,打开备库:
SQL> alter database open;
Database altered.
SQL> alter session set nls_date_format='yyyymmdd hh34:mi:ss';
Session altered.
SQL> select * from scott.tb_test;
ID AGE TM
---------- ---------- -----------------
1 2 20181203 14:22:14
2 3 20181203 14:22:14
3 4 20181203 14:22:14
4 5 20181203 14:22:14
5 6 20181203 14:22:14
6 7 20181203 14:22:14
7 8 20181203 14:22:14
8 9 20181203 14:22:14
9 10 20181203 14:22:14
10 100 20181203 14:26:50
10 rows selected.
此时就得到了所需数据,只需把数据重新导入到主库中即可。
待处理完成后,重新打开备库的redo应用:
SQL> alter database recover managed standby database disconnect from session delay 60;
Database altered.
此时备库又变为了正常的延时库。
注意:
1.备库DELAY时间指的是当主库日志归档后,再延时DELAY指定的时间应用日志,比如:设置DELAY参数为20分钟,10:00主库日志归档,则10:20备库才会应用此归档日志
2.也可以在LOG_ARCHIVE_DEST_2指定DELAY参数达到同样的延时目的:
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=DEVSTBY LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=DEVSTBY DELAY=60'
3.备库不能进行实时应用,因为实时应用会使DELAY参数失效,备库变为ADG