对于Oracle的闪回,很多朋友也问过问,到底是怎么玩的?如果自己做过一些闪回数据库的操作,就会发现这个功能非常强悍。
Flashback DML的操作其实还蛮容易理解的,但是Flashback DDDL那可就是另外一个level了,我们大概了解一下MySQL里面的闪回就会发现,真要实现无缝的全闪回,确实有很多的细节和场景需要考虑。而Oracle作为一个成熟的商业软件,是不希望我们了解很多底层的细节的,用着好就行,所以如果你想得到一些闪回更细节的东西,这个渠道就非常的窄,我们之前也测试了两期,做了一些简单的对比,这一期就做一些基本的突破,对闪回原理做出进一步的解读。
这个尝试来源于今天的一个维护更新,今天早间的时候,会按照季度的业务要求DBA做一个统一的批量查询,得到一些数据供审计和策划的同学分析,提前给出一些解决方案,这个事情是大概一周前提的了,而悲剧的是今天到了公司才想起了有这么一回事。而这个时候数据已经被当日的数据更新了,想要得到早间指定时间段的数据就尤为关键,当然我还算是胸有成竹,因为这个备库我开了闪回。所以我可以很快闪回到指定的近期任意时间点,也算是闪回化解了这样一次尴尬的境地。
当然我在处理问题的时候,还不忘看看闪回的原理,记录日志,其实主要是我对闪回特性的充分自信,要不手心里早都冒汗了。
首先确认数据库角色和状态之后,我关闭数据库,准备从mount状态闪回,避免重启数据库。
下面的错误值得注意,在close这个操作时,还是需要保证数据库的日志应用是终止的,即MRP为停止状态。
SQL> alter database close;
alter database close
*
ERROR at line 1:
ORA-10457: cannot close standby database due to active media recovery我们选择快捷的命令方式,直接关闭日志应用,然后关闭数据库。
SQL> recover managed standby database cancel;
Media recovery complete.
SQL> alter database close;
Database altered.这个操作完成之后,扫了一眼redo和控制文件,已经更新了时间,闪回工作迫在眉睫。我把数据库闪回到了几个小时之前的一个时间点。
SQL> flashback database to timestamp to_timestamp('2017-03-27 07:20:00','yyyy-mm-dd hh24:mi:ss');
Flashback complete.这个过程持续时间很短,所有数据文件的时间戳都更新到了当前的时间点,而其实数据已经闪回到了几个小时之前。
当然下面的一段日志吸引了我。
Mon Mar 27 10:19:24 2017
flashback database to timestamp to_timestamp('2017-03-27 07:20:00','yyyy-mm-dd hh24:mi:ss')
Flashback Restore Start
Flashback Restore Complete
Flashback Media Recovery Start
started logmerger process
Parallel Media Recovery started with 24 slaves
Flashback Media Recovery Log /U01/app/oracle/fast_recovery_area/SGCDB2/archivelog/2017_03_27/o1_mf_1_10600_dfjjm98t_.arc
Flashback Media Recovery Log /U01/app/oracle/fast_recovery_area/SGCDB2/archivelog/2017_03_27/o1_mf_1_10601_dfjonfly_.arc
Mon Mar 27 10:19:43 2017
Incomplete Recovery applied until change 234220253426 time 03/27/2017 07:20:01
Mon Mar 27 10:19:43 2017
Flashback Media Recovery Complete
Completed: flashback database to timestamp to_timestamp('2017-03-27 07:20:00','yyyy-mm-dd hh24:mi:ss')上面的几处红字需要格外注意,里面出现了归档日志文件,这个就需要再提一下。我们可以通过日志看出,整个闪回的工作其实分为两大部分,restore和recover,这个和正常恢复数据如出一辙。但是差别也很明显,因为闪回日志是记录的数据变化的逆操作,所以从10:30闪回到7:20,那么这个过程就是10:30-> 7:20左右。
注意我提到的这个7:20是左右,当然要偏左一些,偏右证明数据还太新了。Restore的这个过程会应用到闪回日志。其实在Oracle中存在一个概念叫做Flashback barrier interval,默认是是30分钟会往闪回日志里写入SCN的标示纪录。所以10:30->7:20的操作你也可以理解为大体是按照10:30->10:00->9:30->9:00->8:30->8:00->7:30->7:00这样的过程。
完成了基本的还原之后,我们要到达指定时间点的状态,这就需要使用归档文件或者重做日志了,这里的重点就是Flashback Recover的过程了。我们可以通过上面的日志看到,其实应用了两个日志文件,序列号为10600和10601,这个过程该如何更好的验证呢。可以通过如下的SQL来做一个基本的分析,当然这个语句还不够严谨。主要思路就是根据v$archived_log来确定一个边界范围。
set linesize 150 pagesize 100
with maxlogchg as
(select max(first_change#) c1 from v$archived_log where first_change#<=234220253426)
select name,sequence#,first_change#,next_change# from v$archived_log,maxlogchg where first_change#>=maxlogchg.c1 and first_change#<=234220253426; 整个数据闪回之后,我们就穿越到了之前的一个时间点,可以做我们需要的操作了。
整个查询的过程持续时间很短,但是得到的这个数据就尤为重要了。根据业务运行一些查询脚本,此处省略查询的SQL语句。
完成之后,我们只需要alter database close,然后正常open就会更新到最新的一个时间点的数据状态。
SQL>alter database close;
SQL>alter database open
SQL> recover managed standby database disconnect from session;
Media recovery complete.
这个过程的日志其实省略了一些东西,我想也是为了避免给用户带来困扰,因为在日志里反反复复recover,可能会让用户有些疑惑,而我们也可以通过另外一个隐含参数(_flashback_verbose_info)来得到更加详细的日志信息。
默认得到的正常日志如下:
Mon Mar 27 10:40:06 2017
ALTER DATABASE RECOVER managed standby database disconnect from session
Attempt to start background Managed Standby Recovery process (gcdb)
Mon Mar 27 10:40:06 2017
MRP0 started with pid=28, OS id=139822
MRP0: Background Managed Standby Recovery process started (gcdb)
started logmerger process
Mon Mar 27 10:40:11 2017
Managed Standby Recovery not using Real Time Apply
Parallel Media Recovery started with 24 slaves
Waiting for all non-current ORLs to be archived...
All non-current ORLs have been archived.
Media Recovery Delayed for 180 minute(s) (thread 1 sequence 10601)
Completed: ALTER DATABASE RECOVER managed standby database disconnect from session 通过如上的日志,你看不到很多潜在的recover操作。而整个过程而言却又是必须的。
通过这个过程我们可以大体看出,整个闪回的过程不是孤立,完全依赖于闪回日志,而同时也是一个Flashback Restore和Flashback Recover的过程。