侧边栏壁纸
博主头像
与晚风述往事博主等级

万般皆下品,唯有读书高。

  • 累计撰写 149 篇文章
  • 累计创建 29 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

Flashback Version Query

与晚风述往事
2021-12-29 / 0 评论 / 0 点赞 / 134 阅读 / 2,192 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2021-12-29,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

介绍

虽然我们可以使用闪回查询来查询事务提交之前的历史数据,但这种查询经常需要执行多次才能获得想要的结果。例如,在某个时间间隔内误运行了某个事务(事务已提交),后面我们发现脚本执行错了,想要查询出事务牵扯到的表中修改前的数据,去跟现在表中的数据进行对比,来知道执行事务前的时间。假设我们使用闪回查询去找的话,首先就需要随便查一个你认为可能会包含事务提交前的历史数据的时间点。如果这个时间正好是事务执行前的时间,那你就可以直接闪回表结束这个事情,还不会有任何责任,但这种可能性太低了。如果这个时间没有查到,就只能将时间改的更早些,然后反复修改和查询,直至找到事务执行前的时间。在这个反复查询的过程中,你需要修改多少次时间?要知道,对于数据库来说,1秒内就可能会执行多个事务,难道修改时间要精确到毫秒位?如果按毫秒位,又需要改多少次呢?那么,有没有一种方法能查询到一段时间间隔内的事务变更情况呢?

答案是有,它就是Flashback Version Query。

Oracle在每次事务执行时,就会将事务涉及到的旧值给移动到UNDO表空间中,待事务提交(commit)后,表中的行数据就会确定新的值,这种新值和旧值切换的过程,就是一个行的版本。当然,实际上的事务操作会更复杂,我只是为了让你们理解行版本,简述了下事务和UNDO表空间的关系。从这里可以看到,Flashback Version Query同样是使用了UNDO的特性,才能够让我们查询到一定时间段内行数据的版本。

Flashback Version Query提供了6个伪列,通过这些伪列,能够让我们查询到行版本的创建时间、过期时间、事务标识符和事务执行的操作类型。以下为伪列的说明:

伪列 描述 备注
VERSIONS_STARTSCN 创建行版本时的数据库变更号(SCN) 此值为NULL,则行版本是在之前创建的
VERSIONS_STARTTIME 创建行版本时的时间戳(TIMESTAMP) 此值为NULL,则行版本是在之前创建的
VERSIONS_ENDSCN 行版本过期时的数据库变更号(SCN) 此值为NULL,则行版本当前的,或者行数据执行了删除操作
VERSIONS_ENDTIME 行版本过期时的时间戳(TIMESTAMP) 此值为NULL,则行版本当前的,或者行数据执行了删除操作
VERSIONS_XID 创建行版本时的事务标识符
VERSIONS_OPERATION 事务对行中的数据进行的操作。I-插入;D-删除;U-更新 对于更新索引键时,Flashback Version Query将update操作视为DELETE+INSERT。

语法

闪回版本查询的语法非常简单,它结合了BETWEEN...AND子句。语法如下所示:

VERSIONS {BETWEEN {SCN | TIMESTAMP} start AND end}

说明:

  • SCN 使用SCN(数据库变更号)
  • TIMESTAMP 使用TIMESTAMP(时间戳)
  • start SCN或TIMESTAMP的开始值
  • end SCN或时间戳的结束值

先决条件

在执行闪回版本查询前,必须要满足以下条件:

  • 当前用户必须在执行闪回查询的表中具有FLASHBACK权限或者具有FLASHBACK ANY TABLE系统权限。
  • 当前用户必须在执行闪回查询的表中具有SELECT权限。

案例

TIMESTAMP闪回版本查询

还是这样一张表testa,数据如下图所示:
image.png
在进行表维护时,误执行了update语句,将表中NAME字段的全部数据改成了“赵六”。脚本如下图所示:
image.png
此时我们想使用闪回版本查询,查询在某个时间段内的行变更记录,可以这样写:

select 
  versions_startscn, versions_starttime,
  versions_endscn, versions_endtime,
  versions_xid, versions_operation, 
  id,name,sex
from testa
versions between timestamp
to_timestamp('2021-12-29 18:20:00','yyyy-mm-dd hh24:mi:ss')
and to_timestamp('2021-12-29 18:23:00','yyyy-mm-dd hh24:mi:ss');

image.png
从上图可以看到,testa表有两行被执行了更新,更新时间是“2021-12-29 18:21:03”。我这里是为了让你们更好的理解这些伪列的使用,所以在查询时全部都查出来了。在生产环境中,建议根据条件去写闪回版本查询语句,避免因行版本数据量太多导致的性能问题。

我这里再写一个用ID字段作为条件去查询“ID=1”的闪回版本查询的语句。

select 
  versions_startscn, versions_starttime,
  versions_endscn, versions_endtime,
  versions_xid, versions_operation, 
  id,name,sex
from testa
versions between timestamp
to_timestamp('2021-12-29 18:20:00','yyyy-mm-dd hh24:mi:ss')
and to_timestamp('2021-12-29 18:23:00','yyyy-mm-dd hh24:mi:ss')
where id=1;

image.png

0

评论区