最近看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利用最大化,这样的话还不如不开,因为开了归档模式数据库的压力会变高,第二管理归档日志会带来一定的维护成本。当然具体如何抉择,还是要依靠大家的实际情况。