0
点赞
收藏
分享

微信扫一扫

Oracle Flashback技术总结


Flashback 技术是以Undo segment中的内容为基础的, 因此受限于UNDO_RETENTON参数。要使用flashback 的特性,必须启用自动撤销管理表空间。

在Oracle 10g中, Flash back家族分为以下成员: Flashback Database, Flashback Drop,Flashback Query(分Flashback Query,Flashback Version Query, Flashback Transaction Query三种)和Flashback Table。



Query

Flashback 是ORACLE 自9i 就开始提供的一项特性,在9i 中利用oracle 查询多版本一致的特点,实现从回滚段中读取表一定时间内操作过的数据,可用来进行数据比对,或者修正意外提交造成的错误数据,该项特性也被称为Flashback Query。

一、Flashback Query
正如前言中所提,Flashback Query 是利用多版本读一致性的特性从UNDO 表空间读取操作前的记录数据!

什么是多版本读一致性
Oracle 采用了一种非常优秀的设计,通过undo 数据来确保写不堵塞读,简单的讲,不同的事务在写数据时,会将数据的前映像写入undo 表空间,这样如果同时有其它事务查询该表数据,则可以通过undo 表空间中数据的前映像来构造所需的完整记录集,而不需要等待写入的事务提交或回滚。

flashback query 有多种方式构建查询记录集,记录集的选择范围可以基于时间或基于scn,甚至可以同时查询出记录在undo 表空间中不同事务时的前映象。用法与标准查询非常类似,要通过flashback query 查询undo 中的撤销数据,最简单的方式只需要在标准查询语句的表名后面跟上as oftimestamp(基于时间)或as of scn(基于scn)即可。as of timestamp|scn 的语法是自9iR2 后才开始提供支持。

1、As of timestamp 的示例:


SQL>  alter session set nls_date_format='YYYY-MM-DD hh24:mi:ss';

会话已更改。

SQL> select sysdate from dual;

SYSDATE

-------------------

2009-10-15 19:04:16


SQL> select * from A;


       ID

       ----------

        2

        1

        3

        4


模拟用户误操作,删除数据

SQL> delete from A;

已删除4行。

SQL> commit;

提交完成。

SQL> select * from A;

未选定行

查看删除之前的状态:
假设当前距离删除数据已经有5 分钟左右的话:
SQL> select * from A as of timestamp sysdate-5/1440;


       ID

       ----------

        2

        1

        3

        4

或者:

SQL>select * from A as of timestampto_timestamp('2009-10-15 19:04:16','YYYY-MM-DD hh24:mi:ss');


       ID

       ----------

        2

        1

        3

        4

Flashback Query恢复之前的数据:

SQL>Insert into Aselect * from Aas of timestampto_timestamp('2009-10-15 19:04:16','YYYY-MM-DD hh24:mi:ss');

已创建4行。

SQL> COMMIT;


提交完成。


SQL> select * from A;


       ID

       ----------

        2

        1

        3

        4

如上述示例中所表示的,as of timestamp 的确非常易用,但是在某些情况下,我们建议使用as of scn 的方式执行flashback query,比如需要对多个相互有主外键约束的表进行恢复时,如果使用as of timestamp 的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过scn 方式则能够确保记录的约束一致性。

2. As of scn 示例


SCN:
SELECT dbms_flashback.get_system_change_number FROM dual;
SELECT CURRENT_SCN FROM V$DATABASE;

SQL> SELECT CURRENT_SCN FROM V$DATABASE;

CURRENT_SCN

-----------

1095782


删除数据:
SQL> delete from A;

已删除4行。

SQL> commit;

提交完成。



查看删除之前的状态:

SQL> select * from A as of scn 1095782;

       ID

    ----------

        2

        1

        3

        4


Flashback Query恢复之前的数据:

SQL> insert into A select * from A as of scn 1095782;

已创建4行。

SQL> commit;

提交完成。

SQL> select * from A;

       ID

       ----------

        2

        1

        3

        4


Oracle 在内部都是使用scn,即使你指定的是as of timestamp,oracle 也会将其转换成scn,系统时间标记与scn 之间存在一张表,即SYS 下的SMON_SCN_TIME

SQL> desc sys.smon_scn_time

名称                       是否为空? 类型

----------------------------------------- --------   ---------------------------


THREAD                               NUMBER

TIME_MP                              NUMBER

TIME_DP                              DATE

SCN_WRP                             NUMBER

SCN_BAS                              NUMBER

NUM_MAPPINGS                       NUMBER

TIM_SCN_MAP                         RAW(1200)

SCN                                   NUMBER

ORIG_THREAD                         NUMBER

每隔5 分钟,系统产生一次系统时间标记与scn 的匹配并存入sys.smon_scn_time 表,该表中记录了最近1440个系统时间标记与scn 的匹配记录,由于该表只维护了最近的1440 条记录,因此如果使用as of timestamp 的方式则只能flashback 最近5 天内的数据(假设系统是在持续不断运行并无中断或关机重启之类操作的话)。

scn 的每5 分钟匹配一次这句话,举个例子,比如scn:339988,339989 分别匹配08-05-3013:52:00 和2008-13:57:00,则当你通过as of timestamp 查询08-05-30 13:52:00 或08-05-30 13:56:59 这段时间点
内的时间时,oracle 都会将其匹配为scn:339988 到undo 表空间中查找,也就说在这个时间内,不管你指定的时间点是什么,查询返回的都将是08-05-30 13:52:00 这个时刻的数据。

SCN 和 timestamp 之间的对应关系:
selectscn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')fromsys.smon_scn_time;



version Query


相对于Flashback Query 只能看到某一点的对象状态, Oracle 10g引入的Flashback Version Query可以看到过去某个时间段内,记录是如何发生变化的。 根据这个历史,DBA就可以快速的判断数据是在什么时点发生了错误,进而恢复到之前的状态。


先看一个伪列 ORA_ROWSCN.  所谓的伪列,就是假的,不存在的数据列,用户创建表时虽然没有指定,但是Oracle为了维护而添加的一些内部字段,这些字段可以像普通文件那样的使用。


最熟悉的伪列就是 ROWID, 它相当于一个指针,指向记录在磁盘上的位置。ORA_ROWSCN 是Oracle 10g 新增的,暂且把它看作是记录最后一次被修改时的SCN。 Flashback Version Query 就是通过这个伪列来跟踪出记录的变化历史。


举个例子:

SQL> select * from A;

       ID

       ----------

        2

        1

        3

        4

SQL> insert into A values(5);

已创建 1 行。

SQL> select * from A;

       ID

       ----------

        2

        1

        3

        4

        5


SQL> commit;

提交完成。

SQL> select ora_rowscn, id from A;

ORA_ROWSCN       ID

----------             ----------

  1098443          2

  1098443          1

  1098443          3

  1098443          4

  1098443          5


获取更多的历史信息

SQL>Select versions_xid,versions_startscn,versions_endscn,

  DECODE(versions_operation,'I','Insert','U','Update','D','Delete', 'Original') "Operation", id from A versions between scn minvalue and maxvalue;

或者

SQL>select xid,commit_scn,commit_timestamp,operation,undo_sql

from flashback_transaction_query q where q.xid in(select versions_xid from Bversions between scn 413946 and 413959);


VERSIONS_XID     VERSIONS_STARTSCN VERSIONS_ENDSCN Operatio    ID

---------------- ----------------- --------------- -------- ----------

05001A0054020000           1099482                 Update            3

05001A0054020000           1099482                 Delete            3

05001A0054020000           1099482                 Delete            2

05001A0054020000           1099482                 Delete            1

0400150005020000           1098443                 Insert           5

下面我们来讲下伪列, Flashback Version Query 技术其实有很多伪列,但是ORA_ROWSCN是最重要。它记录的是最后一次被修改时的SCN, 注意是被提交的修改。如果没有提交,这个伪列不会发生变化。



缺省是数据块级别的,也就是一个数据块内的所有记录都是一个ORA_ROWSCN,数据块内任意一条记录被修改,这个数据库块内的所有记录的ORA_ROWSCN都会同时改变。上例的查询结果以证明。


rowdependencies, 可以改变这种缺省行为,使用这个关键字后,每条记录都有自己的ORA_ROWSCN。 


举例:

create table B (id number(2)) rowdependencies;

表已创建。

insert into B values(1);

1 行。

insert into B values(2);

1 行。

insert into B values(3);

1 行。

commit;

提交完成。

select ora_rowscn, id from B;

        ID

----------

  1100560          1

  1100560          2

  1100560          3


SCN一样,一定很奇怪,这正好说明是最后一次被修改时的SCN,如果没有提交,是不会变的,我们重做一下就清楚了。


analyze table B compute statistics;

表已分析。

select ora_rowscn, id from B;

        ID

----------

  1100560          1

  1100560          2

  1100560          3


delete from B;

4行。

select ora_rowscn, id from B;

未选定行

insert into B values(1);

1 行。

commit;

提交完成。

insert into B values(2);

1 行。

commit;

提交完成。

select ora_rowscn, id from B;

        ID

----------

  1100723          1

  1100729          2













Transaction Query

Transaction Query也是使用UNDO信息来实现。利用这个功能可以查看某个事务执行的所有变化,它需要访问flashback_transaction_query 视图,这个视图的XID列代表事务ID,利用这个ID可以区分特定事务发生的所有数据变化。

示例:

SQL> insert into B values(3);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select * from B;


       ID

      ----------

        1

        2

        3


查看视图,每个事务都对应相同的XID


SQL>Select xid,operation,commit_scn,undo_sql from flashback_transaction_query where xid in (

Select versions_xid from B versions between scn minvalue and maxvalue);

或者

SQL>select xid,commit_scn,commit_timestamp,operation,undo_sql

from flashback_transaction_query q where q.xid in(select versions_xid from Bversions between scn 413946 and 413959);


XID              OPERATION                        COMMIT_SCN

---------------- -------------------------------- ----------

UNDO_SQL

--------------------------------------------------------------------------------


03001C006A020000 DELETE                              1100723

insert into "SYS"."B"("ID") values ('4');


03001C006A020000 DELETE                              1100723

insert into "SYS"."B"("ID") values ('3');


03001C006A020000 DELETE                              1100723

insert into "SYS"."B"("ID") values ('2');



Table

SYS用户不支持闪回,这点前面已经说明过。


Flashback Table也是使用UNDO tablespace的内容来实现对数据的回退。该命令相对简单,输入:flashback table table_name to scn(to timestamp) 即可。


注意:如果想要对表进行flashback,必须允许表的row movement.

Alter table table_name row movement;



要查看某表是否启用row movement,可以到user_tables 中查询(或all_tables,dba_tables),

例如:
SQL> select row_movement from user_tables where table_name='C';
ROW_MOVE
--------
ENABLED

要启用或禁止某表row movement,可以通过下列语句:

--启用
JSSWEB> ALTER TABLE table_name ENABLE ROW MOVEMENT;
表已更改。
--禁止
JSSWEB> ALTER TABLE table_nameDISABLE ROW MOVEMENT;
表已更改。


举例:


SQL> create table C (id number(2));

表已创建。

SQL> insert into C values(1);

已创建 1 行。

SQL> insert into C values(2);

已创建 1 行。

SQL> commit;

提交完成。

SQL> select * from c;

       ID

----------

        1

        2


SQL> alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss";

会话已更改。

SQL> select sysdate from dual;

SYSDATE

-------------------

2009-10-15 21:17:47

SQL> select current_scn from v$database;


CURRENT_SCN

-----------

     1103864


删除数据并恢复

SQL> delete from C;

已删除2行。

SQL> commit;

提交完成。

SQL> alter table c enable row movement;

表已更改。

SQL> flashback table c to scn  1103864;

闪回完成。

或者:

SQL> flashback table c to timestamp to_timestamp('2009-10-15 21:17:47','yyyy-mm-

dd hh24:mi:ss');


SQL> select * from c;

       ID

----------

        1

        2


Flashback table 命令支持同时操作多个表,表名中间以逗号分隔即可,如果你执行一条flashback table命令时同时指定了多个表,要记住单个flashback table 是在同一个事务中,因此这些表的恢复操作要么都成功,要么都失败。

如:

flashback table a,b ,c to scn 1103864;



一些注意事项

1. 基于undo 的表恢复,需要注意DDL 操作的影响
第三个就是修改并提交过数据之后,对表做过DDL 操作,包括:
drop/modify 列, move 表, drop 分区(如果有的话), truncate table/partition,这些操作会另undo 表空间中的撤销数据失效,对于执行过这些操作的表应用flashback query 会触发ORA-01466 错误。另外一些表结构修改语句虽然并不会影响到undo 表空间中的撤销记录,但有可能因表结构修改导致undo 中重做记录无法应用的情况,比如对于增加了约束,而flashback query 查询出的undo 记录已经不符合新建的约束条件,这个时候直接恢复显然不可能成功,你要么暂时disable 约束,要么通过适当逻辑,对要恢复的数据进行处理之后,再执行恢复。
另外,flashback query 对v$tables,x$tables 等动态性能视图无效,不过对于dba_*,all_*,user_*等数据字典是有效的。同时该特性也完全支持访问远端数据库,比如select * fromtbl@dblink as of scn 360;的形式。 



2. 基于undo 的表恢复,flashback table 实际上做的也是dml 操作(会在被操作的表上加dml 锁),因此还需要注意triggers 对其的影响,默认情况下,flashback table to scn/timestamp 在执行时会自动disable 掉与其操作表相差的triggers,如果你希望在此期间trigger 能够继续发挥做用,可以在flashback table 后附加
ENABLE TRIGGERS 子句。



补充:


什么是Automatic Undo Management( 自动撤销管理表空间)
提到自动撤销管理表空间,就不得不提手动管理的回滚段。在9i 之前,回滚段的管理和监控是需要dba手工介入的,创建合适的回滚段是件非常耗费dba 精力的事情,你可能需要不断关注oracle 运行状况很长一阵子时间后,通过不断的调整才能基本确认一段时期内回滚段的大小,一旦回滚段创建的不合适,就极有可能引起性能问题甚至错误,比如ora-1555 就是典型的回滚段设置不合适触发的。
9i 之后呢(含9i),oracle 为了清晰它的整个概念,取消了回滚段这个说法(实际上并未取消回滚段),而完全以undo 来代替,这也它正好与redo 相对应,一个重做,一个撤销。回滚段可以不再由dba 手工介入,而是完全由它自己在运行时自动分配,这在一定程度上即解放了dba,也确实起到了提高性能的作用,比如采用自动管理表空间就可以最大程序的降低ora-1555发生的机率(注意是降低,不是避免,我们不可能创建一个无限大的回滚段,ora-1555 也并不完全是回滚段造成的,关于ora-1555 的问题这里就不深入讨论了,互联网上已经有太多文章描述和介绍该问题及解决方案)

是否起用自动管理的撤销表空间由二个初始化参数决定:
UNDO_MANAGEMENT:值为AUTO 表示使用了自动撤销管理表空间,MANUAL 则表示手动管理
UNDO_TABLESPACE:当UNDO_MANAGEMENT 值为AUTO 时,该参数用来指定当前的undo 表空间名称。
undo 表空间的大小,直接影响到flashback query 的查询能力,因为多版本查询所依赖的undo 数据都存储在undo 表空间中,该表空间越大,所能够存储的undo 数据自然也越多,如果该表空间可用空间非常小,别说flashback 了,恐怕正常查询都有可能触发ora-1555 吧。


初始化参数UNDO_RETENTION
该参数用来指定undo 记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改通常默认是900 秒,也就是15 分钟。
一定要注意,undo_retention 只是指定undo 数据的过期时间,并不是说,undo 中的数据一定会在undo表空间中保存15 分钟,比如说刚一个新事务开始的时候,如果undo 表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建
一个自动管理的undo 表空间时,还要注意其空间大小,要尽可能保证undo 表空间有足够的存储空间。
同时还要注意,也并不是说,undo_retention 中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback 特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention 参数的值并不会影响到你,哪怕你设置成1,只要没有事务去覆盖undo 数据,它就会持续有效。因此呢,这里还是那句话,要注意undo 表空间的大小,保证其有足够的存储空间。

只有在一种情况下,undo 表空间能够确保undo 中的数据在undo_retention 指定时间过期前一定有效,就是为undo 表空间指定Retention Guarantee,指定之后,oracle 对于undo 表空间中未过期的undo 数据不会覆盖,

例如:
SQL> Alter tablespace undotbs1 retention guarantee;
如果想禁止undo 表空间retention guarantee,

例如:
SQL> Alter tablespace undotbs1 retention noguarantee;

举报

相关推荐

0 条评论