Oracle Backout Transaction

        Oracle 11g撤销事务(Backout Transaction),能够撤销一个或多个事务的修改,其功能由一个名为DBMS_FLASHBACK.TRANSACTION_BACKOUT的存储过程实现。该存储过程的工作原理是自动分析重做日志,挖掘出变更前的值用以构建撤销SQL(Undo SQL),然后执行撤销SQL最后达到撤销事务的目的。为了该功能可以正常使用,至少需要事先启用主键补充日志。另外,为了能够跟踪外键依赖还需要启用外键补充日志。

事务的依赖性 比如,两个事务TX1和TX2,若符合以下3个条件的任意一个就可以认为TX2依赖TX1:

(1)WAW依赖(Write After Write),即在TX1修改了表的某行之后,TX2又修改了同一行。

(2)主键依赖,即在一张拥有主键的表中TX1首先删除了一行,之后TX2又插入了具有相同主键值的另一行。

(3)外建依赖,即由于TX1的修改(insert或update)而产生了新的可被外键参考的字段值,之后TX2修改(insert或update)外键字段时利用了TX1所产生的字段值。

了解事务依赖性有助于解决在撤销事务时遇到的矛盾,以主键依赖为例,试想若直接将事务TX1撤销并且不理会事务TX2,岂不是会出现主键值重复的行!

        TRANSACTION_BACKOUT存储过程的OPTIONS参数就是为了解决事务依赖性问题而存在的,在该参数上管理员可以使用4种撤销事务的方案,假设被撤销的事务是TX1,若其具有依赖事务,则称为TX2:

(1)NOCASCADE,TX1不可以被任何其他事务依赖(即TX2不存在),否则撤销操作报错。

(2)CASCADE,将TX1连同TX2一起撤销。

(3)NOCASCADE_FORCE,忽略TX2,直接执行TX1的撤销SQL将TX1撤销,如果没有约束上的冲突,操作将成功,否则约束报错导致撤销操作失败。

(4)NONCONFILICT_ONLY,在不影响TX2的前提下,撤销TX1的修改。与NOCASCADE_FORCE的不同点在于会首先过滤一下TX1的撤销SQL,确保它们不会作用在TX2修改的行上。

        使用DBMS_FLASHBACK.BACKOUT_TRANSACTION的步骤如下:

(1)将需要撤销的事务的事务号或事务名载入对应的VARRAY集合变量。

(2)以NOCASCADE方式调用BACKOUT_TRANSACTION。如果报错,再从另外3种方式中选择一个调用BACKOUT_TRANSACTION。

(3)查看闪回事务操作的报告。

(4)最后决定提交或回滚。

事例:

--修改emp表中sal值

--执行事务1

update emp set sal=800 where empno< 7600;
commit;

--执行事务2
update emp set sal=sal*2 where empno=7499;
commit;

---由于误操作,现在需要撤销事务1

--oracle 11g默认禁用了附加日志,会导致undo_sql为空
--启用附加日志
alter database add supplemental log data;

--查询最近15分钟内的事务
select distinct xid, commit_scn
  from flashback_transaction_query
 where table_owner = 'SCOTT'
   and table_name = 'EMP'
   and commit_timestamp > systimestamp - interval '15' minute
 order by commit_scn;

--确定要撤销事务的undo_sql (事务号小的是需要撤销的事务)
select row_id,undo_sql from flashback_transaction_query where commit_scn='2395146'

--执行撤销事务1操作,首先用nocascade(由于存在事务2,所以会报错)
declare
  v_xid xid_array;
begin
  v_xid :=xid_array('05000300FB050000');
  dbms_flashback.transaction_backout(1,v_xid,options => dbms_flashback.nocascade);
end;

--执行撤销事务1操作,用nocascade_force(忽略事务2,撤销事务1)
declare
  v_xid xid_array;
begin
v_xid :=xid_array('05000300FB050000');
  dbms_flashback.transaction_backout(1,v_xid,options => dbms_flashback.nocascade_force);
end;

--完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值