设为首页 收藏本站
查看: 829|回复: 0

[经验分享] oracle误删除表数据后的恢复详解

[复制链接]

尚未签到

发表于 2016-8-6 09:29:07 | 显示全部楼层 |阅读模式
  
一、undo_retention参数的查询、修改:
show parameter undo;命令查看当时的数据库参数undo_retention设置。
显示如下:
undo_management                       string       AUTO
undo_retention                              integer     10800
undo_suppress_errors                  boolean      FALSE
undo_tablespace                           string       UNDOTBS1
undo_retention(保持力),10800单位是秒。即3个小时。
修改默认的undo_retention参数设置:
ALTER SYSTEM SET undo_retention=10800 SCOPE=BOTH;
二、oracle误删除表数据后的的快速恢复功能方法:
【方法一】:
通过oracle提供的回闪功能:
exec dbms_flashback.enable_at_time(to_date('2007-07-23 10:21:00','yyyy-mm-dd hh24:mi:ss'));
set serveroutput on
DECLARE r_temp hr.job_history%ROWTYPE;
CURSOR c_temp IS SELECT * FROM hr.job_history;
BEGIN
OPEN c_temp;
dbms_flashback.disable;
LOOP
FETCH c_temp INTO r_temp;
EXIT WHEN c_temp%NOTFOUND;
insert into hr.job_history(EMPLOYEE_ID,JOB_ID,START_DATE,END_DATE) values (r_temp.EMPLOYEE_ID,r_temp.JOB_ID,r_temp.START_DATE,r_temp.END_DATE);
commit;
END LOOP; 
CLOSE c_temp; 
END;
这种办法可以将删除的数据恢复到对应的表中,首先要保证该用户有执行dbms_flashback包的权限
【方法二】:
insert into hr.job_history
select * from hr.job_history as of timestamp to_timestamp('2007-07-23 10:20:00', 'yyyy-mm-dd hh24:mi:ss');

这种方法简单,容易掌握,功能和上面的一样时间为你误操作之前的时间,最好是离误操作比较近的,因为oracle保存在回滚保持段里的数据时间有一定的时间限制由undo_retention 这个参数值决定。
 




SQL> col fscn for 9999999999999999999
SQL> col nscn for 9999999999999999999
SQL> select name,FIRST_CHANGE# fscn,NEXT_CHANGE# nscn,FIRST_TIME from v$archived_log;
...................
NAME                                           FSCN                 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
NAME                                           FSCN                 NSCN FIRST_TIME
------------------------------ -------------------- -------------------- -------------------
/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
14811 rows selected.


当前的SCN为:

SQL> select dbms_flashback.get_system_change_number fscn from dual;
FSCN
--------------------
12930142214


使用应用用户尝试闪回

SQL> connect username/password
Connected.


现有数据:

SQL> select count(*) from hs_passport;
COUNT(*)
----------
851998

创建恢复表

SQL> create table hs_passport_recov as select * from hs_passport where 1=0;
Table created.


选择SCN向前恢复

SQL> select count(*) from hs_passport as of scn 12929970422;
COUNT(*)
----------
861686


尝试多个SCN,获取最佳值(如果能得知具体时间,那么可以获得准确的数据闪回)

SQL> select count(*) from hs_passport as of scn &scn;
Enter value for scn: 12929941968
old   1: select count(*) from hs_passport as of scn &scn
new   1: select count(*) from hs_passport as of scn 12929941968
COUNT(*)
----------
861684
SQL> /
Enter value for scn: 12927633776
old   1: select count(*) from hs_passport as of scn &scn
new   1: select count(*) from hs_passport as of scn 12927633776
select count(*) from hs_passport as of scn 12927633776
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed
SQL> /
Enter value for scn: 12929928784
old   1: select count(*) from hs_passport as of scn &scn
new   1: select count(*) from hs_passport as of scn 12929928784
COUNT(*)
----------
825110
SQL> /
Enter value for scn: 12928000000
old   1: select count(*) from hs_passport as of scn &scn
new   1: select count(*) from hs_passport as of scn 12928000000
select count(*) from hs_passport as of scn 12928000000
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed


最后选择恢复到SCN为12929941968的时间点

SQL> insert into hs_passport_recov select * from hs_passport as of scn 12929941968;
861684 rows created.
SQL> commit;
Commit complete.





 
 
数据恢复简单例子
 
简介 

在过去,如果用户误删/更新了数据后,作为用户并没有什么直接的方法来进行恢复,他们必须求助DBA来对数据库进行恢复,到了Oracle9i,这一个难堪局面有所改善。Oracle 9i中提供了一项新的技术手段--闪回查询,用户使用闪回查询可以及时取得误操作前的数据,并可以针对错误进行相应的恢复措施,而这一切都无需DBA干预。 

下面我们通过一个例子来具体说明闪回查询的用法。 

二、示例 

1、使用闪回查询前必须确定下面两个参数: 

UNDO_MANAGEMENT = AUTO 

undo_retention = 1200; #这个时间可以随便设,他表示在系统中保留提交了的UNDO信息的时间,1200就是保留20分钟。 

2、使用闪回查询 

SQL> conn sys/sys as sysdba 

Connected. 

SQL> create user flash identified by flash; 

User created. 

SQL> grant connect, resource to flash; 

Grant succeeded. 

SQL> grant execute on dbms_flashback to flash; 

Grant succeeded. 

SQL> conn flash/flash 

Connected. 

SQL> set echo on 

SQL> create table t (a varchar2(10)); 

Table created. 

SQL> insert into t values('gototop'); 

1 row created. 

SQL> insert into t values('www.ncn.cn'); 

1 row created. 

SQL> / 

SQL> select * from t; 



---------- 

gototop 

www.ncn.cn 

www.ncn.cn 

SQL> set time on 

15:00:22 SQL> 

15:00:22 SQL> 

15:00:23 SQL> delete t where a='gototop'; 

1 row deleted. 

15:00:35 SQL> commit; 

Commit complete. 

15:00:38 SQL> select * from t; 



---------- 

www.ncn.cn 

www.ncn.cn 

15:08:22 SQL> execute DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:00:00')); 

PL/SQL procedure successfully completed. 

15:09:02 SQL> select * from t; 



---------- 

gototop 

www.ncn.cn 

www.ncn.cn 

15:16:43 SQL> execute DBMS_FLASHBACK.DISABLE; 

PL/SQL procedure successfully completed. 

15:17:05 SQL> select * from t; 



---------- 

www.ncn.cn 

www.ncn.cn 

3、使用闪回查询恢复数据: 

15:36:55 SQL> select * from t; 

no rows selected 

15:36:57 SQL> insert into t values('www.ncn.cn'); 

1 row created. 

15:37:15 SQL> / 

1 row created. 

15:37:16 SQL> / 

1 row created. 

15:37:17 SQL> / 

1 row created. 

15:37:18 SQL> / 

1 row created. 

15:37:19 SQL> commit; 

Commit complete. 

15:37:21 SQL> / 

Commit complete. 

15:37:22 SQL> / 

Commit complete. 

15:37:23 SQL> select * from t; 



---------- 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

6 rows selected. 

15:37:28 SQL> 

15:38:44 SQL> delete t; 

6 rows deleted. 

15:38:50 SQL> commit; 

Commit complete. 

15:38:53 SQL> commit; 

Commit complete. 

15:38:54 SQL> / 

Commit complete. 

15:38:57 SQL> declare 

15:39:28 2 cursor flash_recover is 

15:39:28 3 select * from t; 

15:39:28 4 t_recode t%rowtype; 

15:39:28 5 begin 

15:39:28 6 DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:37:23')); 

15:39:28 7 open FLASH_RECOVER; 

15:39:28 8 DBMS_FLASHBACK.DISABLE; 

15:39:28 9 loop 

15:39:28 10 FETCH FLASH_RECOVER INTO t_recode; 

15:39:28 11 EXIT WHEN FLASH_RECOVER%NOTFOUND; 

15:39:28 12 insert into t values (t_recode.a); 

15:39:28 13 end loop; 

15:39:28 14 CLOSE FLASH_RECOVER; 

15:39:28 15 commit; 

15:39:28 16 end; 

15:39:28 17 / 

PL/SQL procedure successfully completed. 

15:39:28 SQL> 15:39:28 SQL> 

15:39:31 SQL> select * from t; 



---------- 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

www.ncn.cn 

15:39:35 SQL> 

我们可以已经恢复了5条纪录,但我们要恢复的6条纪录,为什么会少一条呢?原因就在下面。 

三、局限性 

1、闪回查询是基于SCN的,虽然我执行的是: 

DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:37:23')); 

但Oracle并不会精确的这个时间点,而是ROUND DOWN到最近的一次SCN,然后从这个SCN开始进行恢复。而Oracle 9i是每五分钟记录一次SCN的,并将SCN和对应时间的映射做个纪录。 

这正是上面我们进行恢复时少了一条的原因。因此如果使用DBMS_FLASHBACK.ENABLE_AT_TIME来进行恢复,为了避免恢复失败,我可以先等5分钟,然后再进行恢复。 

使用DBMS_FLASHBACK.ENABLE_AT_TIME进行恢复还有一个缺点,那就是在Oracle 9i中SCN和对应时间的映射信息只会保留5天,因此我们无法通过DBMS_FLASHBACK.ENABLE_AT_TIME来恢复5天前的数据。如果你想使用闪回查询来恢复5天前的数据,你必须自己来确定需要恢复的SCN,然后使用 

DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(SCN_NUMBER); 来定位你的恢复时间点,下面是使用方法: 

15:58:58 SQL> VARIABLE SCN_SAVE NUMBER; 

16:13:43 SQL> EXECUTE :SCN_SAVE := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER; 

PL/SQL procedure successfully completed. 

16:13:50 SQL> print SCN_SAVE; 

SCN_SAVE 

---------- 

2.1202E+11 

16:28:34 SQL> execute DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(:SCN_SAVE); 

PL/SQL procedure successfully completed. 

另外,在使用DBMS_FLASHBACK.ENABLE_AT_TIME前,你必须设定你的NLS_DATE_FORMAT的精确程度,Oracle默认的是精确到天,如果你不设定,像上面的例子你不会得到预期结果。 

2、如果你使用sysdate和DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER来获取时间点或者SCN值,你必须注意它们取得都是当前的时间点和SCN值。 

3、你只能在事务开始时进入闪回查询模式,如果之前有DML操作,则必须COMMIT。 

4、闪回查询无法恢复到表结构改变之前,因为闪回查询使用的当前的数据字典。  
 
附老陈的例子
 
Using Flashback Queries: Example The following statements show a current value from the sample table hr.employees and then change the value. The intervals used in these examples are very short for demonstration purposes. Time intervals in your own environment are likely to be larger.
 
SELECT salary FROM employees
   WHERE last_name = 'Chung';
 
    SALARY
----------
      3800
 
UPDATE employees SET salary = 4000
   WHERE last_name = 'Chung';
 
1 row updated.
 
SELECT salary FROM employees
   WHERE last_name = 'Chung';
 
    SALARY
----------
      4000
 
To learn what the value was before the update, you can use the following Flashback Query:
 
SELECT salary FROM employees
   AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE)
   WHERE last_name = 'Chung';
 
    SALARY
----------
      3800
 
To learn what the values were during a particular time period, you can use a version Flashback Query:
 
SELECT salary FROM employees
  VERSIONS BETWEEN TIMESTAMP
    SYSTIMESTAMP - INTERVAL '10' MINUTE AND
    SYSTIMESTAMP - INTERVAL '1' MINUTE
  WHERE last_name = 'Chung';
 
To revert to the earlier value, use the Flashback Query as the subquery of another UPDATE statement:
 
UPDATE employees SET salary =      
   (SELECT salary FROM employees
   AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '2' MINUTE)
   WHERE last_name = 'Chung')
   WHERE last_name = 'Chung';
1 row updated.
 
SELECT salary FROM employees
   WHERE last_name = 'Chung';
 
    SALARY
----------
      3800
 
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-253586-1-1.html 上篇帖子: SQL语句MSSQL.MySQL.Oracle.PostgreSQL不同用法 下篇帖子: Oracle 10g JDeveloper与J2EE实战演练(学习笔记)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表