Oracle的学习心得和知识总结(一)|Oracle数据库闪回技术详解

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: Oracle的学习心得和知识总结(一)|Oracle数据库闪回技术详解

目录结构

注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下:


1、Oracle闪回详解,点击前往

2、Oracle闪回技术详解,点击前往

3、参考书籍:《涂抹Oracle 三思笔记之一步一步学Oracle》

4、参考书籍:《Oracle Database 11g数据库管理艺术》

5、Flashback Transaction Backout,点击前往

6、关于oracle闪回数据归档的总结,点击前往

7、参考书籍:《Oracle Database 9i10g11g编程艺术深入数据库体系结构(第2版)》


Oracle数据库闪回技术

文章快速说明索引

Oracle闪回的概述

Oracle闪回的使用

闪回查询

闪回表(insert delete update)

闪回删除

闪回数据库(truncate/多表数据变更)

闪回数据归档

image.png

文章快速说明索引

学习目标:


目的:因为接下来想在PostgreSQL上实践实现一下 闪回操作 ,但是就目前而言 PostgreSQL尚不支持此功能。德哥的git和其他PostgreSQL社区爱好者也曾分享过一些 类似的 闪回简易实现,大家有兴趣也可以去看看!本文主要记录在Oracle数据库上面的闪回功能的使用体验和基于开发者的设计思考,以期在PostgreSQL数据库上面支持此功能!


学习内容:(详见目录)


1、Oracle数据库的闪回技术


学习时间:


2020年9月16日03:36:25 - 2020年9月27日23:33:51


学习产出:


1、Oracle数据库闪回技术学习

2、CSDN 技术博客 1篇

3、PostgreSQL数据库闪回功能实现设计思考


Oracle闪回的概述

闪回概述

Flashback 即 数据库闪回操作,它是Oracle自9i版本才开始提供的一项新特性,在Oracle 10g中对功能进行了增强。在10g之前只提供了 闪回查询 的功能,进入10g之后又提供了对事务、对表的恢复,以及真正具有恢复意味的闪回数据库的功能。在Oracle11g之后这些功能日趋更加完善。闪回技术是Oracle强大数据库备份恢复机制的一部分,在数据库发生逻辑错误的时候,闪回技术能提供快速且最小损失的恢复(多数闪回功能都能在数据库联机状态下完成)。需要注意的是,闪回技术旨在快速恢复逻辑错误,对于物理损坏或是介质丢失的错误,闪回技术就回天乏术了,还是得借助于Oracle一些高级的备份恢复工具如RAMN去完成。


闪回特性的优点在于语法简单、操作方便和功能强大,其作用在于快速恢复数据和查询历史数据。在Oracle 10g中的闪回功能可以分成以下三个方面:


闪回查询(Flashback Query) :通过查询UNDO段, 能够重现操作之前的数据

闪回表(Flashback Table) :该特性与10g中新推出的另外一项新增特性Recycle Bin(回收站) 对应, 默认情况下表对象及其关联的索引等对象在DROP后并没有物理删除, 而是标记为删除(类似在Windows中删除文件时, 文件移向“回收站”的概念),如果你想对这类表进行恢复,只需要简单的命令即可,而且该操作只修改数据字典,不管要恢复的对象占用多大空间,恢复效率极高

闪回数据库(Flashback Database) :该功能十分强大, 真正实现了不需要备份的恢复(严格地讲还是有备份, 只不过这个备份操作不由DBA做, 而是Oracle自动进行)

详细内容展开如下表所示:(基于Oracle 11g的闪回技术)


闪回技术 闪回级别 场景描述 功能描述 对象依赖 是否影响数据

Flashback Database Database 表截断、逻辑错误、其他多表意外事件 将整个数据库倒退到一个特定的时刻 闪回日志、undo log YES

Flashback Table Table 更新、删除、插入记录 将表返回到过去的一个状态 还原数据、undo log YES

Flashback DROP Drop 删除表 撤销DROP TABLE命令并恢复被删除的表 recyclebin YES

Flashback QUERY Query 当前数据和历史数据对比 检索过去某一时刻(或时间间隔)的数据 还原数据、undo log NO

Flashback Version Query Version Query 比较行版本 同上 同上 NO

Flashback Transaction Query Transaction Query 比较事务 同上 同上 NO

Flashback Transaction Backout Transaction Backout 撤销事务 在Database Control中单击一下, 撤销一个事务以及它依赖的所有事务 undo log YES

Flashback Data Archive Archive DDL、DML 存储对一个表所做更改的历史,可用它来构造旧版本数据的查询和用于审计用途 归档日志 YES

下面来看一下闪回功能的启停:

主要操作步骤如下:


1、数据库处于归档模式

2、开启归档日志

3、设置合理的闪回区

4、开启flashback并检查:alter database flashback on/off;

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.
Total System Global Area 1586708480 bytes
Fixed Size        2213736 bytes
Variable Size    1090521240 bytes
Database Buffers    486539264 bytes
Redo Buffers        7434240 bytes
Database mounted.
SQL>  archive log list;
Database log mode        No Archive Mode
Automatic archival         Disabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     54
Current log sequence         56
SQL> alter database archivelog;                         # 注意看下面的 Enabled 和 上面的 Disabled
Database altered.
SQL> select flashback_on from v$database;
FLASHBACK_ON
------------------
NO
SQL>  archive log list;
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     54
Next log sequence to archive   56
Current log sequence         56
SQL> alter system set db_recovery_file_dest='/home/oracle/app/flash_recovery_area' scope=both;
System altered.
SQL> alter system set db_recovery_file_dest_size=60G scope=both;
System altered.
SQL>  alter system set db_flashback_retention_target=4320 scope=both;
System altered.
SQL>  archive log list;
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     54
Next log sequence to archive   56
Current log sequence         56
SQL> alter database flashback on;
Database altered.
SQL> select flashback_on from v$database;
FLASHBACK_ON
------------------
YES
SQL>

如上,我们成功开启了数据库的闪回功能,下面我们开始准备闪回所需的数据:

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-26 10:19:21
SQL>
SQL> create table test1 (id int,name varchar(16),curtime TIMESTAMP);
Table created.
SQL> insert into test1 values (1,'post',sysdate);
1 row created.
SQL>  insert into test1 values (2,'orac',sysdate);
1 row created.
SQL> insert into test1 values (3,'mysq',sysdate);
1 row created.
SQL> insert into test1 values (4,'redi',sysdate);
1 row created.
SQL>
SQL> set linesize 800
SQL> set pagesize 900                            
SQL>  select * from test1;
  ID NAME       CURTIME
---------- ---------------- ----------------------------
   1 post       26-SEP-20 10.20.07.000000 AM
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL>

Oracle闪回的使用

闪回使用

闪回查询

闪回查询操作:允许用户查询过去某个时间点的数据,用以重构由于意外删除或更改的数据,但是表中的数据不会变化。于是我们就可以查询过去某个时间点的数据库状态和表中当时的数据。其工作原理为:Oracle 会提取所需要的撤销数据(前提是撤销是可用的,即撤销数据还没被覆盖)进行回滚,但这种回滚是临时的,仅针对当前session可见。

SQL>  select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.20.07.000000 AM
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL> commit;
Commit complete.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-26 10:22:29
SQL> delete from test1 where id = 1;
1 row deleted.
SQL> commit;
Commit complete.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL>
SQL> select * from test1 as of timestamp  to_timestamp('2020-09-26 10:22:29','yyyy-mm-dd hh24:mi:ss');
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.20.07.000000 AM
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL>

如上一条被删除的数据就被我们查回来了,但是建议不要使用时间 而是scn:

SQL> select timestamp_to_scn(to_date('2020-09-26 10:22:29','yyyy-mm-dd hh24:mi:ss')) from dual;
TIMESTAMP_TO_SCN(TO_DATE('2020-09-2610:22:29','YYYY-MM-DDHH24:MI:SS'))
----------------------------------------------------------------------
                     2254386
SQL>
SQL> select * from test1  as of scn 2254386;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.20.07.000000 AM
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL> select * from test1 ;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL>

如上,这个闪回查询 顾名思义,没有改变现表状态的功能 我们可以很清楚的看到数据不会变化。


闪回表(insert delete update)

闪回表操作:闪回表就是对表的数据做回退,回退到之前的某个时间点(也即:可将某个表回退到过去某个时间点的状态和数据内容)。其工作原理为:和上面一样Oracle会先去查询撤销段,提取过去某个时间点之后的所有变更,构造反转这些变更的SQL语句进行回退。闪回操作是一个单独的事务,所以若由于撤销数据过期之类的原因导致无法闪回,整个操作会回滚,不会存在不一致的状态。它这里利用的也是undo的历史数据,与undo_retention设置有关,默认是1440分钟(1天)。但是sys用户表空间不支持闪回表,示例如下:

SQL>  flashback table test1 to timestamp to_timestamp('2020-09-26 10:22:29','yyyy-mm-dd hh24:mi:ss');
 flashback table test1 to timestamp to_timestamp('2020-09-26 10:22:29','yyyy-mm-dd hh24:mi:ss')
                 *
ERROR at line 1:
ORA-08185: Flashback not supported for user SYS
SQL>

OK,我们换一个用户开始同样的操作:

SQL> CREATE user song identified by sys;
User created.
SQL> show user
USER is "SYS"
SQL> alter user song identified by 123456;
User altered.
SQL> grant connect,resource,dba to song;
Grant succeeded.
SQL> show user
USER is "SYS"
SQL> connect song/123456
Connected.
SQL>

然后我们在其他用户下面执行这个闪回表操作(需要注意的是:要想表闪回,需要允许表启动行迁移(row movement)

),实例如下:

SQL> show user
USER is "SONG"
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-26 10:53:01
SQL> create table test1 (id int,name varchar(16),curtime TIMESTAMP);
Table created.
SQL> insert into test1 values (1,'post',sysdate);
1 row created.
SQL> insert into test1 values (2,'orac',sysdate);
1 row created.
SQL> insert into test1 values (3,'mysq',sysdate);
1 row created.
SQL> insert into test1 values (4,'redi',sysdate);
1 row created.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> commit;
Commit complete.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-26 10:54:10
SQL> delete from test1 where id = 1;
1 row deleted.
SQL> commit;
Commit complete.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ----------------------
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> select * from test1 as of timestamp  to_timestamp('2020-09-26 10:54:10','yyyy-mm-dd hh24:mi:ss');
  ID NAME       CURTIME
---------- ---------------- ----------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> flashback table test1 to timestamp to_timestamp('2020-09-26 10:54:10','yyyy-mm-dd hh24:mi:ss');
flashback table test1 to timestamp to_timestamp('2020-09-26 10:54:10','yyyy-mm-dd hh24:mi:ss')
                *
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled
SQL> select row_movement from dba_tables where table_name='test1' and owner='song';
no rows selected
SQL> alter table test1 enable row movement;
Table altered.
SQL> flashback table test1 to timestamp to_timestamp('2020-09-26 10:54:10','yyyy-mm-dd hh24:mi:ss');
Flashback complete.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ----------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> alter table test1 disable row movement;
Table altered.
SQL>

如上开启row movement,因为启用表闪回首先要在表上支持行移动(在数据字典中设置标识来标识该操作可能会改变行ID,即同一条数据闪回成功后主键都一样,但行ID其实已经发生变化了)。


闪回表可能会失败,有可能有以下几种情况:


违反了数据库约束:比如用户不小心删除了子表中的数据,现在想利用闪回表技术进行回退,恰好在这中间,父表中与该数据对应的那条记录也被删除了,在这种情况下,由于违反了外键约束,导致闪回表操作失败了

撤销数据失效:比如用于支撑闪回操作的撤销数据被覆盖了,这种情况闪回表操作自然会失败

闪回不能跨越DDL:在闪回点和当前点之间,表结构有过变更,这种情况闪回操作也会失败

注:上述闪回功能都是基于撤销数据(undo log)的,而撤销数据是会被重写的(Expired会被重写,Active不会被重写),所以在需要使用上面闪回功能去恢复数据的时候(确切地说,是需要使用基于撤销数据的闪回功能时),最短时间发现错误,第一时间执行闪回操作,才能最大程度地保证闪回功能的成功。


闪回删除

在Oracle中,当一个表被drop掉,表会被放入recyclebin 即:回收站。于是我们这里的drop闪回就可以通过回收站做表的闪回。在闪回过程中 表上的索引、约束等同样会被恢复,同样这里也不支持sys/system用户表空间对象


而回收站功能的开启和关闭是可通过alter system set recyclebin=off; alter system set recyclebin=on scope=spfile;来完成(默认是开启的)示例如下:

SQL> alter database flashback off;
Database altered.
SQL> show recyclebin;                  # 看一眼回收站
ORIGINAL NAME  RECYCLEBIN NAME    OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST1    BIN$sC+Fb/6hJ+3gUAB/AQATZg==$0 TABLE      2020-09-26:10:52:17
SQL> purge recyclebin;                  # 清空回收站 不影响下面的操作
Recyclebin purged.
SQL> show recyclebin;                  # 回收站为空
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> drop table test1;
Table dropped.
SQL> show recyclebin;                  # 表被放到回收站了
ORIGINAL NAME  RECYCLEBIN NAME    OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST1    BIN$sC+Fb/6iJ+3gUAB/AQATZg==$0 TABLE      2020-09-26:12:24:15
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-26 12:24:45
SQL> flashback table TEST1  to before drop;
Flashback complete.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL>

如上我们使用purge recyclebin;来清理当前的回收站。这里我们注意一点:在最开始的时候 我可是把flashback关闭了的,但是只要开启了recyclebin,那么就可以闪回DROP表。

但如果连续覆盖,就需要指定恢复的表名,如果已经存在表,则需要恢复重命名。

SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL> drop table test1;
Table dropped.
SQL> create table test1 (id int,mytime timestamp);
Table created.
SQL> insert into test1 values (1,sysdate);
1 row created.
SQL>  drop table test1;
Table dropped.
SQL> show recyclebin;                  # 这个时候回收站里面有两个不一样的同名表
ORIGINAL NAME  RECYCLEBIN NAME    OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST1    BIN$sC+Fb/6kJ+3gUAB/AQATZg==$0 TABLE      2020-09-26:12:31:23
TEST1    BIN$sC+Fb/6jJ+3gUAB/AQATZg==$0 TABLE      2020-09-26:12:30:18
SQL> flashback table "BIN$sC+Fb/6kJ+3gUAB/AQATZg==$0" to before drop ;    # 这样可以恢复指定那个
Flashback complete.
SQL> select * from test1;
  ID MYTIME
---------- ---------------------------------------------------------------------------
   1 26-SEP-20 12.31.17.000000 PM
SQL> flashback table test1 to before drop rename to another_test1;     # 恢复的时候 同时做了个重命名
Flashback complete.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       26-SEP-20 10.53.20.000000 AM
   2 orac       26-SEP-20 10.53.28.000000 AM
   3 mysq       26-SEP-20 10.53.36.000000 AM
   4 redi       26-SEP-20 10.53.45.000000 AM
SQL>

闪回数据库(truncate/多表数据变更)

数据库闪回功能可以基于两种方式来完成:1、数据库闪回必须在mounted状态下进行 ; 2、基于快照的可以在open下进行闪回库 (要求数据库为归档模式)。


闪回数据库主要是将数据库还原到过去的某个时间点或SCN,用于数据库出现逻辑错误时,需要open database resetlogs。当然,闪回点之后的所有工作就丢失了,其实就相当于数据库的不完整恢复,所以只能以resetlogs模式打开数据库。闪回数据库会造成停机时间,当然相比于传统备份恢复机制,恢复过程会快很多。其工作原理为:闪回数据库不使用撤销数据(undo log),使用另外一种机制来保留回退所需要的恢复数据。当启用闪回数据库时,发生变化的数据块会不断从数据库缓冲区缓存中复制到闪回缓冲区,然后被称为恢复写入器(Recovery Writer)的后台进程会将这些数据刷新到磁盘中的闪回日志文件中。闪回的过程:是一个 提取闪回日志 到 将块映像复制回数据文件 的过程。


虽然在上面我们已经配置过闪回数据库的一些属性,但是这个很重要,下面再来详细看一下闪回数据库功能的配置:

主要操作步骤如下:


1、数据库处于归档模式 startup mount

2、开启归档日志 alter database archivelog;

3、设置合理的闪回区 指定闪回恢复区 指定恢复区大小 指定闪回日志保存时间

指定闪回恢复区,也就是存放闪回日志的位置,但闪回恢复区不仅仅是为了存放闪回日志。Oracle的很多备份恢复技术都用到这个区域,比如控制文件的自动备份等都会存放到此区域

alter system set db_recovery_file_dest='/home/oracle/app/flash_recovery_area' scope=both;

指定恢复区大小

alter system set db_recovery_file_dest_size=60G scope=both;

指定闪回日志保留时间为4320 / 60 = 72小时,即通过闪回操作,可以将数据库回退到前72小时内的任意时间点

alter system set db_flashback_retention_target=4320 scope=both;

4、开启flashback并检查:alter database flashback on/off;


下面是详细的SQL演示:

SQL> shutdown immediate                      # 因为当前用户是song 不是sys  没有权限
ORA-01031: insufficient privileges
SQL> conn /as sysdba                      # 连接 用sys用户
Connected.
SQL> shutdown immediate                      # 关闭数据库
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount                      # 开启mounted状态
ORACLE instance started.
Total System Global Area 1586708480 bytes
Fixed Size        2213736 bytes
Variable Size    1090521240 bytes
Database Buffers    486539264 bytes
Redo Buffers        7434240 bytes
Database mounted.
SQL> archive log list;             # 查看归档日志参数
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     58
Next log sequence to archive   60
Current log sequence         60
SQL> alter database archivelog;            # 开启归档日志
Database altered.
SQL> archive log list;
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     58
Next log sequence to archive   60
Current log sequence         60
SQL>  select flashback_on from v$database;                 # 查看闪回是否开启
FLASHBACK_ON
------------------
NO
SQL>                       # 下面是配置闪回属性
SQL> alter system set db_recovery_file_dest='/home/oracle/app/flash_recovery_area' scope=both;
System altered.
SQL> alter system set db_recovery_file_dest_size=60G scope=both;
System altered.
SQL> alter system set db_flashback_retention_target=4320 scope=both;
System altered.
SQL> archive log list;
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     58
Next log sequence to archive   60
Current log sequence         60
SQL>  alter database flashback on;       # 开启闪回
Database altered.
SQL> select flashback_on from v$database;        # 查看 是开启的
FLASHBACK_ON
------------------
YES
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';         # 设置时间格式
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-27 10:55:26
SQL> select * from test1;
select * from test1
              *
ERROR at line 1:
ORA-01219: database not open: queries allowed on fixed tables/views only
SQL> alter database open;                # 打开数据库
Database altered.
SQL> select * from test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   2 orac       26-SEP-20 10.20.15.000000 AM
   3 mysq       26-SEP-20 10.20.23.000000 AM
   4 redi       26-SEP-20 10.20.32.000000 AM
SQL> connect song/123456                      # 使用自定义用户连接
Connected.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL>

如下是闪回数据库的实例:


SQL> connect /as sysdba
Connected to an idle instance.
SQL>  startup
ORACLE instance started.
Total System Global Area 1586708480 bytes
Fixed Size        2213736 bytes
Variable Size    1090521240 bytes
Database Buffers    486539264 bytes
Redo Buffers        7434240 bytes
Database mounted.
Database opened.
SQL> connect song/123456
Connected.
SQL> select table_name from dba_tables where owner = 'SONG';
TABLE_NAME
------------------------------
SHANHUI
SYS_TEMP_FBT
ANOTHER_TEST1
SQL> select * from ANOTHER_TEST1;
  ID NAME
---------- ----------------
CURTIME
---------------------------------------------------------------------------
   1 post
27-SEP-20 02.05.11.000000 PM
   2 orac
27-SEP-20 02.06.02.000000 PM
   3 mysq
27-SEP-20 02.06.02.000000 PM
  ID NAME
---------- ----------------
CURTIME
---------------------------------------------------------------------------
   4 redi
27-SEP-20 02.06.35.000000 PM
SQL> set linesize 800
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2020-09-27 14:29:26
SQL> truncate table ANOTHER_TEST1;
Table truncated.
SQL> select * from ANOTHER_TEST1;
no rows selected
SQL> commit;
Commit complete.
SQL> connect /as sysdba
Connected.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.
Total System Global Area 1586708480 bytes
Fixed Size        2213736 bytes
Variable Size    1090521240 bytes
Database Buffers    486539264 bytes
Redo Buffers        7434240 bytes
Database mounted.
SQL> flashback database to timestamp to_timestamp('2020-09-27 14:29:26','yyyy-mm-dd HH24:MI:SS');
Flashback complete.
SQL> alter database open resetlogs;
Database altered.
SQL> conn song/123456
Connected.
SQL> select * from ANOTHER_TEST1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL> show user
USER is "SONG"
SQL>


如上,在闪回完成之后,还需要注意的是:闪回数据库主要是将数据库还原值过去的某个时间点或SCN,用于数据库出现逻辑错误时,千万不能忘记open database resetlogs。


在上面我们也曾说过:闪回数据库的功能 也是 可以基于快照来实现。即:创建闪回快照点,然后恢复到指定的快照点。示例如下:

SQL> select * from ANOTHER_TEST1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL> create restore point myfirstpoint guarantee flashback database;
create restore point myfirstpoint guarantee flashback database
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL> conn /as sysdba
Connected.
SQL> create restore point myfirstpoint guarantee flashback database; # 创建闪回快照点
Restore point created.
SQL> conn song/123456
Connected.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL> truncate table another_test1;
Table truncated.
SQL> commit;
Commit complete.
SQL> conn /as sysdba
Connected.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.
Total System Global Area 1586708480 bytes
Fixed Size        2213736 bytes
Variable Size    1090521240 bytes
Database Buffers    486539264 bytes
Redo Buffers        7434240 bytes
Database mounted.
SQL> flashback database to restore point myfirstpoint; # 基于快照点,开始闪回
Flashback complete.
SQL> alter database open resetlogs;
Database altered.
SQL> show user
USER is "SYS"
SQL> conn song/123456
Connected.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL>
SQL> select flashback_on from v$database;
FLASHBACK_ON
------------------
YES
SQL> archive log list;
ORA-01031: insufficient privileges
SQL> conn /as sysdba
Connected.
SQL> archive log list;
Database log mode        Archive Mode
Automatic archival         Enabled
Archive destination        USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     1
Next log sequence to archive   1
Current log sequence         1
SQL>
SQL>  select NAME,OPEN_MODE ,DATABASE_ROLE,CURRENT_SCN,FLASHBACK_ON from v$database;
NAME    OPEN_MODE        DATABASE_ROLE  CURRENT_SCN FLASHBACK_ON
--------- -------------------- ---------------- ----------- ------------------
ORCL    READ WRITE         PRIMARY        2364180 YES
SQL> show user
USER is "SYS"
SQL> select to_char(systimestamp,'yyyy-mm-dd HH24:MI:SS') as sysdt , dbms_flashback.get_system_change_number scn from dual;
SYSDT        SCN
------------------- ----------
2020-09-27 15:52:26    2364190
SQL>  select * from V$FLASHBACK_DATABASE_LOG; # 查看数据库可恢复的时间点
OLDEST_FLASHBACK_SCN OLDEST_FL RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- --------- ---------------- -------------- ------------------------
       2328783 27-SEP-20       4320       31883264          388988928
SQL>

闪回数据归档

闪回数据归档:使得表具有回退到过去任何时间点的能力(前面提到的闪回查询、闪回表都会受限于撤销数据是否失效,如果撤销数据被覆盖重写了,闪回操作自然会失败;闪回删除则受限于表空间是否有足够可用空间) 而闪回数据归档,则没有这些限制。


该功能实现的步骤如下:


1、创建一个用户闪回数据归档的表空间

2、创建一个保留时间为一定时间的闪回归档

3、为某一个表启用闪回归档


示例如下:

SQL> show user
USER is "SYS"
SQL> conn song/123456
Connected.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
# 创建一个用户闪回数据归档的表空间
SQL> create tablespace another_test1 datafile 'test1.dbf' size 20m;
Tablespace created.
# 创建一个保留时间为一年时间的闪回归档
SQL> create flashback archive test1_flahback_archive tablespace another_test1 retention 1 year;
Flashback archive created.
# 赋予用户归档的权限
SQL> grant flashback archive on test1_flahback_archive to song;
Grant succeeded.
# 为 another_test1 表启用闪回归档
SQL> alter table another_test1 flashback archive test1_flahback_archive;
Table altered.
SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
# 查哪些表已经启用了闪回数据归档
SQL> select table_name from dba_flashback_archive_tables;
TABLE_NAME
------------------------------
ANOTHER_TEST1
SQL> set line 300
SQL> col FLASHBACK_ARCHIVE_NAME for a50
SQL> col tablespace_name for a50
SQL> col quota_in_mb for a50
# 查看有关闪回数据归档所使用的表空间的信息
SQL> select flashback_archive_name,tablespace_name,quota_in_mb from dba_flashback_archive_ts;
FLASHBACK_ARCHIVE_NAME           TABLESPACE_NAME              QUOTA_IN_MB
-------------------------------------------------- -------------------------------------------
TEST1_FLAHBACK_ARCHIVE           ANOTHER_TEST1
SQL> # 查询数据库中所有的闪回数据归档
SQL> select flashback_archive_name,retention_in_days from dba_flashback_archive;
FLASHBACK_ARCHIVE_NAME           RETENTION_IN_DAYS
-------------------------------------------------- -----------------
TEST1_FLAHBACK_ARCHIVE             365
SQL>

取消对于数据表的闪回归档可以使用如下命令:


alter table table_name no flashback archive;

下面来实际操作一下闪回数据归档 首先记录一下SCN,从数据库表中删除部分数据:

原表数据内容如下:

SQL> select * from another_test1;
  ID NAME       CURTIME
---------- ---------------- ---------------------------------------------------------------------------
   1 post       27-SEP-20 02.05.11.000000 PM
   2 orac       27-SEP-20 02.06.02.000000 PM
   3 mysq       27-SEP-20 02.06.02.000000 PM
   4 redi       27-SEP-20 02.06.35.000000 PM
SQL>

通过闪回查询如下:

SQL>  select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
     2367563
SQL> delete from another_test1 where id <= 2;
2 rows deleted.
SQL> commit;
Commit complete.
SQL> select count(*) from another_test1 as of scn 2367563;
  COUNT(*)
----------
   4
SQL>

其查询计划如下:

SQL> explain plan for select count(*) from another_test1 as of scn 2367563;
Explained.
SQL> select count(*) from another_test1 as of scn 2367563;
  COUNT(*)
----------
   4
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------
Plan hash value: 3878810653
----------------------------------------------------------------------------
| Id  | Operation    | Name    | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |   1 |   6   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |       |   1 |    |    |
|   2 |   TABLE ACCESS FULL| ANOTHER_TEST1 |   4 |   6   (0)| 00:00:01 |
----------------------------------------------------------------------------
9 rows selected.
SQL> 

接下来执行一段代码,使UNDO数据老化并覆盖。之后再来看一下闪回数据归档发挥作用的闪回查询,通过执行计划能够看到和之前查询执行方式的不同:

SQL> begin
  delete from another_test1 where rownum < 2;
  commit;
  end;
  /  2    3    4    5  
PL/SQL procedure successfully completed.
SQL> select * from another_test1;
  ID NAME                 CURTIME
---------- -------------------------------------------------- --------------------------------------------
   4 redi                 27-SEP-20 02.06.35.000000 PM
SQL> select count(*) from another_test1 as of scn 2367563;
  COUNT(*)
----------
   4
SQL> explain plan for select count(*) from another_test1 as of scn 2367563;
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------
Plan hash value: 1720804579
----------------------------------------------------------------------------------------------------------
| Id  | Operation     | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |          |     1 |       |    13   (8)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE     |          |     1 |       |      |        |       |       |
|   2 |   VIEW        |          |     3 |       |    13   (8)| 00:00:01 |       |       |
|   3 |    UNION-ALL      |          |       |       |      |        |       |       |
|   4 |     PARTITION RANGE SINGLE|          |     2 |    52 |     3   (0)| 00:00:01 |     1 |     1 |
|*  5 |      TABLE ACCESS FULL    | SYS_FBA_HIST_75607 |     2 |    52 |     3   (0)| 00:00:01 |     1 |     1 |
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------
|*  6 |     FILTER      |          |       |       |      |        |       |       |
|*  7 |      HASH JOIN OUTER    |          |     1 |  2040 |    10  (10)| 00:00:01 |       |       |
|*  8 |       TABLE ACCESS FULL   | ANOTHER_TEST1      |     1 |    12 |     6   (0)| 00:00:01 |       |       |
|*  9 |       TABLE ACCESS FULL   | SYS_FBA_TCRV_75607 |     2 |  4056 |     3   (0)| 00:00:01 |       |       |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   5 - filter("ENDSCN">2367563 AND "ENDSCN"<=2367777 AND ("STARTSCN" IS NULL OR "STARTSCN"<=2367563))
   6 - filter("STARTSCN"<=2367563 OR "STARTSCN" IS NULL)
PLAN_TABLE_OUTPUT
----------------------------------------------------------
   7 - access("T".ROWID=CHARTOROWID("RID"(+)))
   8 - filter("T"."VERSIONS_STARTSCN" IS NULL)
   9 - filter(("ENDSCN"(+) IS NULL OR "ENDSCN"(+)>2367777) AND ("STARTSCN"(+) IS NULL OR
        "STARTSCN"(+)<2367777))
Note
-----
   - dynamic sampling used for this statement (level=2)
30 rows selected.
SQL>

通过以上执行计划可以看到,查询闪回来自SYS_FBA_TCRV_75607系统表,该表隶属于闪回归档表空间,用于记录闪回数据:

SQL> set linesize 100
SQL> desc SYS_FBA_TCRV_75607
 Name                  Null?  Type
 ----------------------------------------------------- -------- ------------------------------------
 RID                VARCHAR2(4000)
 STARTSCN             NUMBER
 ENDSCN               NUMBER
 XID                RAW(8)
 OP               VARCHAR2(1)
SQL> select count(*) from SYS_FBA_TCRV_75607;
  COUNT(*)
----------
   3
SQL> select * from SYS_FBA_TCRV_75607;
RID          STARTSCN     ENDSCN XID        O
-------------------- ---------- ---------- ---------------- -
AAASe9AAEAAAAI/AAA  2367600      06000C0004060000
AAASe9AAEAAAAI/AAB  2367600      06000C0004060000
AAASe9AAEAAAAI/AAC  2368015      08001F0001060000
SQL> 

闪回功能生成的字典对象有多个,通过查询USER_TABLES / USER_OBJECTS视图可以获得这些对象的详细信息:

SQL> select table_name,tablespace_name from user_tables where table_name like '%FBA%';
TABLE_NAME           TABLESPACE_NAME
------------------------------ --------------------------------------------------
SYS_FBA_DDL_COLMAP_75607   ANOTHER_TEST1
SYS_FBA_TCRV_75607         ANOTHER_TEST1
SYS_FBA_HIST_75607
SQL> select object_name,object_type from user_objects where object_name like '%FBA%';
OBJECT_NAME          OBJECT_TYPE
------------------------------ -------------------
SYS_FBA_TCRV_IDX_75607         INDEX
SYS_FBA_TCRV_75607             TABLE
SYS_FBA_HIST_75607             TABLE PARTITION
SYS_FBA_HIST_75607             TABLE
SYS_FBA_DDL_COLMAP_75607       TABLE
SQL>

还可以通过数据字典视图来查看关于闪回归档表的记录:

SQL> select * from user_flashback_archive_tables;
TABLE_NAME           OWNER_NAME         FLASHBACK_ARCHIVE_NAME      ARCHIVE_TABLE_NAME      STATUS
------------------------------------------------------------ ---------------------------------------------- ---------
ANOTHER_TEST1          SONG           TEST1_FLAHBACK_ARCHIVE      SYS_FBA_HIST_75607      ENABLED
SQL>
# 可以通过dict字典查询和闪回归档有关的数据字典表
SQL> select table_name from dict where table_name like '%FLASHBACK_ARCHIVE%';
TABLE_NAME
------------------------------
DBA_FLASHBACK_ARCHIVE
DBA_FLASHBACK_ARCHIVE_TABLES
DBA_FLASHBACK_ARCHIVE_TS
USER_FLASHBACK_ARCHIVE
USER_FLASHBACK_ARCHIVE_TABLES
SQL>

本文小结:


闪回查询 包括基本闪回查询,闪回表等技术都依赖于撤销数据(还有一类闪回技术为闪回事务,可以对指定事务进行闪回操作,原理类似,借助于撤销数据来构建用于反转事务的SQL语句),依赖于撤销数据,则自然受限于撤销数据的保留时间,可能会由于撤销数据被覆写而导致闪回失败


闪回删除 则是由于10g版本后对表的删除仅表现为一个rename操作,引入回收站的概念,但此回收站仅是当前表空间的一块逻辑划分,所以会受限于当前表空间的可用空间的限制


闪回归档 可提供查询或回退到过去任意时间点的功能


闪回数据库 则是一中更极端的数据库恢复功能,相当于不完整恢复,依赖于闪回日志


相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
5天前
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
17 7
|
5天前
|
Oracle 关系型数据库 数据库
oracle数据库技巧
【10月更文挑战第25天】oracle数据库技巧
11 6
|
5天前
|
存储 Oracle 关系型数据库
Oracle数据库优化策略
【10月更文挑战第25天】Oracle数据库优化策略
11 5
|
22天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
96 6
|
20天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
55 3
Mysql(4)—数据库索引
|
22天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
58 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
|
5天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
36 2
|
8天前
|
存储 关系型数据库 MySQL
MySQL vs. PostgreSQL:选择适合你的开源数据库
在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个。它们都有着强大的功能、广泛的社区支持和丰富的生态系统。然而,它们在设计理念、性能特点、功能特性等方面存在着显著的差异。本文将从这三个方面对MySQL和PostgreSQL进行比较,以帮助您选择更适合您需求的开源数据库。
38 4
|
14天前
|
存储 关系型数据库 MySQL
如何在MySQL中创建数据库?
【10月更文挑战第16天】如何在MySQL中创建数据库?
|
18天前
|
SQL Oracle 关系型数据库
安装最新 MySQL 8.0 数据库(教学用)
安装最新 MySQL 8.0 数据库(教学用)
86 4

推荐镜像

更多