love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

Phone:18180207355 提供专业Oracle/MySQL/PostgreSQL数据恢复、性能优化、迁移升级、紧急救援等服务

about flashback_transaction_query

本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

本文链接地址: about flashback_transaction_query

前几天某大师提醒我说了,我以前一篇文档flashback_transaction_query 查询慢的问题 有点问题。 现在回想一下,确实不太对,
虽然以前的方法也是一种处理方法然而有点偏离方向了。首先我们来看一下试图的定义:
—definition

可以看到,该试图的本质是访问x$ktuqqry. 那么这个试图是干什么的呢?显然是闪回事务查询的时候需要用到的东西,而且访问的
的数据是来自undo.下面我们随便从该试图中取一个xid来重现一下:

可以发现访问很慢,为什么呢 ?我们先来看下执行计划:

可以发现,id 2的地方走了table full scan,也就是全表扫描. 以前没用注意的一个细节.大家注意看下面的filter部分,很明显是
进行了隐式转换,以至于走full table scan了。 这里用的rwatohex进行了转换,那么如果使用hextoraw进行反向转一下呢 ?

可以发现,这样的话,速度非常之快. 原来以前一直犯了一个错误,误导了不少人啊. 自我批评下.

到这里可能很多人以为这篇文章到此结束了,是吗? 实际上,故事才刚刚开始….

或许有些网友已经想到了,这个试图是干吗的?闪回查询,那么如何去定位到这个xid号呢 ?

假如1分钟之前某人删除了一条记录,那么我们要通过闪回事务去恢复这条数据,如何去进行恢复呢 ? 我们可以直接通过
查询该试图来获取undo_sql 进行恢复,其关键是如何获得该操作的XID ?

+++++++++ 方法1 闪回查询 +++++++++

这里的versions_xid,就表示该事务的xid,其中versions_operaition表示操作类型:D表示delete,I表示insert,U表示update.
通过该xid,我们可以直接查询undo_sql,然后执行该sql文本就可以将该条删除的数据恢复回来,如下查询:

实际上我们利用该视图来定位undo_sql,关键的地方是定位到具体的xid。

那么针对一个表的操作,可能有很多,我们如何去定位呢? 其实完全可以结合scn和operation以及table_name,table_owner来缩小范围.
类似如下的操作:
SQL> select XID,OPERATION,UNDO_CHANGE#,TABLE_NAME,TABLE_OWNER,ROW_ID
2 from FLASHBACK_TRANSACTION_QUERY where table_name=’TEST_UNDO1′ and table_owner=’ROGER’ and row_id >’AAAPJyAACAAAR/vABN’;

当然如果由于该x$表仅仅在xid字段上存在索引,索引这样查询,可能会比较慢.如下:

显然这里我们根据判断知道第1条信息是我们所需要的.

++++++++++ 方法2 根据rowid 边界定位xid ++++++++++

除了利用闪回的方法,是否还有其他方法呢?假如我删除掉一个范围的数据,例如:

不考虑边界的问题,某条数据通常会跟其他数据存在同一block中,所以根据删除的数据范围,定位到block 号:

此时roger_ora_14279.trc 内容如下:

从上面2个block的dump可以看出xid 信息如下:
0x000c.011.0000038f
0x000c.011.0000038f 虽然涉及到多个block的操作,但是仍然是同一个事务.所以这里xid的一个值.

将其转换为FLASHBACK_TRANSACTION_QUERY.xid的格式,其长度为16位,不足的部分用0补齐.

0c00 1100 8f030000 即使xid=0c0011008f030000

获取到xid后,直接生成恢复的脚本即可,如下:

++++++++++++ 方法 3 使用bbed 定位XID
如果操作的数据刚好都在一个block,即一共block内数据被全部删除,那么无法通过第2种的边界方法去定位.
首先我这里用一个例子来展示,将一个block的数据全部delete掉,但是需要先定位到该block的数据范围:

从上面可以看出,该block内的数据范围在object_id 459和546之间,将其全部delete掉:

通过bbed来获取xid,首先观察操作前后的itl信息变化,如下:

—-delete操作之后

在不考虑ITL被覆盖的情况下,显然该事务所使用的itl应该是最后一个.

从这里我们可以看出对应的事务XID为:0x0014 0003 0000039d

转换为FLASHBACK_TRANSACTION_QUERY试图的标准xid格式为:140003009d030000

获得到xid后,我们就可以直接查询获得undo_sql文本了,如下:

我们可以发现,刚好82条记录,也就是该block中被删除的所有记录,一共82条.

备注: 本文不考虑block itl被覆盖的情况,如果block itl被覆盖,那么情况更为复制,大家可以一起研究下.

One Response to “about flashback_transaction_query”

  1. about flashback_transaction_query - 数据库 - 开发者 Says:

    […] 详见原文博客链接地址:about flashback_transaction_query 本文链接: about flashback_transaction_query 版权所有: 非特殊声明均为本站原创文章,转载请注明出处:开发者 订阅更新: 您可以通过RSS订阅我们的内容更新 […]

Leave a Reply

You must be logged in to post a comment.