Oracle Flashback闪回
Flashback Database功能非常类似与RMAN的不完全恢复,它可以把整个数据库回退到过去的某个时点的状态,这个功能依赖于 Flashback log日志。比RMAN更快速和高效。因此Flashback Database可以看作是不完全恢复的替代技术。
Flashback是ORACLE自9i就开始提供的一项特性,在9i中利用oracle查询多版本一致的特点,实现从回滚段中读取表一定时间内操作过的数据,可用来进行数据比对,或者修正意外提交造成的错误数据,该项特性也被称为Flashback Query。
什么是多版本读一致性
Oracle采用了一种非常优秀的设计,通过undo数据来确保写不堵塞读,简单的讲,
不同的事务在写数据时,会将数据的前映像写入undo表空间,这样如果同时有其它事务查询该表数据,则可以通过undo表空间中数据的前映像来构造所需的完整记录集,而不需要等待写入的事务提交或回滚。
flashback query有多种方式构建查询记录集,记录集的选择范围可以基于时间或基于scn,甚至可以同时查询出记录在undo表空间中不同事务时的前映象。用法与标准查询非常类似,要通过flashback
query查询undo中的撤销数据,最简单的方式只需要在标准查询语句的表名后面跟上as
of timestamp(基于时间)或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;
模拟用户误操作,删除数据
SQL> delete from A;
已删除4行。
SQL> commit;
提交完成。
SQL> select * from A;
未选定行
查看删除之前的状态:
假设当前距离删除数据已经有5分钟左右的话:
SQL> select * from A as of timestamp sysdate-5/1440;
或者:
SQL>select * from A as of timestamp to_timestamp('2009-10-15
19:04:16','YYYY-MM-DD hh24:mi:ss');
用Flashback
Query恢复之前的数据:
SQL>Insert into A select * from A as of timestamp to_timestamp('2009-10-15
19:04:16','YYYY-MM-DD hh24:mi:ss');
已创建4行。
SQL> COMMIT;
提交完成。
SQL> select * from A;
如上述示例中所表示的,as
of timestamp 的确非常易用,但是在某些情况下,我们建议使用as
of scn的方式执行flashback
query,比如需要对多个相互有主外键约束的表进行恢复时,如果使用as
of timestamp的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过scn方式则能够确保记录的约束一致性。
-
As of scn
查看 SCN:
SQL>SELECT dbms_flashback.get_system_change_number FROM dual;
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;
用Flashback Query恢复之前的数据:
SQL> insert into A select * from A as of scn 1095782;
已创建4行。
SQL> commit;
提交完成。
SQL> select * from A;
事实上,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之间的对应关系:
select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')from sys.smon_scn_time; -
伪列 ORA_ROWSCN
所谓的伪列,就是假的,不存在的数据列,用户创建表时虽然没有指定,但是Oracle
为了维护而添加的一些内部字段,这些字段可以像普通文件那样的使用。
最熟悉的伪列就是ROWID,它相当于一个指针,指向记录在磁盘上的位置。
ORA_ROWSCN是Oracle 10g新增的,暂且把它看作是记录最后一次被修改时的SCN。Flashback Version Query 就是通过这个伪列来跟踪出记录的变化历史。
举个例子:
SQL> select * from A;
SQL> insert into A values(5);
已创建1行。
SQL> select * from A;
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 B
versions 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,数据块内任意一条记录被修改,这个数据库块内的所有记录的
ORA_ROWSCN都会同时改变。上例的查询结果以证明。
不过我们可以在建表时使用关键字rowdependencies,可以改变这种缺省行为,使用这个关键字后,每条记录都有自己的 ORA_ROWSCN。
举例:
SQL> create table B (id number(2)) rowdependencies;
表已创建。
SQL> insert into B values(1);
已创建1行。
SQL> insert into B values(2);
已创建1行。
SQL> insert into B values(3);
已创建1行。
SQL> commit;
提交完成。SQL> select ora_rowscn, id from B;
ORA_ROWSCN ID
---------- ----------
1100560 1
1100560 2
1100560 3
此处SCN一样,一定很奇怪,这正好说明是最后一次被修改时的SCN,如果没有提交,是
不会变的,我们重做一下就清楚了。
SQL> analyze table B compute statistics;
表已分析。
SQL> select ora_rowscn, id from B;
ORA_ROWSCN ID
---------- ----------
1100560 1
1100560 2
1100560 3
SQL> delete from B;
已删除4行。
SQL> select ora_rowscn, id from B;
未选定行
SQL> insert into B values(1);
已创建1行。
SQL> commit;
提交完成。
SQL> insert into B values(2);
已创建1行。
SQL> commit;
提交完成。
SQL> select ora_rowscn, id from B;
ORA_ROWSCN ID
---------- ----------
1100723 1
1100729 2
二、闪回事物(Flashback
Transaction Query)
Oracle11g
闪回事务查询就是对过去某段时间内所完成的事务的查询和撤销,通过闪回事物分析,可以识别在一个特定的时间段内所发生的所有变化,也可以对数据库表进行事物级恢复。
前面提到可以审计一个事务到底做了什么,现在可以获得事务的历史操作进行撤销。
举例:
根据上一例查询某段时间内的操作发生情况:
1、
SQL>select id,name,versions_operation,versions_xid,versions_starttime from test
versions between timestamp minvalue and maxvalue order by id;
2、
根据 XID
对
flashback_transaction_query
进行查询
SQL>select table_name,table_owner,undo_sql from flashback_transaction_query where
xid=‘„’
3、
运行上面找出的 sql
语句,即可将以前删除的数据恢复回来。
Flashback Transaction Query
也是使用
UNDO
信息来实现。利用这个功能可以查看某个事务执行的所有变化,它需要访问
flashback_transaction_query
视图,这个视图的
XID
列代表事务
ID,利用这个
ID
可以区分特定事务发生的所有数据变化。
示例:
SQL> insert into B values(3);
已创建
1
行。
SQL> commit;
提交完成。
SQL> select * from B;
查看视图,每个事务都对应相同的
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 B
versions 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');
-
闪回丢弃(Flashback Drop )
System,sys用户删除的表不进入回收站,普通用户删除入回收站。
在 DROP 表前索引已经被删除从 Oracle 10g 开始, 每个表空间都会有一个叫作回收站的逻辑区域,当用户执行 drop 命令时, 被删除的表和表的关联对象( 包括索引, 约束,触发器,LOB 段,LOB index 段) 不会被物理删除, 这些对象先转移到回收站中,这就给用户提供了一个恢复的可能。
闪回丢弃是指将被丢弃的数据库对象及其相依对象的拷贝保存在回收站中,以便在必要
时能够及时恢复这些对象。在回收站被清空以前,被丢弃的对象并没有从数据库中删除,这就使得数据库能够恢复被意外或误操作而删除的表。
回收站:是所有丢弃表及其相依对象的逻辑存储容器。 Oracle 回收站将用户所做的
DROP 语句操作记录在一个系统表里,即将被删除的对象写到一个数据字典中,当不再需要被删除对象时,可以使用 PURGE 命令对回收站空间进行清除。
举例说明:
SQL>drop table test;
查询
user_recyclebin
回收站
SQL>select object_name,original_name from user_recyclebin;
利用回收站中的记录,使用
flashback
恢复表
test
SQL>flashback table test to before drop;
回收站空间清除:
可以使用
PURGE
命令清除回收站对象从而释放空间,有以下几种方式:
1、使用
PURGE TABLE original_table_name;
这里的
original_table_name
表示未
drop
以前的名称
2、使用
PURGE TABLE recyclebin_object_name;
这里的
recyclebin_object_name
表示回
收站中的对象名称
3、使用
PURGE TABLESPACE tablespace_name
从指定的表空间中清除所有的丢弃对象
4、使用
PURGE TABLESPACE tablespace_name USER user_name
从回收站中清除属于某个特定用户的所有丢弃对象。
5、DROP
USER user_name cascade 直接删除指定用户及其所属的全部对象,也就是说,DROP
USER 命令会绕过回收站进行直接删除。
6、使用
PURGE RECYCLEBIN
命令清除用户自己的回收站
7、PURGE
DBA_RECYCLEBIN 从所有用户的回收站清除所有对象
局限性:
闪回丢弃对于如下表不生效:
存放在
SYSTEM
表空间上的表;
使用精细审计或虚拟私有数据库
建在字典管理表空间上的表
已经被手工清除或自动清除的表(即表被
DROP
后使用了
PURGE
操作)
如下依赖对象不受保护:
位图索引
物化视图日志
外键一致性约束
初始化参数
recyclebin
用于控制是否启用
recyclebin
功能,缺省是
ON,可以使用
OFF
关闭。
SQL> show parameter recycle
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_recycle string
db_recycle_cache_size big integer 0
recyclebin string on
禁用该功能:
SQL> alter system set recyclebin=off;
SQL> alter session set recyclebin=off;
禁用后删除的对象将直接删除,不会写到
Recycle
中,当然在删除时,指定
purge
参数,
表也将直接删除,不会写到
recyclebin
中。
SQL> drop table name purge;
查看
recyclebin
中的对象列表:
SQL> select * from A;
SQL> drop table A;
表已删除。
SQL> show recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ----------------------------- ------------ -------------------
A BIN$RWXQQcTPRde0ws4h9ewJcg==$0 TABLE 2009-10-15:12:44:33
查看
recyclebin
中对象:
SQL> select original_name,object_name from recyclebin;
ORIGINAL_NAME OBJECT_NAME
-------------------------------- ------------------------------
A BIN$RWXQQcTPRde0ws4h9ewJcg==$0
查看
recyblebin
对象里的内容:
SQL> select * from "BIN$RWXQQcTPRde0ws4h9ewJcg==$0";
表空间的
Recycle Bin
区域只是一个逻辑区域,而不是从表空间上物理的划出一块区域固定用于回收站,因此
Recycle Bin
是和普通对象共用表空间的存储区域,或者说是
RecycleBin
的对象要和普通对象抢夺存储空间。当发生空间不够时,Oracle
会按照先入先出的顺序覆盖
Recycle Bin
中的对象。也可以手动的删除
Recycle Bin
占用的空间。