Oracle Flashback 详解

  Oracle flashback 是一种方便快捷的数据库恢复技术,它不使用备份文件,通过闪回日志可以使数据库恢复到过去的某个状态,当用户发生逻辑错误时(误删表数据、表、表空间等)需要快速恢复数据库,可以使用Flashback 实现。

  1 启用Flashback 数据库

  Oracle 默认不启动flashback 数据库,使用flashback 技术必须先启动数据库到flashback 状态,且数据库必须处于archive 模式下,并启用闪回恢复区,因为闪回日志文件必须存放在闪回恢复区中。

1)  检查数据库的归档状态

SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 4
Next log sequence to archive 6
Current log sequence 6
SQL>

如果数据库没有启动到归档模式,需要手动启动到模式下。

SQL> shutdown immediate

SQL> startup mount

SQL> alter database archivelog

 

2) 确定闪回恢复区的目录

SQL> show parameter DB_RECOVERY_FILE_DEST;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest string /usr/oracle/app/flash_recovery
_area
db_recovery_file_dest_size big integer 3882M

 

3) 查看并设置db_flashback_retention_target参数

该参数是一个以分为单位的数字,默认为1440分钟,表示从当前开始计算最大可以把数据库闪回到过去的时间。

SQL> show parameter db_flashback_retention_target;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target integer 2880

 

此处必须明确Oracle 不保证一定可以闪回到时间段内的某个时间点,因为闪回日志是由快闪恢复区自动维护的,如果由于备份数据库或者其他操作引起磁盘空间不足,闪回日志将会被删除,所以我们在数据库运行时要评估快闪恢复区的空间,可以通过下面的参数查看

 

4) 评估快闪恢复区的空间

可以通过访问数据字典v$flashback_database_log来评估需要的快闪恢复区空间。

SQL> select *
2 from v$flashback_database_log;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TIME RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- --------------------- ---------------- -------------- ------------------------
6202363 2017/6/19 星期一 22:24:4 2880 92143616 546471936

 ESTIMATED_FLASHBACK_SIZE表示系统估计的快闪恢复区的大小为546471936字节, FLASHBACK_SIZE表示当前闪回数据的大小为92143616字节。

 

5) 启动数据库到可闪回状态

要启动闪回数据库,必须先将系统启动到mount状态,然后启动闪回数据库

SQL> startup mount

SQL> alter database flashback on

SQL> alter databse open

查看当前数据库是否启动了闪回状态,可以访问数据字典v$database

SQL> select dbid, name, flashback_on from v$database;

DBID NAME FLASHBACK_ON
---------- --------- ------------------
1452257309 ORCL YES

 

6) 查询表空间是否处于闪回保护状态

SQL> select name, flashback_on
2 from v$tablespace;

NAME FLASHBACK_ON
------------------------------ ---------------
SYSTEM YES
SYSAUX YES
UNDOTBS1 YES
USERS YES
TEMP YES
CTRR_DATA YES
APSALU3_DATA YES
DEFAULT_TABLESPACE YES
TEMP02 YES
RMAN_TS YES

7) 开启或者关闭某个表空间闪回状态

首先数据库必须处于mount状态下才能进行此操作

SQL> startup mount

SQL> alter tablespace users flashback on/off

 

2 闪回数据库的实施步骤

1) 数据库级别闪回

使用scott用户建立测试表插入一部分数据然后删除。

获取一个删除前的时间点用于闪回恢复

select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

2017-06-21 12:36:49

 

删除测试表

drop table t_test1;
drop table t_test3;
commit;

 

关闭数据库启动到mount状态

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.

Total System Global Area 450953216 bytes
Fixed Size 2214256 bytes
Variable Size 348128912 bytes
Database Buffers 96468992 bytes
Redo Buffers 4141056 bytes
Database mounted.

 

使用闪回命令将数据库恢复到删除表之前的时间点

flashback database to timestamp to_timestamp('2017-06-21 12:36:49','yyyy-MM-dd hh24:mi:ss');

SQL> flashback database to timestamp to_timestamp('2017-06-21 12:36:49','yyyy-MM-dd hh24:mi:ss');

Flashback complete.

 

然后使用read only 模式打开数据库验证删除的表是否已经恢复

alter database open read only

 

验证无误之后再重新启动数据到mount状态,然后使用resetlogs 打开数据库,闪回日志仍然有效,我们还可以继续闪回到resetlogs以前的某一个时间点,但是这里需要明确一点数据库不能再闪回到resetlogs 之后的某个时间点了,例如这次我们闪回的时间点为:2017-06-21 12:36:49,我们只能闪回到此时间点之前的某个时间点,之后的时间点不能再闪回了。

 

SQL> startup mount

SQL> alter database open resetlogs

 

查看之前删除的两个表已经恢复回来了。

 

2) 删除用户测试

新建用户

create user latiny identified by XXXXX
default tablespace default_tablespace
temporary tablespace temp;

grant connect, resource to latiny;

 

创建表插入测试数据

create table t_test1(id number not null primary key);

循环插入1000条数据

 

获取系统当前时间,用以删除之后闪回恢复时间点

select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

2017-06-21 12:36:49

 

latiny用户退出登录,使用sys用户删除新建的用户

drop user latiny cascade;

 

关闭数据库启动到mount状态下

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.

Total System Global Area 450953216 bytes
Fixed Size 2214256 bytes
Variable Size 352323216 bytes
Database Buffers 92274688 bytes
Redo Buffers 4141056 bytes
Database mounted.

 

将数据库恢复到latiny用户被删之前的时刻

SQL> flashback database to timestamp to_date('2017-06-21 12:36:49','yyyy-MM-dd hh24:mi:ss');

Flashback complete.

 

只读方式打开数据检查被删的用户latiny是否已被恢复。

SQL> alter database open read only;

Database altered.

 

用户跟用户创建的表都已恢复

 

关闭数据库,启动到mount状态,然后再以resetlogs状态启动到open状态

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.

Total System Global Area 450953216 bytes
Fixed Size 2214256 bytes
Variable Size 352323216 bytes
Database Buffers 92274688 bytes
Redo Buffers 4141056 bytes
Database mounted.
SQL> alter database open resetlogs;

Database altered.

 

2 闪回删除

如果用户使用drop table命令,该表不会立即删除,而是保持原本位置,并且将删除的表信息存储在回收站中保留原表名并且赋予一个新的名字,显然此时被删除的表占有的空间没有立刻被释放,记录的信息在回收站中会保留一段时间,直到回收站空间不足或者使用purge 指令永久删除回收站中的记录。

  回收站是一个逻辑结构,不具有物理数据结构,只要删除的表信息记录在其中就可以通过闪回技术恢复。

 

1) 查看数据库闪回删除是否启动

SQL> show parameter recyclebin;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
recyclebin string on

 

已启动,如未启动可以使用如下命令

SQL> alter system set recyclebin=on scope=both;

 

2) 回收站的使用

通过查询数据字典USER_RECYCLEBIN与 DBA_RECYCLEBIN 可以得到回收站删除表的所有信息


select *
from   dba_recyclebin;

 

select *
from user_recyclebin;

 

删除latiny用户下创建的测试表

SQL> drop table t_test1;

Table dropped

SQL> commit;

Commit complete

 

然后用sql查看回收站信息,可以发现被删除的表信息。

 

恢复删除的表

SQL> flashback table T_TEST1 to before drop;

Done

 

可以查看到该表已恢复。

 

这里需要注意一点,表被删除之后相关的数据库对象(索引,触发器)等都将被删除闪回之后这些对象也会跟着被恢复,但是名字不再是未删除之前的名字,它会改变,是系统自动起的名字,不易阅读理解,需要手工修改。

 

3) 多个同名的表恢复

在实际使用中,可能不同的库或者同一库在不同时间里删除相同名字的表,那么在恢复前我们需要通过表的结构,删除时间等来确定哪一个表是真正需要恢复的表。

建立测试表t_test1,并且插入一些数据

create table t_test1(id number not null primary key);

然后删除

再建立测试表t_test1,并且插入一些数据

create table t_test1(id number not null primary key, name varchar2(25));

 

查看回收站发现两个一样的表

SQL> select object_name, original_name, type, droptime
2 from user_recyclebin;

OBJECT_NAME ORIGINAL_NAME TYPE DROPTIME
------------------------------ -------------------------------- ------------------------- -------------------
BIN$UneF8OUhYlbgUAB/AQBq2g==$0 T_TEST1 TABLE 2017-06-21:19:36:23
BIN$UneF8OUgYlbgUAB/AQBq2g==$0 SYS_C0012828 INDEX 2017-06-21:19:36:23
BIN$UneF8OUkYlbgUAB/AQBq2g==$0 SYS_C0012830 INDEX 2017-06-21:19:36:39
BIN$UneF8OUlYlbgUAB/AQBq2g==$0 T_TEST1

 

使用desc 查看表结构,注意一定要在系统里通过sqlplus进去使用该命令,使用PL/SQL或者其他远程连接工具的command 窗口查询不到表结构,会提示object_name对应的表名不存在。

SQL> desc "BIN$UneF8OUhYlbgUAB/AQBq2g==$0";
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER

SQL> desc "BIN$UneF8OUlYlbgUAB/AQBq2g==$0";
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
NAME VARCHAR2(25)

 

使用object_name恢复表

SQL> flashback table "BIN$UneF8OUlYlbgUAB/AQBq2g==$0" to before drop rename to t_test1_new;

Flashback complete.

 

查询恢复的表存在,并且就是之前建立的有两个字段的t_test1;

 

4) purge 永久删除表

如果非常确定一个表没有用了,可以永久删除,可以使用purge命令,此命令删除的表回收站不会存它的任何记录。

SQL> drop table t_test1_new purge;

Table dropped

如果一个表已经在回收站想永久删除,可以使用如下命令

SQL> purge table t_test1;

Done

 

此时查看回收站已经没有任何信息了,因为之前的两个测试表信息都已经使用带purge命令删除与清空了

SQL> show recyclebin;
SQL>

 

 5) 不能使用闪回技术的情况

  •  违反数据库约束,如果子表存在外键约束,删除了子表中的数据,子表在主表对应的记录已经被删除了,此时闪回恢复子表会失败,因为违反了外键约束。
  • 如果回收站的数据因为空间不足,或者永久删除等原因丢失了,闪回表操作会失败。
  • 闪回不能跨越DDL,如果在闪回点与当前点之间有修改表结构的操作,闪回会失败。

 

3 闪回表

闪回表就是将表里的数据退回到历史上的某个时间点,如果用户误删数据,就可以利用闪回表技术将表退回到删除表之前的某一刻,这个操作可以在数据库online时操作,不需要像闪回数据库那样,关闭数据启动到mount状态下操作。

闪回表利用undo表空间里的记录数据旧映像恢复数据,所以如果需要的undo数据丢失或者被覆盖,就不能恢复了。闪回表能恢复的时间由初始化参数undo_retention规定。

 

查看undo相关参数

SQL> show parameter undo;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1

undo_retention 的单位是秒,900表示undo空间只保留15分钟以内的闪回数据,在15分钟以内被删除的数据不能被覆盖,我们可以修改这个值为12小时,12*60*60=43200

SQL> alter system set undo_retention = 43200 scope=spfile;

System altered.

 

为了保证闪回成功我们还需要将undo表空间设置一下

SQL> alter tablespace UNDOTBS1 retention guarantee;

Tablespace altered.

 

创建测试表插入901条数据,然后删除101条,再使用闪回语句恢复删除的表数据

flashback table t_test1 to timestamp to_date('2017-06-22 14:57:00','yyyy-MM-dd hh24:mi:ss');

 

数据恢复成功,之前删除的数据已经被恢复。

 

在实际工作中往往需要采用尝试的方法,因为有时候我们不确定用户错误操作的时间,因此也不确定该恢复的时间点,只能通过大致的时间来估算,此时我们可以多试几次,但是要注意参数设置的值,最多只能闪回到的时间点。

 

 

 4 闪回版本查询

闪回版本是指每次事务引起的数据行的变化情况,每一次变化就是一个版本,我们可以通过查询伪列得到详细的版本信息

select   to_char(versions_starttime,'yyyy-mm-dd hh24:mi:ss'),to_char(versions_endtime,'yyyy-mm-dd hh24:mi:ss'),versions_startscn,versions_endscn,versions_xid,versions_operation
from    t_test1
versions between scn minvalue and maxvalue
order by versions_starttime;

 

versions_starttime:  事务开始时间

versions_endtime: 事务结束时间

versions_startscn: 事务开始的SCN号

versions_endscn: 事务结束的SCN号

versions_xid: 事务ID号

versions_operation: 事务所进行的操作类型,包括插入(显示为I)、删除(D)、更新(U)

 

做个简单的测试,创建一个测试表t_test1,先插入2条数据,然后分更新一次删除一次,可以通过上面的sql查询到版本信息如下

TO_CHAR(VERSIONS_STARTTIME,'YY TO_CHAR(VERSIONS_ENDTIME,'YYYY VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_XID VERSIONS_OPERATION
1 2017-06-26 14:01:49 2017-06-26 14:02:10 9059413 9059422 01001D0086090000 I
2 2017-06-26 14:01:49 9059413 01001D0086090000 I
3 2017-06-26 14:02:10 2017-06-26 14:03:22 9059422 9059511 0100200086090000 U
4 2017-06-26 14:03:22 9059511 0100360086090000 D

 

我们可以根据时间或者SCN号将测试表返回到某个状态,我们测试返回到刚插入数据时的状态。

 flashback table t_test1 to timestamp to_date('2017-06-26 14:02:10','yyyy-mm-dd hh24:mi:ss');

查看结果可以看到测试表达的数据已经返回到最开始插入数据之后的状态,更新与删除操作都被撤销了。

 

5 闪回事务

闪回事务可以通过一个视图来查询,flashback_transaction_query,此视图可以显示哪些事务引起了数据变化,并且为此提供了撤销的sql语句。

select *
from flashback_transaction_query;

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/Latiny/p/7058936.html