Oracle Flashback(闪回) 详解
通常我们对数据库进行了误操作时, 需要把数据库Rollback到之前的版本。一个常用的方法就是使用日志来进行数据库恢复. 这个方法虽然强大有效, 但是花费时间等成本高。
例如当我们只是误提交了1个delete语句, 丢失了删除行的数据时, 如果我们执行数据库恢复的话, 就需要断开当前所有server processes, 甚至需要关闭数据库,相当于暂停了所有的生产活动。
而且使用日志恢复的话, 还往往需要相当长的时间(取决于备份文件的复制时间和日志的应用时间)
一, 什么是Flashback
除了上面所说的日志恢复机制.
Oracle提供了另1个快速数据库恢复机制, 就是Flashback.
1.1 Flashback的简单原理
Oracle会将数据库数据的每1个改动记录在日志文件中, 所以理论上依靠日志文件, 是能将数据库回滚到任何一个时间点的.
而Flashback的机制有点类似与回收站, 会把数据库改动前的镜像放到undo表空间中.
如果用户要rollback1个数据库对象, 只需要找到undo表空间中对应的Undo数据即可.
1.2 Flashback的优点
很明显, Flashback并不依赖于日志文件, 只需Undo表空间中undo数据即可发挥作用.
所以Flashback可以满足用户逻辑错误的快速恢复.
所以优点如下:
1. 快速
2. 在线恢复, 无需关闭数据库
3. 操作简单.便捷.
1.3 Flashback的缺点
Flashback缺点同样明显.
1. 只适用于用户逻辑错误, 所谓逻辑错误就是用户对数据的唔操作, 例如误删除一些数据行等等.
而对于数据文件的损坏则无能为力(只能通过日志恢复).
2. undo表空间的容量有限, 旧的undo数据有可能会被新的数据覆盖, 所以Flashback一般只适用于短时间内的恢复, 对于一段相当时间前的误操作, 很可能因为undo数据被覆盖而恢复失败.
1.4 启用Flashback功能
为了正常使用Flashback功能, 通常我们要打开补充日志(Supplemental logging)功能, oracle 11g数据库默认情况下补充日志是关闭的.
补充日志也分成几个级别,最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(unique),支持外键(foreign key)。包括LONG,LOB,LONG RAW及集合等字段类型均无法利用补全日志.
例如:
使用如下命令来打开最小补全日志.
alter database add supplemental log data;
使用如下命令来查看补全日志是否被打开.
SQL> select supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui, supplemental_log_data_fk, supplemental_log_data_all from v$database;
SUPPLEME SUP SUP SUP SUP
-------- --- --- --- ---
YES NO NO NO NO
使用Flashback 需要当前用户具有select any transaction 权限.
可以用dba账号执行:
grant select any transaction to xxx;
来获得这个权限.
1.5 关于flashback 的undo设置, Automatic Undo Management
SQL> show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- -----------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
1.5.1 Parameter UNDO_MANAGEMENT
1.5.2 Parameter UNDO_TABLESPACE
1.5.3 Parameter UNDO_RETENTION
只有1中情况例外, 当为undo tablespace 启用retention guarantee.
oracle 可以保证undo 数据在undo_retention指定的时间内一定存在(不能被其他undo数据覆盖).
启用guarantee:
Alter tablespace undotbs1 retention guarantee;
禁用guarantee:
Alter tablespace undotbs1 retention noguarantee;
启用这个特性能保证undo数据在undo tablespace 内的存在时间, 但是也有代价的.
假如表空间已满, 而且不允许旧的undo数据被新数据覆盖. 为了保证多版本的读一致性(详见本文第五节), 新的事务的
操作就会受影响了.
所以还是那几句话: the size of undo tablespace is very importance.
二, Flashback的级别和成员
2.1 Flashback的级别
Flashback可以分为三个级别:
1.Database Level
数据库级别的flashback允许将数据库恢复到某个时间点, 当误删除1个user或误truncate 1张表是适用数据库级别的flashback.
2.Table level
表级flashback可以将1个table回滚到某个时间点或者某个SCN号, 也可以闪回通过Drop命令删除的表.
3.Transaction level
事务级闪回会记录用户事务的每个DML操作, 并给出相应rollback的DML指令. 比如insert操作的rollback指令就是delete.
一般用于rollback 用户已经commit的误操作事务.
而根据误操作对于数据的影响.
用户可以选择执行flashback操作或者flashback查询.(flashback query)
所谓falshback查询就是查询数据被DML操作的历史记录(一般就是commit的记录), 然后在此基础上确定是否进行flashback操作.
2.2 Flashback的成员
Flashback可以分为如下成员:
1.Flashback Database
2.Flashback Drop
3.Flashback Query
-- Flashback Query
-- Flashback Version Query
-- Flashback Transaction Query
4.Flashback Table
5.Flashback Data Archive
三, Flashback Version Query
首先我们介绍的第一个成员叫flashback 版本查询.
所谓Version是指数据库中每次因为事务commit 而产生的数据行变化情况, 每一次变化就是1个版本.
这里需要强调的是这里变化是因为事务commit 产生的变化, 未commit的事务引起的变化不会被Flashback Version query 检索出来.
Flash Version Query 查询使用的undo 表空间的Undo 数据, 一旦undo数据因为undo segment的空间压力被清除, 则产生无法flashback的情况.
通过versions between 关键字可以查询制定时间(timestamp) or 版本(scn号)区间内的的不同修改版本.
语法:
基于 SCN 的版本查询
SELECT <columns>
FROM <schema_name.table_name>
VERSIONS BETWEEN SCN <minimum_scn>AND <maximum_scn>
[WHERE <column_filter>]
[GROUP BY <non-aggregated_columns>]
[HAVING <group filter>
[ORDER BY <position_numbers_or_column_names>]
基于 TIMESTAMP 的版���查询
SELECT <columns>
FROM <schema_name.table_name>
VERSIONSBETWEEN timestamp to_timestamp('start_timestamp')and to_timestamp('end_timestamp')
[WHERE <column_filter>]
[GROUP BY <non-aggregated_columns>]
[HAVING <group filter>
[ORDER BY <position_numbers_or_column_names>]
返回的视图提供多个伪列. 包括:
VERSIONS_STARTSCN VERSIONS_STARTTIME
记录操作时(也就是产生这条记录)的scn或时间, 如果为空, 表示该行记录是查询范围外创建的.
VERSIONS_ENDSCN VERSIONS_ENDTIME
表示该记录失效时的scn或时间.
这里什么是失效? 所谓失效就是对应的数据行被修改或者删除.
例如事务1中在A时间点修改了数据行x. 那么数据行x在事务1中的starttime 是A, 但是endtime是空的, 因为事务1的修改一直维持.
直到事务2在B时间点再次修改数据行x, 那么数据行x在事务1中的endtime 就是B了, 因为事务1的修改已经失效.
也就是说, 如果这两列的数据是空, 代表在改断时间内无操作(update or delete)
VERSIONS_OPERATION
记录操作的类型, I 表示Insert, D表示Delete, U表示Update. 如果对索引键的update操作, flashback version query可能会表示为Delete和Insert两个动作.
VERSIONS_XID
表示该操作的事务ID(key)
例子:
SQL> create table Test3(id numeric, name varchar2(10));
Table created.
SQL> insert into test3 select 1,'Jack' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> insert into test3 select 2,'Bill' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> insert into test3 select 3,'Gordon' from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> update test3 set name = 'Billing' where id = 2;
1 row updated.
SQL> commit;
Commit complete.
SQL> delete from test3 where id = 3;
1 row deleted.
SQL> commit;
Commit complete.
上面例子中我新建1个简单的table Test3, 然后插入了3个数据行, 更新了1条, 删除了1条, 注意的是每条语句后都commit了一次.
接下来可以利用flashback versions query 来查询这张表被修改的版本信息.
select id, name, versions_xid, versions_startscn, versions_endscn,
to_char(versions_starttime,'YY/MM/DD HH24:MI:SS') as startime,
to_char(versions_endtime,'YY/MM/DD HH24:MI:SS') as endtime,
versions_operation
from Test3 versions between scn minvalue and maxvalue where id > 0;
输出:
ID NAME VERSIONS_XID VERSIONS_STARTSCN VERSIONS_ENDSCN STARTIME ENDTIME VERSIONS_OPERATION
---------- ---------- ---------------- ----------------- --------------- ----------------- ----------------- ------------------
3 Gordon 05001400BC090000 3028255 14/05/22 22:15:47 D
2 Billing 08001D002B090000 3028245 14/05/22 22:15:23 U
3 Gordon 020010004A090000 3028239 3028255 14/05/22 22:15:11 14/05/22 22:15:47 I
2 Bill 07000900D5060000 3028234 3028245 14/05/22 22:14:56 14/05/22 22:15:23 I
1 Jack 03000B0068090000 3028229 14/05/22 22:14:48 I
可以见到:
1. 在倒数第一行, 我们插入了一条数据1,Jack, 它的versions_scn为空, 因为自从insert后一直没有对这条数据行操作.
2. 倒数第2行, 具有version_scn数据, 因为它被倒数第4行的事务更新了(Bill - > Billing).
3. 同样道理, 倒数第3行的Gordon被删除.