• flashback transaction闪回事务查询


    闪回事务查询有别于闪回查询的特点有以下3个: 

    (1)其正常工作不但需要利用撤销数据,还需要事先启用最小补充日志。 

    (2)返回的结果不是以前的“旧”数据,而是能够将当前数据修改为以前的样子的撤销SQL(Undo SQL)语句。 

    (3)集中地在名为flashback_transaction_query表上查询,而不是在各个表上通过“as of”或“versions between”子句查询。 

    了解了以上特点之后,使用闪回事务查询就没有任何困难了,首先打开最小补充日志: 

    SQL> alter database add supplemental log data; 

    Database altered. 

    从此以后,只要在闪回查询的查询窗口内,管理员就可以通过flashback_transaction _query表获得相关事务的撤销SQL。下面列举一个典型的闪回事务查询的使用方法。 

    场景:用户在一个事务中分别使用insert和update命令修改了hr.departments和hr.employees表,命令细节如下所示: 

    SQL> insert into hr.departments 
      2  (department_id,department_name,manager_id,location_id) 
      3  values (999,'SETI',100,1700); 

    1 row created. 

    SQL> update hr.employees set department_id=999 
      2  where employee_id=200; 

    1 row updated. 

    SQL> commit; 

    Commit complete. 

    该事务创建了一个新的999号部门,并且将200号员工指派入该新部门,该员工在此之前在10号部门上班。可惜这个事务是人为错误!且看如何利用闪回事务查询恢复原始状态。首先通过闪回版本查询获得该事务的XID,比如从错误的999号部门入手: 

    SQL> select 
      2  versions_xid,versions_startscn,department_id,department_name 
      3  from hr.departments 
      4  versions between timestamp minvalue and maxvalue 
      5  where department_id=999 
      6  order by 2 nulls first; 

    VERSIONS_XID     VERSIONS_STARTSCN DEPARTMENT_ID DEPARTMENT_NAME 
    --------------- ----------------- ------------- ------------------------------ 
    090010002B030000           1037789           999 SETI 

    然后使用结果中的事务号090010002B030000查询flashback_transaction_query表以获得撤销SQL: 

    SQL> select undo_sql 
      2  from flashback_transaction_query 
      3  where xid='090010002B030000'; 

    UNDO_SQL 
    -------------------------------------------------- 
    update "HR"."EMPLOYEES" set "DEPARTMENT_ID" = '10' 
    where ROWID = 'AAAR5pAAFAAAADLAAC'; 

    delete from "HR"."DEPARTMENTS" 
    where ROWID = 'AAAR5kAAFAAAACtAAA'; 

    2 rows selected. 

    结果得到了两句dml命令,如果遵循给出的ROWID不难发现撤销SQL试图将hr.employees表中200号员工的部门从999修改为10: 

    SQL> select employee_id,department_id 
      2  from hr.employees where rowid='AAAR5pAAFAAAADLAAC'; 

    EMPLOYEE_ID DEPARTMENT_ID 
    ----------- ------------- 
            200           999 

    并且试图删除999号部门: 

    SQL> select * from hr.departments where ROWID = 'AAAR5kAAFAAAACtAAA'; 

    DEPARTMENT_ID DEPARTMENT_NAME           MANAGER_ID    LOCATION_ID 
    ------------- ------------------------------ ---------- ----------- 
              999 SETI                                  100              1700 

    如果根据撤销SQL的手段处理,那不是正好将一开始的新部门创建及修改200号员工部门的insert和update命令抵消。笔者利用一个简单的PL/SQL匿名块来执行undo_sql: 

    SQL> begin 
      2  for rec in 
      3   (select undo_sql 
      4    from flashback_transaction_query 
      5    where xid='090010002B030000') 
      6  loop 
      7  if rec.undo_sql is not null then 
      8   execute immediate substr(rec.undo_sql,1,length(rec.undo_sql)-1); 
      9  end if; 
    10  end loop; 
    11  commit; 
    12  end; 
    13  / 

    PL/SQL procedure successfully completed. 

    检查一下效果,应该发现200号员工不在999号部门了: 

    SQL> select department_id from hr.employees where employee_id=200; 

    DEPARTMENT_ID 
    ------------- 
               10 

    并且999号部门也不存在了: 

    SQL> select department_name from hr.departments where department_id=999; 

    no rows selected 

    闪回事务查询可以将同一事务的所有撤销SQL列出,这是闪回查询做不到的,如有必要,管理员还能够执行对应一个事务的部分撤销SQL以一种破坏事务原子性的方式恢复一部分数据,如此行事正确与否完全取决于应用的逻辑。

    最后,因为ddl命令的撤销SQL包括对数据字典表的DML操作,并且人为地直接修改数据字典表是非常危险的,况且某些DDL操作不仅仅是对数据字典的DML操作,它们还涉及撤销SQL无法影响到的领域,所以不要指望通过直接执行撤销SQL恢复错误的ddl命令造成的影响。

  • 相关阅读:
    二叉树前中后、层次遍历
    二叉查找树-插入、查找某个值节点、查找前驱或后继、删除
    查找算法-二分、插值、斐波那契
    8个排序算法
    split函数实现
    strlen、strcmp、strcat、strlen、memmove
    thinkphp5 404 file_put_contents 无法打开流:权限被拒绝
    小程序之旅——第六站(模板首页)
    小程序之旅——第五站(登陆)
    小程序之旅——第三站(数据库用户权限设计)
  • 原文地址:https://www.cnblogs.com/chinajsks/p/5151091.html
Copyright © 2020-2023  润新知