最近看DBA相关的书,其中有一句话说的很好:一切的备份都是为了恢复
于是自己拿测试环境试了试,模拟一下恢复操作
具体测试场景:Flashback闪回table和DML语句
oracle版本:11gR2
小版本号:11.2.0.4.0
是否归档:非存档模式
首先书里写了,只要查询show parameter bin
,recyclebin
的值为on
,即可用flashback
恢复drop
的表,但是上网一查,貌似闪回操作还得开启归档模式,书中没写是否要必须开启归档模式,我们来试验一下看看:
首先建立一张表testlijian
,里面有一个字段叫name
,insert
三条数据为lijian3
,wangsiqi
,helloworld
,具体操作由PLsql图形化界面完成,我就不贴建表语句了。
之后我们执行show parameter bin
,得到结果:recyclebin
的值为on
sql> show parameter bin NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ cursor_bind_capture_destination string memory+disk recyclebin string on
之后我们drop
这个表,执行drop table testlijian;
ok,这张表被drop掉了。
我们现在执行select * from testlijian;
得到数据库中没有这张表:
sql> select * from testlijian; select * from testlijian ORA-00942: 表或视图不存在
我们现在执行flashback table testlijian to before drop;
之后再次执行select * from testlijian;
,会发现表已经回来了,而且表里的记录也没有丢失。
完整的执行过程如下:
sql> select * from testlijian; select * from testlijian ORA-00942: 表或视图不存在 sql> flashback table testlijian to before drop; Done sql> select * from testlijian; NAME -------------------------------------------------- lijian3 wangsiqi helloworld sql>
从这里可以验证出来,flashback闪回被drop掉的table,是不需要开启归档模式的,只跟是否开启回收站功能有关。
之后我们来验证一下DML语句是否也可以不用开启归档模式,用闪回来恢复。
我们执行一条命令:update testlijian set name ='lijian4' where name = 'lijian3';
commit;
之后用如下命令来确定xid号:
select versions_xid,name from testlijian versions between scn minvalue and maxvalue;
得到刚刚提交的update操作的xid号为:0900090018740000
我们再执行如下命令:
select operation,undo_sql from flashback_transaction_query where xid = hextoraw('0900090018740000')
我们把完整的操作记录复制出来看一下:
sql> update testlijian set name ='lijian4' where name = 'lijian3'; 1 row updated sql> sql> select versions_xid,name 2 from testlijian 3 versions between scn minvalue and maxvalue; VERSIONS_XID NAME ---------------- -------------------------------------------------- lijian3 wangsiqi helloworld sql> commit; Commit complete sql> sql> select versions_xid,name 2 from testlijian 3 versions between scn minvalue and maxvalue; VERSIONS_XID NAME ---------------- -------------------------------------------------- 0900090018740000 lijian4 lijian3 wangsiqi helloworld sql> sql> select operation,undo_sql 2 from flashback_transaction_query 3 where xid = hextoraw('0900090018740000') 4 ; OPERATION UNDO_sql -------------------------------- -------------------------------------------------------------------------------- UNKNOWN BEGIN sql>
我们可以看到,在最后一个sql执行完了之后,undo_sql怎么是空的呢?然后operation也是unknown,明明我执行了一个update语句呀?
关于这里,我上网查询了一下:原来在11gR2里,有一个功能默认是不开启的
oracle11gR2默认禁止supplemental logging
需要把它开启,需要执行alter database add supplemental log data;
如果要把它关闭,就是执行alter database drop supplemental log data;
我们来实验一下:
执行alter database add supplemental log data;
再把咱们之前的update语句改一改:update testlijian set name ='lijian5' where name = 'lijian4';
之后再重复一下我们之前做过的操作,完整记录贴出来:
sql> alter database add supplemental log data; Database altered sql> update testlijian set name ='lijian5' where name = 'lijian4'; 1 row updated sql> commit; Commit complete sql> sql> select versions_xid,name 2 from testlijian 3 versions between scn minvalue and maxvalue; VERSIONS_XID NAME ---------------- -------------------------------------------------- 060015002A710000 lijian5 0900090018740000 lijian4 lijian3 wangsiqi helloworld sql> sql> select operation,undo_sql 2 from flashback_transaction_query 3 where xid = hextoraw('060015002A710000'); OPERATION UNDO_sql -------------------------------- -------------------------------------------------------------------------------- UPDATE update "JLLT_DM"."TESTLIJIAN" set "NAME" = 'lijian4' where ROWID = 'AAAW08AAFAAK BEGIN sql>
ok,这回我们看见了undo_sql的内容,正是我们执行的Update语句。
我们执行:
select operation,start_scn from flashback_transaction_query where xid = hextoraw('060015002A710000');
得到SCN号为:1559951294
,后来发现这个数不对,因为没设置行显示长度,看的不全,导致后面有一个错误出来。
我们先开启行迁移模式:alter table testlijian enable row movement;
执行flashback table testlijian to SCN 1559951294;
完整操作如下:
sql> select operation,start_scn 2 from flashback_transaction_query 3 where xid = hextoraw('060015002A710000'); OPERATION START_SCN -------------------------------- ---------- UPDATE 1559951294 BEGIN 1559951294 sql> alter table testlijian enable row movement; Table altered sql> flashback table testlijian to SCN 1559951294; flashback table testlijian to SCN 1559951294 ORA-08181: 指定的编号不是有效的系统更改号 sql> flashback table testlijian to SCN 15599512948179; Done sql> select * from testlijian; NAME -------------------------------------------------- lijian4 wangsiqi helloworld sql> alter table testlijian disable row movement; Table altered sql>
我们惊喜的看到,lijian5又变回了lijian4,这说明我们不开启归档模式,我们也能够通过闪回找回误操作后的数据了!
但是这个操作,有一个限制条件,那就是这个找回,是在回滚段里找回的,那就跟一个参数的设置有关,即:undo_retention
我们看一下库里这个参数的设定:
sql> select name,value 2 from v$parameter 3 where name like '%undo%'; NAME VALUE ----------------------------------------------------------------- undo_management AUTO undo_tablespace UNDOTBS1 undo_retention 900
可以看到,这里是900秒,也就是说,我们的误操作,第一要满足undo的空间足够大,能够装得下这部分数据,另外要满足15分钟这个条件,才能通过非归档模式下的flashback找回成功。
从这里我们展开一下联想,很多数据库都开了归档模式,但是并没有配置Rman来对这些archivelog利用最大化,这样的话还不如不开,因为开了归档模式数据库的压力会变高,第二管理归档日志会带来一定的维护成本。当然具体如何抉择,还是要依靠大家的实际情况。