使用闪回查询恢复误删除的数据
某日,一个朋友的数据库数据被误操作删除(delete)掉了,并且已经提交请求请我帮忙进行恢复。数据库版本是Oracle 10g Release 2的,我首先想到的是使用Flashback Query进行闪回恢复,不幸的是出现了ORA- 01555,数据已经不能被闪回了。
Oracle从9i开始推出的闪回查询特性被一直不断增强着,闪回查询通过对回滚段中存储的前镜像数据进行追溯,可以获得变更之前的数据,从而在前镜像被覆盖之前,提供一种快捷的恢复和回退方式,在Oracle Database 11g中,Oracle更加引入了闪回数据归档的新特性,允许将前镜像数据通过独立的表空间进行归档,从而提供长达数年的历史追溯。
闪回特性受到初始化参数UNDO_RETENTION的影响,这个参数在10g中默认地设置为900秒,这个时间长度一般是不够的,我们可以根据数据库的具体情况,酌情调高这个参数,将前镜像的期望保留时间延长,一般习惯将这个参数修改为10 800秒,即3个小时(代码如下):ALTERSYSTEMSETundo_retention=10800 SCOPE=BOTH;
但请注意,增大这个参数可能会导致更多的UNDO表空间使用,以前在Oracle 9iR2中,这个参数的默认值一度被设为10 800秒,可是随之而来的问题可能是UNDO表空间的过分扩展,不易回收,所以Oracle在不同版本中,也在进行不停地折中,不断尝试不同的初始化参数设置。Oracle也许会这样想:如果很少有人使用Flashback Query,而过大的UNDO_RETENTION又会带来麻烦,那么干脆,设小点。
而根据我们的经验,在初始化创建数据库之后,UNDO_RETENTION的设置应该被修改,这一经验性调整应该被更新入安装手册,在数据库创建之后即刻进行。
然而在生产环境中修改这样一个参数需要谨慎,事实上,我们提醒DBA们要养成一些良好的习惯,如:
1. 尽量在测试后才在生产环境中执行某些维护操作。
2. 在生产环境空闲时才执行某些特定的维护操作。
在RAC环境中,修改某些数据库参数更须谨慎,有客户遇到了这样的问题,在Oracle 10gR1 RAC环境下修改UNDO_RETENTION参数,使用如下命令:altersystemsetundo_retention=18000 sid='*';
这条命令直接导致了RAC的其他节点挂起,Oracle记录了一个相关Bug,Bug号为4220405,Oracle提示不指定具体SID的UNDO_RETENTION修改在该版本中不被支持,其Workaround就是,分别修改不同实例:
altersystemsetundo_retention=18000 sid='RAC1';
altersystemsetundo_retention=18000 sid='RAC2';
altersystemsetundo_retention=18000 sid='RAC3';
......
Oracle声明在Oracle Database 11g中改正了以上这一问题,笔者曾经在10.2.0.4版本中测试过,证实已经不存在这个问题了。
这样一个简单的案例告诉我们,数据库的Bug可能无处不在,生产数据库调整应当极其谨慎,对于DBA来说,养成一些良好的工作习惯对于减少故障非常重要。
以下是一个简单的通过闪回查询恢复误删除数据的案例,这一特性应当为DBA所熟知。
某日下午接到研发工程师的电话,说误删除了部分重要数据,并且已经提交,需要恢复。登录到数据库上查看,由于是Oracle9iR2,首先尝试使用flashback query闪回数据。
数据库运行在归档模式,可以首先通过V$ARCHIVED_LOG视图来确认数据库的SCN变化,如下所示:SQL> col fscnfor9999999999999999999
SQL> col nscnfor9999999999999999999
SQL>selectname,FIRST_CHANGE# fscn,NEXT_CHANGE#
nscn,FIRST_TIMEfromv$archived_log;
NAMEFSCN
NSCN FIRST_TIME
------------------------------ ------------
-------------------- -------------------
/mwarch/oracle/1_52413.dbf 12929941968
12929942881 2005-06-22 14:38:28
/mwarch/oracle/1_52414.dbf 12929942881
12929943706 2005-06-22 14:38:32
/mwarch/oracle/1_52415.dbf 12929943706
12929944623 2005-06-22 14:38:35
/mwarch/oracle/1_52416.dbf 12929944623
12929945392 2005-06-22 14:38:38
/mwarch/oracle/1_52417.dbf 12929945392
12929945888 2005-06-22 14:38:41
/mwarch/oracle/1_52418.dbf 12929945888
12929945965 2005-06-22 14:38:44
/mwarch/oracle/1_52419.dbf 12929945965
12929948945 2005-06-22 14:38:45
/mwarch/oracle/1_52420.dbf 12929948945
12929949904 2005-06-22 14:46:05
/mwarch/oracle/1_52421.dbf 12929949904
12929950854 2005-06-22 14:46:08
/mwarch/oracle/1_52422.dbf 12929950854
12929951751 2005-06-22 14:46:11
/mwarch/oracle/1_52423.dbf 12929951751
12929952587 2005-06-22 14:46:14
...................
/mwarch/oracle/1_52498.dbf 12930138975
12930139212 2005-06-22 15:55:57
/mwarch/oracle/1_52499.dbf 12930139212
12930139446 2005-06-22 15:55:59
/mwarch/oracle/1_52500.dbf 12930139446
12930139682 2005-06-22 15:56:00
/mwarch/oracle/1_52501.dbf 12930139682
12930139915 2005-06-22 15:56:02
/mwarch/oracle/1_52502.dbf 12930139915
12930140149 2005-06-22 15:56:03
/mwarch/oracle/1_52503.dbf 12930140149
12930140379 2005-06-22 15:56:05
/mwarch/oracle/1_52504.dbf 12930140379
12930140610 2005-06-22 15:56:05
/mwarch/oracle/1_52505.dbf 12930140610
12930140845 2005-06-22 15:56:07
获得当前的SCN为:SQL>selectdbms_flashback.get_system_change_number fscnfromdual;
FSCN
--------------------
12930142214
使用应用用户尝试闪回:SQL>connectusername/password
Connected.
现有数据:SQL>selectcount(*)fromhs_passport;
COUNT(*)
----------
851998
创建恢复表如下:SQL>createtablehs_passport_recovasselect*
fromhs_passportwhere1=0;
Tablecreated.
根据开发人员提供的大致误操作时间,结合V$ARCHIVED_LOG视图,选择适当SCN向前执行闪回查询:SQL>selectcount(*)fromhs_passportasofscn 12929970422;
COUNT(*)
----------
861686
尝试多个SCN,获取***值(如果能得知具体时间,那么可以获得准确的数据闪回):SQL>selectcount(*)fromhs_passportasofscn &scn;
Enter valueforscn: 12929941968
COUNT(*)
----------
861684
SQL> /
Enter valueforscn: 12927633776
selectcount(*)fromhs_passportasofscn 12927633776
*
ERRORatline 1:
ORA-01466: unabletoreaddata -tabledefinition has changed
SQL> /
Enter valueforscn: 12929928784
COUNT(*)
----------
825110
SQL> /
Enter valueforscn: 12928000000
selectcount(*)fromhs_passportasofscn 12928000000
*
ERRORatline 1:
ORA-01466: unabletoreaddata -tabledefinition has changed
***选择恢复到SCN为12929941968的时间点,代码如下:
SQL>insertintohs_passport_recovselect*
fromhs_passportasofscn 12929941968;
861684rowscreated.
SQL>commit;
Commitcomplete.
然后由研发人员通过HS_PASSPORT_RECOV表确认,向当前表中补回误删除的数据,至此闪回恢复成功。如果没有闪回特性,这样的恢复就或者需要通过物理备份进行不完全恢复,或者找出足够及时的逻辑备份来进行恢复,其过程都可能是极其复杂的。
【责任编辑:董书