您的位置:首页 > 数据库 > Oracle

ORACLE 6种闪回技术详解

2014-08-25 20:53 495 查看
闪回的类型:

(1)闪回查询 flashback query

(2)闪回表 flashback table

(3)闪回版本查询 flashback version query

(4)闪回事务查询 flashback transaction

(5)闪回删除 flashback drop

(6)闪回数据库 flashbac database

1.闪回查询 flashback query

闪回查询,利用undo表空间的数据查询过去某个时间的数据.有两种方式:

1)select * from t as of scn XX where

2)select * from t as of timestamp XX where

先创建一张表,向表中插入数据,并查询此时的SCN:

13:52:11 SQL> CREATE TABLE test_flashback_query (ID INT ,NAME VARCHAR2(50));
13:52:11 SQL> INSERT INTO test_flashback_query VALUES(1,'小明');
1 row inserted
13:52:11 SQL> INSERT INTO test_flashback_query VALUES(2,'小红');
1 row inserted
13:52:11 SQL> INSERT INTO test_flashback_query VALUES(1,'小李');
1 row inserted
13:52:11 SQL> COMMIT;
Commit complete
13:53:40 SQL> select dbms_flashback.get_system_change_number  from dual;GET_SYSTEM_CHANGE_NUMBER------------------------                 4791134
[/code]

然后删除数据:

13:54:52 SQL> delete from test_flashback_query ;
3 rows deleted
13:55:10 SQL> commit;
Commit complete
13:55:51 SQL> select * from test_flashback_query; ID    NAME---- -------------
[/code]

查不到数据.

现在使用闪回查询:

13:58:03 SQL> select * from test_flashback_query as of  scn 4791134;
ID NAME
--------------------------------------- --------------------------------------------------
1 小明
2 小红
1 小李
14:01:29 SQL> select * from test_flashback_query as of timestamp to_date('20140821 13:53:40','YYYYMMDD HH24:MI:SS');ID NAME--------------------------------------- --------------------------------------------------1 小明2 小红1 小李
[/code]

闪回查询使用undo里的旧数据查询历史数据,如果undo数据被覆盖掉就不能使用闪回查询.那么undo里的数据可以保存多少时间?

参数undo_retention 设置了一个保留目标:

15:43:33 SQL> show parameter undo_retention
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_retention                       integer     900


undo_retention 的值 为900,表示undo的历史数据保留900秒.实际这个参数没有意义的,undo能保留多少时间由undo表空间大小和事务量决定的.如果没有什么事务,那么历史数据会一直保留在undo里;如果有大量的数据事务,可能保存不到900秒就被覆盖掉了.

如果要强制保留
undo_retention
指定的时间,要启动undo强制保留:ALTER
TABLESPACE undotbs1 RETENTION GUARANTEE.不过这样做的结果可能是事务没有undo可用.

注意:即使在表上做了DDL操作,依然可以闪回查询到DDL操作之前.

19:35:17 SQL> select * from test_flashback_query;
ID NAME
--------------------------------------- --------------------------------------------------
1 小明
1 小红
1 小李
19:35:24 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
4822535
19:36:19 SQL> alter table test_flashback_query add  note varchar2(50);
Table altered
19:36:31 SQL> select * from test_flashback_query as of scn 4822535;
ID NAME               NOTE
--------------------------------------- ------------------ ---------------------------
1 小明                                               
1 小红                                               
1 小李   


2.闪回表flashback table

闪回表的原理同样是使用undo数据将表闪回到过去的某个时间.

闪回表的要求:

1)开启row movement

2)有flashback any table的权限

3)如果将表还原到某个restore point,需要select any dictionary或flashback any table权限或select_catalog_role角色.

闪回表的语法:



实验:

16:58:02 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 scott
2 jim
3 jack
17:00:39 SQL> select  dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
631692
17:01:04 SQL> delete from flashback_table where id in (1,2);
2 rows deleted
17:01:31 SQL> commit;
Commit complete
17:01:32 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
3 jack
17:13:31 SQL> alter table flashback_table enable row movement;
Table altered
17:13:51 SQL>  flashback table flashback_table to scn 631692;
Done
17:13:57 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 scott
2 jim
3 jack


注意:如果在表上执行了DDL,则不能将表闪回到DDL之前.

把表再次闪回到SCN631692:

17:14:09 SQL> truncate table flashback_table;
Table truncated
17:17:27 SQL> flashback table flashback_table to scn 631692;
flashback table flashback_table to scn 631692
ORA-01466: 无法读取数据 - 表定义已更改


3.闪回版本查询 flashback version query

闪回版本查询用于显示一段时间内表中行的变化.行的变化称为一个版本,同样使用undo的数据来查行的历史.

注意:闪回版本查询只能查询已经提交的事务引起的行的变化.

语法:

SELECT VERSIONS_STARTSCN,
VERSIONS_STARTTIME,
VERSIONS_ENDSCN,
VERSIONS_ENDTIME,
VERSIONS_XID,
VERSIONS_OPERATION
FROM FLASHBACK_TABLE VERSIONS BETWEEN VERSIONS {BETWEEN {SCN | TIMESTAMP} start AND end}

各伪列的说明如下:

VERSIONS_STARTSCN

VERSIONS_STARTTIME

Starting System Change Number (SCN) or
TIMESTAMP
when the row version was created. This pseudocolumn identifies the time when the data first had the values
reflected in the row version. Use this pseudocolumn to identify the past target time for Oracle Flashback Table or Oracle Flashback Query.
If this pseudocolumn is
NULL
, then the row version was created before
start
.
行被创建时的SCN或时间,如果为NULL,则在startscn前,行已经被创建
VERSIONS_ENDSCN

VERSIONS_ENDTIME

SCN or
TIMESTAMP
when the row version expired.
If this pseudocolumn is
NULL
, then either the row version was current at the time of the query or the row corresponds to a
DELETE
operation.
行过期的时间,如果为NULL,则在查询时行是存在于表中或者行执行删除操作
VERSIONS_XID

Identifier of the transaction that created the row version.
创建行版本的事务号
VERSIONS_OPERATION

Operation performed by the transaction:
I
for insertion,
D
for deletion, or
U
for
update. The version is that of the row that was inserted, deleted, or updated; that is, the row after an
INSERT
operation, the row before a
DELETE
operation, or the row affected
by an
UPDATE
operation.
For user updates of an index key, Oracle Flashback Version Query might treat an
UPDATE
operation as two operations,
DELETE
plus
INSERT
,
represented as two version rows with a
D
followed by an
I
VERSIONS_OPERATION
.
版本操作:I:insert D:delete U:update

来源: <http://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_flashback.htm#ADFNS01004>
实验:

在表中插入三行数据,并查询这三行数据的版本

17:52:50 SQL> INSERT INTO flashback_table VALUES(1,'scott');
1 row inserted
17:53:09 SQL> commit;
Commit complete
17:53:11 SQL> INSERT INTO flashback_table VALUES(2,'jim');
1 row inserted
17:53:21 SQL> commit;
Commit complete
17:53:22 SQL> INSERT INTO flashback_table VALUES(3,'jack');
1 row inserted
17:53:30 SQL> delete from flashback_table where id=2;
1 row deleted
18:08:29 SQL> commit;
Commit complete
18:08:31 SQL>
SQL> SELECT VERSIONS_STARTSCN startscn,
2 VERSIONS_STARTTIME starttime,
3 VERSIONS_ENDSCN ENDSCN,
4 VERSIONS_ENDTIME ENDTIME,
5 VERSIONS_XID XID,
6 VERSIONS_OPERATION OPERATION,
7 ID,
8 NAME
9 FROM FLASHBACK_TABLE VERSIONS BETWEEN TIMESTAMP TO_DATE('20140824 17:52:50', 'YYYYMMDD HH24:MI:SS')
10 AND TO_DATE('20140824 18:08:35', 'YYYYMMDD HH24:MI:SS');

STARTSCN STARTTIME ENDSCN ENDTIME XID Operation ID NAME
---------- ----------------------------------- ---------- ----------------------------------- ---------------- - ---------- ----------
636387 24-8月 -14 06.08.25 下午 05001E000C020000 D 2 jim
635244 24-8月 -14 05.53.42 下午 09000D0009020000 I 3 jack
635202 24-8月 -14 05.53.21 下午 636387 24-8月 -14 06.08.25 下午 07000400FE010000 I 2 jim
635192 24-8月 -14 05.53.09 下午 03000E00FE010000 I 1 scott
[/code]

可以看到,行都是在查询的时间段内创建的.而id=2的行在05.53.21时插入表中,在06.08.25时被删除.第三行中endscn 636387表示行在该scn过期(被删除).第一行的operation为D,说明该行被删除.
如果在表中执行DDL操作,无法查询DDL操作之前的版本变化.

4.闪回事务查询 flashback transaction

闪回事务查询,通过查询flashback_transaction_query表来查询一个事务引起的变化.闪回事务查询使用的也是undo表空间的数据.
该表的字段说明

ColumnDatatypeNULLDescription
XID
RAW(8)
Transaction identifier事务号
START_SCN
NUMBER
Transaction start system change number (SCN)事务开始时的SCN
START_TIMESTAMP
DATE
Transaction start timestamp 事务开始时的时间
COMMIT_SCN
NUMBER
Transaction commit system change number; NULL for active transactions 事务提交时的scn
COMMIT_TIMESTAMP
DATE
Transaction commit timestamp; NULL for active transactions 事务提交时的时间
LOGON_USER
VARCHAR2(30)
Logon user for the transaction 执行操作用户
UNDO_CHANGE#
NUMBER
Undo system change number (
1
or higher) undo号
OPERATION
VARCHAR2(32)
Forward-going DML operation performed by the transaction: 执行的操作

D
- Delete

I
- Insert

U
- Update

B


UNKNOWN


TABLE_NAME
VARCHAR2(256)
Name of the table to which the DML applies 表
TABLE_OWNER
VARCHAR2(32)
Owner of the table to which the DML applies
ROW_ID
VARCHAR2(19)
Rowid of the row that was modified by the DML
UNDO_SQL
VARCHAR2(4000)
SQL to undo the DML indicated by
OPERATION  反转事务的语句


来源: <http://docs.oracle.com/cd/E11882_01/server.112/e40402/statviews_5125.htm#REFRN29086>
现在来查询删除id=2的事务,在上文中可以找到事务号为05001E000C020000

XID               START_SCN START_TIMESTAMP COMMIT_SCN COMMIT_TIMESTAMP LOGON_USER      UNDO_CHANGE# OPERATION       TABLE_NAME                TABLE_OWNER     ROW_ID              UNDO_SQL
---------------- ---------- --------------- ---------- ---------------- --------------- ------------ --------------- ------------------------- --------------- ------------------- --------------------------------------------------------------------------------
05001E000C020000     635244 2014-08-24 17:5     636387 2014-08-24 18:08 SCOTT                      1 DELETE          FLASHBACK_TABLE           SCOTT           AAAOn9AAEAAAAA/AAB  insert into "SCOTT"."FLASHBACK_TABLE"("ID","NAME") values ('2','jim');


可以看到事务开始时间提交时间,用户,表名,执行的操作等,undo_sql可以反转该事务.

即使对表执行了DDL语句,也可以进行闪回事务查询.

5.闪回删除 flashback drop

从10G开始,删除一个表时,默认情况下并不会把直接删除,而是把表和表的对象重命名,然后放到回收站.把回收站的表的重新找回来,称为闪回删除.闪回删除使用的是回收站而非undo.

实验:

在有上创建一个索引,然后删除表再闪回删除表.

22:15:45 SQL> create index id_flashback_table on flashback_table(id);
Index created
22:15:49 SQL> drop table flashback_table;
Table dropped
22:18:14 SQL> select a.OBJECT_NAME,a.original_name,a.operation,a.TYPE,a.CAN_UNDROP from recyclebin a;
OBJECT_NAME                    ORIGINAL_NAME                    OPERATION       TYPE                      CAN_UNDROP
------------------------------ -------------------------------- --------------- ------------------------- ----------
BIN$4Buuep1uTJiXp4s3H0tKcA==$0 ID_FLASHBACK_TABLE               DROP            INDEX                     NO
BIN$WAzqL7qmRESDsPL6KkO9VQ==$0 FLASHBACK_TABLE                  DROP            TABLE                     YES


可以看到回收站中有两个对象,分别是flashback_table和索引id_flashback_table.
现在闪回表:

22:19:10 SQL> flashback table flashback_table to before drop;
Done
22:21:36 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------


可以查询表,说明表已经被闪回了.

查询一下表上的索引:

22:24:26 SQL> SELECT a.INDEX_NAME,a.TABLE_NAME,a.TABLE_OWNER,a.status FROM User_Indexes a where a.TABLE_NAME='FLASHBACK_TABLE';
INDEX_NAME                     TABLE_NAME                TABLE_OWNER     STATUS
------------------------------ ------------------------- --------------- --------
BIN$4Buuep1uTJiXp4s3H0tKcA==$0 FLASHBACK_TABLE           SCOTT           VALID


发现表上的索引也被闪回了,但是并不是原来的名字,而是删除后重命名的名字.

可以直接删除表不放在回收站中:drop table FLASHBACK_TABLE purge;

6.闪回数据库 flashbac database

接下来讨论本节的重点内容,闪回数据库.

闪回数据库是通过闪回日志,将数据库闪回到过去的一个时刻.闪回数据库用来执行逻辑错误的恢复,如删除了表(purge)\用户\截断了表等,在没有闪回以前,要进行不完全恢复或TSPITR才能实现.闪回数据库不能用于物理恢复,比如恢复到某个数据文件创建以前.

闪回数据库的限制:

1)不能执行介质恢复,只能执行逻辑恢复.

2)不能反转shrink操作,可以脱机shrink的datafile再执行闪回

3)不能闪回到数据库物理结构变化之前

4)如果控制控制文件执行了恢复或重建,不能闪回到恢复或重建之前

闪回数据库的实现依赖于闪回日志.闪回日志记录了数据库的变化,进行数据库闪回时,数据库使用闪回日志,还原数据块的变化.闪回日志必须放在快速恢复区中.因此必须配置快速恢复区.

启用快速恢复区需要设置两个参数:db_recovery_file_dest ,db_recovery_file_dest_size.前者指定位置,后者指定大小.

23:11:39 SQL> alter system set db_recovery_file_dest_size=2G;
System altered
23:12:11 SQL> alter system set db_recovery_file_dest='D:\app\wj\flash_recovery_area';
System altered


要启用闪回日志,开启归档,必须在mount开启闪回功能.

SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 1071333376 bytes
Fixed Size                  1334380 bytes
Variable Size             343933844 bytes
Database Buffers          721420288 bytes
Redo Buffers                4644864 bytes
数据库装载完毕。
SQL> alter database archivelog ;
数据库已更改。
SQL> alter database flashback on;
数据库已更改。
SQL> alter database open;
数据库已更改。


可以闪回的时间段可以从v$flashback_database_log表查询

SQL> SELECT * FROM v$flashback_database_log;
OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TIME RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- --------------------- ---------------- -------------- ------------------------
667499 2014-08-24 23:15:27               1440       16384000                        0


最早可以闪回到的SCN是667499,闪回日志保留区的目标为1440分钟,闪回日志大小是16384000byte(15.625M).

现在测试闪回功能.

在表中插入3条数据,记录SCN,删除一条数据,再记录SCN

23:17:19 SQL> select dbms_flashback.get_system_change_number from dual;GET_SYSTEM_CHANGE_NUMBER------------------------                  667976

23:17:51 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 scott
2 jim
3 jack
23:18:08 SQL> delete from flashback_table where id=3;
1 row deleted
23:18:19 SQL> commit;
Commit complete
23:18:21 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
667989


此时表中有两条数据,然后将数据闪回到SCN 667976,必须在mount下闪回

23:23:22 SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
23:24:04 SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 1071333376 bytes
Fixed Size                  1334380 bytes
Variable Size             343933844 bytes
Database Buffers          721420288 bytes
Redo Buffers                4644864 bytes
数据库装载完毕。
23:24:23 SQL> flashback database to scn 667976;
闪回完成。


查询表中的内容:

23:25:23 SQL> alter database open resetlogs;
数据库已更改。
23:26:22 SQL> select * from scott.flashback_table;\
ID NAME
---------- ----------
1 scott
2 jim
3 jack


可以看到表已经闪回,表的数据又是3条了.

可以用A点(现在)闪回到B点(过去),再从B点闪回到A点.从B到点A的过程实际上是使用归档日志而不闪回日志,因为闪回日志只记录了undo数据,无法向前闪回,而归档日志记录了redo信息,可以把数据库向前推进.

17:38:02 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 java
2 oracle
3 c
17:39:30 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1064028
17:39:45 SQL> delete from flashback_table where id=2;
1 row deleted
17:40:20 SQL> commit;
Commit complete
17:40:22 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 java
3 c
17:40:28 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1064065
17:41:13 SQL> shutdowm immediate;
SP2-0734: 未知的命令开头 "shutdowm i..." - 忽略了剩余的行。
17:41:20 SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
17:41:40 SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 1653518336 bytes
Fixed Size                  2176288 bytes
Variable Size            1056967392 bytes
Database Buffers          587202560 bytes
Redo Buffers                7172096 bytes
数据库装载完毕。
17:42:04 SQL> flashback database to scn 1064028;
闪回完成。
17:42:50 SQL> alter database open read only;
数据库已更改。
17:43:30 SQL> select * from flashback_table;
ID NAME
--------------------------------------- ----------
1 java
2 oracle
3 c

ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。

Total System Global Area 1653518336 bytes
Fixed Size                  2176288 bytes
Variable Size            1056967392 bytes
Database Buffers          587202560 bytes
Redo Buffers                7172096 bytes
数据库装载完毕。
SQL> flashback database to scn to 1064065;
SQL> alter database open read only;
SQL> select * from scott.flashback_table;
ID NAME
--------------------------------------- ----------
1 java
3 c


测试从B点到A的,可以先闪回到B点,再用RMAN恢复数据库,说明前滚是使用归档日志.

总结一下:

闪回技术使用的数据限制
闪回查询 flashback queryundo表空间可以查询到DDL操作之前
闪回表 flashback tableundo表空间 不能闪回到DDL操作之前
闪回版本查询 flashback version queryundo表空间 不能查询DDL之前的版本
闪回事务查询 flashback transactionundo表空间 可以查询DDL之前的事务
闪回删除 flashback drop回收站
闪回数据库 flashbac database闪回日志
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: