记一次在非归档模式下的Oracle数据库用闪回操作恢复表和DML语句

最近看DBA相关的书,其中有一句话说的很好:一切的备份都是为了恢复
于是自己拿测试环境试了试,模拟一下恢复操作

具体测试场景:Flashback闪回table和DML语句
oracle版本:11gR2
小版本号:11.2.0.4.0
是否归档:非存档模式

首先书里写了,只要查询show parameter binrecyclebin 的值为on,即可用flashback恢复drop的表,但是上网一查,貌似闪回操作还得开启归档模式,书中没写是否要必须开启归档模式,我们来试验一下看看:

首先建立一张表testlijian,里面有一个字段叫nameinsert三条数据为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利用最大化,这样的话还不如不开,因为开了归档模式数据库的压力会变高,第二管理归档日志会带来一定的维护成本。当然具体如何抉择,还是要依靠大家的实际情况。

    原文作者:Summer的小西瓜
    原文地址: https://segmentfault.com/a/1190000011064417
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞