全部博文(101)
分类: Oracle
2011-04-19 18:44:58
二.闪回错误的DML操作
前提:oracle版本必须oracle10g以上。
原理:oracle是利用还原段(回滚段)中的数据来进行这一恢复的。
undo_retention参数:提交DML操作之后,该操作所使用的还原段就可以被其他的操作使用了,为
了保证在进行闪回操作时这些数据仍然在还原段中,可以能要重新设置undo_retention参数,该参
数的单位是秒,表示一个事物提交后,该事物的数据至少要在还原段中保留该参数所定义的时间。
实际示例演示这个参数:
SQL> conn as sysdba;
已连接。
SQL> --显示参数;
SQL> show parameter undo_retention;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_retention integer 900
SQL> --默认是900秒(15分钟),现在改成7200秒(2个小时);
SQL> alter system set undo_retention=7200;
系统已更改。
SQL> show parameter undo_retention;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_retention integer 7200
SQL> --修改成功;
提示:闪回技术并不能保证两个小时内提交的DML操作一定能恢复,因为还原表空间没用足够的
空间时oracle仍然会使用undo_retention参数要求保留的磁盘空间,即这部分表空间中的数据
有可能被覆盖掉。因为该参数是针对整个数据库的,所以这个参数不能设置的太大。
下面是具体示例如何使用闪回命令恢复数据;
C:/Documents and Settings/jacky>sqlplus/nolog
SQL*Plus: Release 10.2.0.1.0 - Production on 星期六 4月 2 13:30:17 2011
Copyright (c) 1982, 2005, Oracle. All rights reserved.
SQL> conn ;
已连接。
SQL> select * from shandml;
SD SJ ID
---------------------------------------- ---------- ----------
3.18日22点-----3.19日01点 30000 20
3.19日01点-----3.19日04点 30000 21
3.19日04点-----3.19日07点 30000 22
3.19日07点-----3.19日10点 30000 23
3.17日16点-----3.17日19点 30000 24
SQL> update shandml set sj=50000;
已更新5行。
SQL> select versions_xid,sd,sj,id from shandml
2 versions between scn minvalue and maxvalue
3 ;
VERSIONS_XID SD SJ ID
---------------- ---------------------------------------- ---------- ----------
3.18日22点-----3.19日01点 30000 20
3.19日01点-----3.19日04点 30000 21
3.19日04点-----3.19日07点 30000 22
3.19日07点-----3.19日10点 30000 23
3.17日16点-----3.17日19点 30000 24
SQL> --上面输出表示version_xid为空,是因为我们没有提交刚才的dml,现在我们提交;
SQL> commit;
提交完成。
SQL> select versions_xid,sd,sj,id from shandml
2 versions between scn minvalue and maxvalue;
VERSIONS_XID SD SJ ID
---------------- ---------------------------------------- ---------- ----------
07001A00EC010000 3.18日22点-----3.19日01点 50000 20
07001A00EC010000 3.19日01点-----3.19日04点 50000 21
07001A00EC010000 3.19日04点-----3.19日07点 50000 22
07001A00EC010000 3.19日07点-----3.19日10点 50000 23
07001A00EC010000 3.17日16点-----3.17日19点 50000 24
3.18日22点-----3.19日01点 30000 20
3.19日01点-----3.19日04点 30000 21
3.19日04点-----3.19日07点 30000 22
3.19日07点-----3.19日10点 30000 23
3.17日16点-----3.17日19点 30000 24
已选择10行。
SQL> --从上面可以看出SJ这列的值做了修改且相应的version_xid也有了值了,
SQL> --切换到拥有DBA权限的用户,因为jacky有dba的权限,所以不用切换;
SQL> --下面介绍一个新的数据字典flashback_transaction_query;
SQL> col operation for a10
SQL> col undo_sql for a80
SQL> set line 150
SQL> select operation,undo_sql from flashback_transaction_query
2 where xid=hextoraw('07001A00EC010000');
OPERATION UNDO_SQL
---------- ---------------------------------------------------------------------
-----------
UPDATE update "JACKY"."SHANDML" set "SJ" = '30000' where ROWID = 'AAAMrOAAEA
AAAB0AAA';
UPDATE update "JACKY"."SHANDML" set "SJ" = '30000' where ROWID = 'AAAMrOAAEA
AAAB0AAB';
UPDATE update "JACKY"."SHANDML" set "SJ" = '30000' where ROWID = 'AAAMrOAAEA
AAAB0AAC';
UPDATE update "JACKY"."SHANDML" set "SJ" = '30000' where ROWID = 'AAAMrOAAEA
AAAB0AAD';
UPDATE update "JACKY"."SHANDML" set "SJ" = '30000' where ROWID = 'AAAMrOAAEA
AAAB0AAE';
BEGIN
已选择6行。
SQL> --undo_sql表示要恢复到原来的所需执行的语句;
SQL> --看一下表中现在的值;
SQL> select * from shandml;
SD SJ ID
---------------------------------------- ---------- ----------
3.18日22点-----3.19日01点 50000 20
3.19日01点-----3.19日04点 50000 21
3.19日04点-----3.19日07点 50000 22
3.19日07点-----3.19日10点 50000 23
3.17日16点-----3.17日19点 50000 24
SQL> --因为已经提交了,所以SJ的值已经修改了;
SQL> --重要步骤,因为俺突然后悔了,俺想将刚才的DML操作撤销;
SQL> --首先是查询刚刚提交事务的对应的SCN号;
SQL> select operation,start_scn from flashback_transaction_query
2 where xid=hextoraw('07001A00EC010000');
OPERATION START_SCN
---------- ----------
UPDATE 1121240
UPDATE 1121240
UPDATE 1121240
UPDATE 1121240
UPDATE 1121240
BEGIN 1121240
已选择6行。
SQL> --重要时刻,我们要回到查询到的SCN的那个时刻点,来恢复到当时的状态;
SQL> --不过之前先要打开该表的行移动功能,oracle默认是关闭的;
SQL> alter table jacky.shandml enable row movement;
表已更改。
SQL> --然后再执行恢复操作;
SQL> flashback table jacky.shandml to SCN 1121240;
闪回完成。
SQL> --进下来便是验证奇迹的时刻;
SQL> select * from jacky.shandml;
SD SJ ID
---------------------------------------- ---------- ----------
3.18日22点-----3.19日01点 30000 20
3.19日01点-----3.19日04点 30000 21
3.19日04点-----3.19日07点 30000 22
3.19日07点-----3.19日10点 30000 23
3.17日16点-----3.17日19点 30000 24
SQL> --OMG,果然SJ的值已经变回原来的了,看来这个闪回功能还真是有用;呵呵!
补充说明:闪回DML操作还可以闪回到指定的时间;
例如: flashback table jacky.shandml
to timestamp to _timestamp('2011-04-02 13:30:00','yyyy-mm-dd hh24:mi:ss');
提示:对比起来用SCN号恢复更加保险和安全。