对于闪回部分,Oracle本身提供了非常多相关的特性,我个人对于闪回数据库这个特性最为喜爱,尤其是应用再Data Guard环境中,真是一大杀器。
而对于DML的闪回部分其实也相对比较容易理解,毕竟就是原操作的逆操作,之前通过logminer的方式来读取redo来间接得以印证。Oracle闪回原理-Logminer解读redo(r11笔记第17天)
但是对于DDL的闪回,这个特性真是非常强悍了。比如一个truncate操作,它的逆操作改怎么定义,就很难去界定了。当然这个里面肯定有一些很有意思的实现方式值得好好玩味。
我简单测试了truncate和delete的操作,虽然步骤简单,但是是带着特定的眼光来审视这个过程。
我们来创建一些数据,先创建200万的数据压压惊。
SQL> create table test_fb as select level object_id,'obj_'||level object_name from dual connect by level <=2000000;
Table created.
然后持续插入一些数据,目的是保证这个表的数据量足够大。
SQL> insert into test_fb select *from test_fb;
2000000 rows created.
SQL> /
4000000 rows created.
SQL> /
8000000 rows created.
SQL> select count(*)from test_fb;
COUNT(*)
----------
16000000
SQL> commit;
Commit complete.数据准备工作就这些,简单看看对应的段,会发现段的大小在近400M的样子。
SQL> select segment_name,bytes/1024/1024 size_MB from user_segments where segment_name='TEST_FB';
SEGMENT_NAME SIZE_MB
------------------------------ ----------
TEST_FB 384虽然看起来不是特别大的段,不过已经能够说明问题了。我们开启闪回数据库的功能。
alter database flashback on;这个时候查看闪回区,会发现突然多出了两个闪回日志。
[oracle@newtest flashback]$ ll
total 102420
-rw-r--r-- 1 oracle oinstall 171 Aug 21 20:37 a.sql
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:34 o1_mf_d5x1vjlb_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:34 o1_mf_d5x1vjvc_.flb可以理解这是一个初始化的过程。因为从alert日志可以看到启动了RVWR进程,SGA里面其实也分配了闪回区的缓存.
Sat Dec 24 22:34:24 2016
alter database flashback on
Starting background process RVWR
Sat Dec 24 22:34:24 2016
RVWR started with pid=37, OS id=21314
Flashback Database Enabled at SCN 192530049424
Completed: alter database flashback on这个时候数据库标示,闪回数据库是基于某一个SCN的。
下面我们来做一个truncate操作,为了让闪回的过程看起来自然一些,我们就创建一个还原点,毕竟基于SCN,基于时间戳还是有些取巧的感觉。
create restore point fb_recover_trunc guarantee flashback database;
对于还原点更多的信息可以联系v$restore_point来查看,其实从数据字典里查看,这部分信息也会清晰不少。
col NAME for a20
col TIME for a35
set lines 200
col STORAGE_SIZE for a50
SELECT NAME, SCN, TIME, DATABASE_INCARNATION# DI,GUARANTEE_FLASHBACK_DATABASE, STORAGE_SIZE/1024/1024/1024
FROM V$RESTORE_POINT
WHERE GUARANTEE_FLASHBACK_DATABASE='YES';
NAME SCN TIME DI GUARAN STORAGE_SIZE/1024/1024/1024
---------------- ----------------------------- ----------------------------------- ---------- ------ ---------------------------
FB_RECOVER_TRUNC 192530049487 24-DEC-16 10.35.16.000000000 PM 10 YES .048828125
这个过程,闪回日志没有大小的任何变化,但是闪回日志的时间戳会发生变化,证明是在持续更新。
我们来操作truncate,这个操作绝对是很多数据库灾难的源头。
truncate table test_fb;
但是操作完成之后查看闪回日志,竟然还是没有任何大小的变化。
可见truncate的操作,在闪回日志中不会记录逆操作的信息,这个应该是在其它的地方来做的。
我们来开启闪回数据库,尝试闪回到指定的还原点
shutdown immediate;
startup mount
从启动日志可以清晰的看到,SGA里面是分配了60多M的flashback generation buffer.
Successful mount of redo thread 1, with mount id 806293483
Allocated 63749952 bytes in shared pool for flashback generation buffer
Starting background process RVWR
Sat Dec 24 22:38:39 2016
RVWR started with pid=23, OS id=21403开始闪回到指定的还原点
flashback database to restore point fb_recover_trunc;这个时候闪回日志还是没有任何大小的变化。不过数据库日志需要格外关注。
Sat Dec 24 22:39:17 2016
flashback database to restore point fb_recover_trunc
Flashback Restore Start
Flashback Restore Complete
Flashback Media Recovery Start
started logmerger process
Parallel Media Recovery started with 24 slaves
Sat Dec 24 22:39:18 2016
Recovery of Online Redo Log: Thread 1 Group 3 Seq 11412 Reading mem 0
Mem# 0: /U01/app/oracle/oradata/newtest2/redo03.log
Incomplete Recovery applied until change 192530049488 time 12/24/2016 22:35:16
Flashback Media Recovery Complete
Completed: flashback database to restore point fb_recover_trunc
这段日志很宝贵,可以看到是几个阶段,restore,media recovery,其中恢复的过程中是使用logmerger来处理的。这些个过程是后续进行分析的重要内容了。
为了简单验证,我们启动数据库至read only状态
alter database open read only;确认无误,后续的操作就是启动数据库,纠结的部分还是到来是,是一个resetlogs的操作。
shutdown immediate
startup mount
alter database open resetlogs;在主库上还是有些纠结,所以我喜欢在备库上来玩闪回数据库。
整个resetlogs的过程会重置redo.
但是闪回日志的大小依旧不会有任何的变化。
听起来闪回日志的作用还是不大明显,如果你做了DML的操作,那这个过程的影响就会放大数倍。
当前的这个测试表数据量在1600万。
SQL> select count(*)from test_fb;
COUNT(*)
----------
16000000
我们做一个大动作,闪回1000万数据。
SQL> delete from test_fb where rownum<10000000;
9999999 rows deleted.
这个过程会持续一些时间,可以看到后台的redo非常忙,切换了近90次。
而闪回日志是否很忙呢,这下终于忙起来了,而且非常忙,生成了非常多的闪回日志。
[oracle@newtest flashback]$ ll
total 2446012
-rw-r--r-- 1 oracle oinstall 171 Aug 21 20:37 a.sql
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:49 o1_mf_d5x1vjlb_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:49 o1_mf_d5x1vjvc_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:49 o1_mf_d5x2qv3h_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:49 o1_mf_d5x2r454_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2rf6s_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2rm8d_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2rwb0_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2s5co_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2sgfb_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2sngx_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2sxjk_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:50 o1_mf_d5x2t6l6_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:51 o1_mf_d5x2thmt_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:51 o1_mf_d5x2toof_.flb
-rw-r----- 1 oracle oinstall 52436992 Dec 24 22:51 o1_mf_d5x2tyq2_.flb
-rw-r----- 1 oracle oinstall 104865792 Dec 24 22:51 o1_mf_d5x2v4rn_.flb
-rw-r----- 1 oracle oinstall 209723392 Dec 24 22:52 o1_mf_d5x2vfvm_.flb
-rw-r----- 1 oracle oinstall 389283840 Dec 24 22:53 o1_mf_d5x2vx2o_.flb
-rw-r----- 1 oracle oinstall 453705728 Dec 24 22:54 o1_mf_d5x2wyhs_.flb
-rw-r----- 1 oracle oinstall 560545792 Dec 24 22:53 o1_mf_d5x2yxz0_.flb
而且尤其值得关注的是,后面生成的闪回日志不是按照原有的50M而是逐步递增的节奏。
如果你继续使用truncate的方式清理数据,闪回日志的大小还是没有任何的变化。这应该不是巧合,也是故弄玄虚,flashback restore,flashback media recovery这些需要关注,后台进程RVWR来维护整个闪回数据库的过程,自有它的道理。