ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 利用undo的闪回特性恢复错误操作的表

利用undo的闪回特性恢复错误操作的表

原创 Linux操作系统 作者:comebackdog 时间:2012-03-02 18:28:51 0 删除 编辑
网厅数据库一张表被开发人员一条sql误操作

update policy.wt_gift_instance set cust_id='171392222723',code_number='15306563211',code_type='18',
def_id='216481660',instance_id='305886471',
used_date=sysdate,gift_cust_id='171392222723',
give_code_number='15306563211',
give_code_type='18',modify_date=sysdate,
create_date=sysdate,status='已使用',
occupy_seq='309541654',sts='Y' where activity_def_id='4441521';

表policy.wt_gift_instance被错误的更改了,客户要求(我觉得他们应该雪地裸体跪求才对,嘿嘿)恢复被修改的数据。
数据库没有闪回区不能利用闪回区恢复,客户说数据今天更改量很小可以恢复到昨天备份的时候,但是rman备份没法恢复一张表到一个时间点。
考虑用logminer获得redo的sql但是太复杂,群里一吆喝有个哥们提出个方法,使用撤销段的闪回特性从undo数据里提取。

没有设置Retention Guarantee强制保留undo数据。
SQL> select tablespace_name,retention from dba_tablespaces where tablespace_name like '%UNDO%';

TABLESPACE_NAME            RETENTION
------------------------------ -----------
UNDOTBS1               NOGUARANTEE
UNDOTBS2               NOGUARANTEE

SQL> show parameter undo

NAME                     TYPE     VALUE
------------------------------------ ----------- ------------------------------
undo_management              string     AUTO
undo_retention                 integer     7200
undo_tablespace              string     UNDOTBS1

时间只有7200即2小时,切并不强制保留undo的数据。
先确定下是否有数据,这条sql的执行时间是15点13分,我们就查询这个时间点之前的数据。

执行操作如下:
SQL> select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 15:13:00','YYYY-MM-DD HH24:MI:SS') ;

  COUNT(*)
----------
    128720

ok 这部分数据还在,检查下现在表的数据记录
SQL> select count(*) from policy.wt_gift_instance;

  COUNT(*)
----------
    128736
记录数就差16条,因为开发人员说这个表今天新数据插入很少,刚才的误操作也只是update所以数据量应该没有问题。
趁热打铁,赶紧把数据导出来,建立新表policy.wt_gift_instance_restore将15点13分之前的数据从undo里导出来到新表中。
SQL>  create table policy.wt_gift_instance_restore tablespace TS_POLICY_DATA
as select * from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 15:13:00','YYYY-MM-DD HH24:MI:SS') ;

Table created.

检查新表记录
SQL> select count(*) from policy.wt_gift_instance_restore;

  COUNT(*)
----------
    128720

没问题

保险起见,有把15点10分的数据导出一份出来。
SQL>  create table policy.wt_gift_instance_restore_1 tablespace TS_POLICY_DATA
as select * from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 15:10:00','YYYY-MM-DD HH24:MI:SS') ;

Table created.

SQL> select count(*) from policy.wt_gift_instance_restore_1;

  COUNT(*)
----------
    128718

保险起见,有把15点整的数据导出一份出来。
SQL> create table policy.wt_gift_instance_restore_2 tablespace TS_POLICY_DATA
 as select * from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 15:00:00','YYYY-MM-DD HH24:MI:SS') ;

Table created.


SQL> select count(*) from policy.wt_gift_instance_restore_2;

  COUNT(*)
----------
    128709

把三个表告知开发人员,他们确定数据可以使用,剩下的事情是他们自己去整合新旧数据了。

随后又测试了下,看看能从中获得多少时间前的数据
SQL> select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 00:00:00','YYYY-MM-DD HH24:MI:SS') ;
select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 00:00:00','YYYY-MM-DD HH24:MI:SS')
                            *
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 74 with name "_SYSSMU74$"
too small


SQL> select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 09:00:00','YYYY-MM-DD HH24:MI:SS') ;
select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 09:00:00','YYYY-MM-DD HH24:MI:SS')
                            *
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 74 with name "_SYSSMU74$"
too small


SQL> select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 12:00:00','YYYY-MM-DD HH24:MI:SS') ;
select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 12:00:00','YYYY-MM-DD HH24:MI:SS')
                            *
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 74 with name "_SYSSMU74$"
too small


SQL> select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 14:00:00','YYYY-MM-DD HH24:MI:SS') ;
select count(*) from policy.wt_gift_instance AS OF timestamp to_timestamp ('2012-3-2 14:00:00','YYYY-MM-DD HH24:MI:SS')
                            *
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 89 with name "_SYSSMU89$"
too small

快照太旧,回滚段太小,都失败了,也就1小时左右前的数据保留在undo空间里了。


总结,利用undo的闪回特性查询数据表在某个时间点的数据可恢复意外的错误操作,但这个跟undo_retention设置的大小和Retention Guarantee参数(强制保留undo数据)有关。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/20575781/viewspace-717549/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 检查pga
请登录后发表评论 登录
全部评论

注册时间:2011-09-27

  • 博文量
    19
  • 访问量
    81573