Oracle表误操作恢复历史数据方法

178 篇文章 16 订阅

背景说明

最近在生产环境中,开发人员误操作,错误update数据库某张表的部分数据,在一天后发现问题,于是联系DBA进行紧急数据恢复。

处理思路

如果能查询到操作前的一分钟数据是什么样子,就可以将这些数据筛选出来,与现在改过的数据进行对比,借助一个临时的表,将需要更正的数据的原来的数据保存在临时表内,然后基于临时表的数据和现在的数据进行对比修改。就可以使数据回到修改前的状态。

处理方法

一、表的恢复

如果Oracle版本是在8i或之前版本,需要通过备份恢复,自9i之后,使用Flashback Query的特性,我们可以很轻松地恢复记录(注意并不是任何情况下都可以恢复哟,这里假设的都是在理想条件下)。

对误删的表,只要没有使用PURGE永久删除选项,那么从FLASHBACK TABLE区恢复回来希望是挺大的。一般步骤有:
1、从FLASHBACK TABLE里查询被删除的表

SELECT * FROM RECYCLEBIN ORDER BY DROPTIME DESC

2.执行表的恢复

FLASHBACK TABLE TABLE_NAME TO BEFORE DROP;
二、表数据恢复

对误删的表记录,只要没有 TRUNCATE 语句,就可以根据事务的提交时间进行选择恢复,一般步骤有:
1、先从 FLASHBACK_TRANSACTION_QUERY 视图里查询,视图提供了供查询用的表名称、事务提交时间、UNDO_SQL等字段。

SELECT * FROM FLASHBACK_TRANSACTION_QUERY WHERE TABLE_NAME='TEST';

2、执行表记录恢复
一般先根据时间进行查询,基于时间查询过去某一时刻某个表的数据,查询语句模式为【1】:

SELECT * FROM TABLE_NAME AS OF TIMESTAMP TO_TIMESTAMP(TIME,'yyyy-mm-dd hh24:mi:ss'); --time指某个时间点

说明:TABLE_NAME是误操作需要闪回的表,time是误操作的时间点,是个大概的时间,不用精确,在这个时间之前就是之前正确的数据,之后就是误操作后的数据

如查询SCOTT.TEST 表 2022-07-08 00:00:00 时的数据:

SELECT * FROM SCOTT.TEST AS OF TIMESTAMP TO_TIMESTAMP('2022-07-08 00:00:00','yyyy-mm-dd hh24:mi:ss');

若有数据,恢复极为简单了:
方法一:

ALTER TABLE TABLE_NAME ENABLE ROW MOVEMENT; --TABLE_NAME是误操作需要闪回的表

这个命令的作用是,允许Oracle 修改分配给行的rowid。
在Oracle 中,插入一行时就会为它分配一个rowid,而且这一行永远拥有这个rowid。
闪回表处理会对EMP 完成DELETE,并且重新插入行,这样就会为这些行分配一个新的rowid。
要支持闪回就必须允许Oracle 执行这个操作
闪回操作前启用行移动功能

FLASHBACK TABLE TABLE_NAME TO TIMESTAMP TO_TIMESTAMP(TIME,'yyyy-mm-dd hh24:mi:ss'); 

如:

FLASHBACK TABLE SCOTT.TEST TO TIMESTAMP TO_TIMESTAMP('2022-07-08 00:00:00','yyyy-mm-dd hh24:mi:ss');

方法二:
创建一个临时表,用来保存误操作之前的数据

create table NewTable_Name  as  select * from OldTtable_Name AS OF TIMESTAMP TO_TIMESTAMP('TIME,'yyyy-mm-dd hh24:mi:ss'');

如:

create table SCOTT.TEST_NEW  as  select * from SCOTT.TEST AS OF TIMESTAMP TO_TIMESTAMP('2022-07-08 00:00:00,'yyyy-mm-dd hh24:mi:ss'');

确认后可删除原表,并将临时表改名:

drop table SCOTT.TEST; --删除原来的表

alter table SCOTT.TEST_NEW rename to SCOTT.TEST;--更改临时表的表名
拓展

Ⅰ、AS OF SCN方式
需要对多个相互有主外键约束的表进行恢复时,如果使用AS OF TIMESTAMP的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过AS OF SCN方式则能够确保记录处理的时间点一致。

a.假设此时距离误操作已经过了一分钟了,此时你应该确认误操作前的某个时间节点对应的scn号。

查询指定范围的时间和scn的的映射关系语句:

select timestamp_to_scn(sysdate-1/1440)as scn from dual;--查询一分钟之前的scn号

select scn_to_timestamp(17528041484406)from dual;--查询指定scn号对应的时间
  • 因为使用到了dbms_flashback包,如果是普通用户需要使用sysdba给用户赋权:
    grant execute on dbms_flashback to 用户名;
  • 每隔5分钟,系统产生一次系统时间标记与scn的匹配并存入sys.smon_scn_time表。

b.根据上面的第一条语句,获取到误操作前一分钟的scn号(假设为 17528041484406),就可以查看该时刻此表的数据:

select * from table  as of scn 17528041484406;

scn是oracle数据库系统提供的标识时间和系统改变码之间的一种映射关系(sys.smon_scn_time)。
在10g中,系统平均每3秒产生一次系统时间与SCN的匹配并存入SYS.SMON_SCN_ TIME表。因此10g版本如果使用AS OF TIMESTAMP查询UNDO中的数据,实际获取的数据是以指定的时间对应的SCN时的数据为基准。
使用scn查询更加准确,因为scn对应的timestamp是时间的一个区间,scn对应一段区间值,并且在低版本中timestamp和scn的值是每隔5分钟才真正映射到smon_scn_time表中的,所以在闪回查询中尽量使用基于scn的闪回查询。
使用SCN查询会比TIMESTAMP更加精确,事实上,即使执行Flashback Query时指定的是AS OF TIMESTAMP,Oracle也会将其转换成SCN,这是由于Oracle内部都是通过SCN来标记操作而不是时间。

Ⅱ、Falshback query查询的局限

1. 不能Falshback到5天以前的数据。

2. 闪回查询无法恢复到表结构改变之前,因为闪回查询使用的是当前的数据字典。

3. 受到undo_retention参数的影响,对于undo_retention之前的数据,Flashback不保证能Flashback成功。

4. 对drop,truncate等不记录回滚的操作,不能恢复。



附录:

【1】也可通过如下语句进行相对时间查询,如:

select * from SCOTT.TEST as of timestamp sysdate - 30/1440;//查询SCOTT.TEST表30分钟前的数据

参考文章:
https://www.cnblogs.com/vipsoft/archive/2012/12/19/2825312.html
https://www.cnblogs.com/coco–/p/12201980.html
https://www.jianshu.com/p/ce4828be77fe

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值