编辑手记:对于数据库的闪回功能,可能大家都不陌生,那么如何在多租户环境下使用该功能,如果关闭了表空间的闪回功能,会给数据库带来哪些影响?我们一起来学习。
本文来自周四大讲堂内容整理。
我们先说一下Flashback这个单词,我们大家常称它为闪回,可能有的人称它为回闪。Flashback 是oracle 9i 版本开始提供的一项特性,利用oracle查询多版本一致的特点,实现从回滚段中读取一定的时间内在表中操作过的数据。
Flashback Database是Oracle10g的新增功能,在启动Flashback Database之后,它定期将已发生变化的块写入闪回日志的日志文件中。这些日志不是由传统的Log Writer (LGWR) 进程写入,而是由一种称作Recovery Writer (RVWR)的新进程写入。这是Oracle10g的新增进程。
闪回日志是存储在闪回恢复区(Flash Recovery Area),闪回恢复区简称FRA。配置闪回恢复区,有两个参数:DB_RECOVERY_FILE_DEST和DB_RECOVERY_FILE_DEST_SIZE。
DB_RECOVERY_FILE_DEST是用来指定FRA的存储路径,可以指定一个文件系统下的路径,也可以指定ASM磁盘组,但是不能将该路径指向一个裸设备。RAC数据库要指定共享存储上。
DB_RECOVERY_FILE_DEST_SIZE这个参数是指定FRA最大可用空间。建议分配大一些,如果剩余空间不足15%的时候,它将会在alert中增加告警,提示空间不足。但此时不会影响数据库正常运行。
可以通过视图V$FLASHBACK_DATABASE_LOG、v$flashback_database_stat查看闪回日志及数据库状态。当需要Flashback Database时,通过Flashback Log中保存的数据,就可以快速将oracle数据库恢复到指定时间点块的状态,然后通过应用重做日志,将数据库恢复到一致状态。
闪回数据库:
使用闪回数据库,通过还原自先前某个时间点以来发生的所有更改,可快速将数据库恢复到那个时间的状态。因为不需要还原备份,所以此操作速度很快。可以使用此功能还原导致逻辑数据损坏的更改。
使用闪回数据库时,Oracle DB 可使用过去的块映像回退对数据库的更改。在正常数据库操作期间,Oracle DB 会不定期地将这些块映像记录在闪回日志中。闪回日志将按顺序写入并且不进行归档。Oracle DB 会自动在快速恢复区中创建、删除闪回日志和调整它的大小。您仅需出于监视性能目的而关注闪回日志,并确定为快速恢复区分配了多少磁盘空间以存放闪回日志。
使用闪回数据库倒回数据库所需的时间与需回退到多久以前以及目标时间之后发生的数据库活动量成比例。还原和恢复整个数据库所需的时间会长得多。闪回日志中的前像仅用于将数据库还原至过去的某一时间点,而前滚恢复则用于将数据库恢复到与过去某个时间一致的状态。Oracle DB 可将数据文件恢复至以前的时间点,但辅助文件除外,如初始化参数文件。
启用闪回数据库功能时,会启动RVWR(闪回写进程)后台进程。此后台进程按顺序将闪回数据库数据从闪回缓冲区写入闪回数据库日志,这些日志会被循环使用。随后,当发出FLASHBACK DATABASE 命令时,系统使用闪回日志还原块的前像,然后使用重做数据前滚到所需的闪回时间。
启用闪回数据库的开销取决于数据库的读/写混合工作量。因为查询不需要记录任何闪回数据,所以工作量的写操作量越大,启用闪回数据库的开销就越高。可以从v$flashback_database_stat查看在一个时间段内数据库闪回日志记录的信息。
在一个END_TIME -BEGIN_TIME时间段内:
FLASHBACK_DATA记录写闪回日志大小;(单位:字节)
DB_DATA记录数据库读写大小;(单位:字节)
REDO_DATA记录redo日志的大小;(单位:字节)
ESTIMATED_FLASHBACK_SIZE记录预估满足保留时间所需要的空间大小。(单位:字节)
CON_ID代表的是容器ID。
字段含义如下:
OLDEST_FLASHBACK_SCN 保留的最低系统改变号;
OLDEST_FLASHBACK_TIME 最低系统改变号的时间;
RETENTION_TARGET 闪回日志保留时间(单位:时间);
FLASHBACK_SIZE 当前闪回日志的大小(单位:字节);
ESTIMATED_FLASHBACK_SIZE 预估满足保留时间所需要的空间大小(单位:字节);CON_ID代表的是容器ID。
闪回日志可以通过参数指定保留时间,db_flashback_retention_target。默认值为:1440 minutes。
实验步骤:
1、首先,我们开启数据库闪回功能:
mkdir -p /u01/app/oracle/fast_recovery_area
alter system setdb_recovery_file_dest_size=10G;
alter system setdb_recovery_file_dest='/u01/app/oracle/fast_recovery_area' scope=both;
shutdown immediate;
startup mount;
alter database archivelog;
alter database flashback on;
alter database open;
查看当前数据库实例状态:
set lines 200
col name for a30
select con_id,name,open_mode from v$pdbs;
开启PDB实例:
alter session set container=PERFEADER;
alter pluggable database PERFEADER open;
我们来创建测试表空间,测试用户:
查看表所在默认表空间:
set lines 200
col TABLE_NAME for a20
select table_name,tablespace_name fromuser_tables;
查看表的数据量:
select count(*) from perfeader.test;
select count(*) from perfeader.test1;
查询当前数据库scn:
select current_scn from v$database;
删掉表test中20000行数据:
delete from perfeader.test where rownum<=20000;
commit;
查询当前数据库scn:
select current_scn from v$database;
查询当前test表中数据量:
select count(*) from perfeader.test;
再向表中插入20行数据,然后commit查询表perfeader.test表的数据量。
insert into perfeader.test select * fromdba_objects where rownum <= 20;
commit;
等一下,测试将数据闪回到scn= 1469627,delete数据之后,insert之前。
操作 |
Scn |
表(TEST)数据量 |
表(TEST1)数据量 |
Create table |
72612 |
38 |
|
Delete test 数据 |
52612 |
38 |
|
commit |
1469627 |
||
Insert test 数据 |
52632 |
38 |
|
Commit |
查询开启闪回的表空间:
select * from v$tablespace;
接下来查看数据库是否开启闪回:
select flashback_on from v$database;
关闭表空间test的闪回:
alter tablespaceTEST flashback off;
关闭数据库,闪回数据库到scn=1469627:
conn / as sysdba
shutdown immediate
startup mount
flashback database to scn 1469627;
这个时候,我们能够看到闪回报错为无法闪回数据文件13,没有闪回日志。
开启数据库,开启表空间test闪回,需要在PDB实例开启:
alter session set container=PERFEADER;
alter tablespace TEST flashback on;
conn / as sysdba
alter database open;
alter session set container=PERFEADER;
select * from v$tablespace;
要切换到perfeader实例,才可以开启表空间test01的闪回:
我们再创建一个表空间test01,测试关闭该表空间的闪回功能,是否会有不一样的报错?
开启pdb实例,创建表空间test01:
alter pluggable database PERFEADER open;
create tablespace TEST01 datafile'/u01/app/oracle/oradata/PROD/test01_01.dbf' size 100M autoextend on;
alter tablespace TEST01 flashback off;
select * from v$tablespace;
闪回到表空间test的delete数据的时间点scn=1469627
conn / as sysdba
shutdown immediate
startup mount
flashback database to scn 1469470;
可以发现,表空间TEST01是关闭闪回功能的,我们闪回到test01表空间创建之前的时间点也是无法闪回的。我们可以看出闪回日志中的表空间必须是连续,而且没有表空间是关闭闪回的。
问题1:关闭表空间的闪回功能,会给出什么告警信息?
结论:如果数据库中有表空间没有开启闪回,将告警显示没有该表空间的闪回日志可以闪回。无论是在开启数据库闪回之前,还是之后,都将会报没有闪回日志。说明,如果在一个连续的数据库闪回日志,该闪回日志过程中某一个表空间关闭了闪回,都将无法将数据库闪回到之前的某一时间点。
开启数据库,还是相同的步骤重新创建用户,表空间及表:
create tablespace TEST02 datafile '/u01/app/oracle/oradata/PROD/test02_01.dbf'size 100M autoextend on;
create user allen identified by allendefault tablespace TEST02 account unlock;
grant dba to allen;
conn allen/allen@perfeader
create table allen.test as select * fromdba_objects;
create table allen.test1 tablespace usersas select * from dba_users;
查看表所在表空间:
select table_name,tablespace_name fromuser_tables;
查看该表空间中表的数据:
select count(*) from allen.test;
select count(*) from allen.test1;
先关闭表空间TEST02闪回功能,稍后闪回的时候我们将不闪回该表空间:
alter tablespaceTEST02 flashback off;
查看perfeader 用户,users表空间下表TEST1的数据:
select count(*) from perfeader.TEST1;
从perfeader用户表TEST1中删除一条数据:
delete from perfeader.TEST1 whereUSERNAME='SYSTEM';
COMMIT后查看当前数据库SCN:
COMMIT;
删除1行之后commit,查询SCN号,这个时候perfeader.test1表有37行,TEST没有改变.
操作 |
Scn |
表(TEST)数据量 |
表(TEST1)数据量 |
Create table |
72612 |
38 |
|
Delete test 数据 |
52612 |
38 |
|
commit |
1469627 |
||
Insert test 数据 |
52632 |
38 |
|
Commit |
|||
Delete test1 数据 |
52632 |
37 |
|
Commit |
1470592 |
这时,我们又向allen用户下的表TEST,TEST1都插入数据,使其状态改变。
查询allen用户下表test,test1的数据量:
select count(*) from allen.test;
select count(*) from allen.test1;
第一步插入表test1:
insert into allen.TEST1 select * from allen.TEST1;
commit查询test,test1表的数据:
commit;
select count(*) from allen.TEST;
select count(*) from allen.TEST1;
查询当前scn:
select current_scn from v$database;
第二步插入表test2:
insert into allen.TEST select * from allen.TEST;
commit查询test,test1表的数据:
commit;
select count(*) from allen.TEST;
select count(*) from allen.TEST1;
select current_scn from v$database;
第三步插入表test1,test2:
insert into allen.TEST select * from allen.TEST;
insert into allen.TEST1 select * from allen.TEST1;
commit查询test,test1表的数据:
commit;
select count(*) from allen.TEST;
select count(*) from allen.TEST1;
select current_scn from v$database;
变化之后的数据,我们可以看一下下面的表格:
perfeader用户:
操作 |
Scn |
表(TEST)数据量 |
表(TEST1)数据量 |
Create table |
72612 |
39 |
|
Delete test 数据 |
52612 |
38 |
|
commit |
1469627 |
||
Insert test 数据 |
52632 |
38 |
|
Commit |
|||
Delete test1 数据 |
52632 |
37 |
|
Commit |
1470592 |
allen用户:
操作 |
Scn |
表(TEST)数据量 |
表(TEST1)数据量 |
Create table |
72631 |
39 |
|
Insert test1 数据后 |
72631 |
78 |
|
commit |
1470812 |
||
Insert test 数据后 |
145262 |
78 |
|
Commit |
1470885 |
||
Insert test,test1 数据后 |
290524 |
156 |
|
Commit |
1470968 |
insert test插入数据后这个时候allen用户下的表的数据是test(145262),test1(78),而perfeader用户下的数据是test(52632),test1(37)。
等一下,测试将数据闪回到scn=1470812。
我们再测试一下,test02表空间没有开启闪回功能,会报什么错误。
关闭数据库,启动数据库到mount,闪回数据库,scn= 1470812:
flashback database to scn 1470812;
闪回数据库表空间allen用户insert test数据后commit时间点,还是会报无test02_1.dbf闪回日志:
flashback database to scn 1470885;
尝试一下在pdb做闪回,告诉我们不允许在插入的数据库做闪回:
查看当前闪回日志中的信息发现,闪回最老的时间点是开启闪回数据库功能的时间:
alter session set nls_date_format='yyyy-mm-ddhh24:mi:ss';
select * from v$FLASHBACK_DATABASE_LOG;
select * from v$flashback_database_stat;
下面我们验证,将关闭闪回功能的表空间offline,是否能够闪回数据库?
alter database open;
alter session set container=PERFEADER;
alter pluggable database PERFEADER open;
alter tablespace TEST02 offline;
查询表空间online状态:
select TABLESPACE_NAME,status,ONLINE_STATUSfrom dba_data_files;
切换到CDB$ROOT实例,关闭数据库并闪回数据数据库到scn=1470812。
conn / as sysdba
shutdown immediate
startup mount
flashback database to scn 1470812;
当open数据库时,会提示是RESETLOGS开启,还是NORESETLOGS方式:
alter database open;
如果以RESETLOGS方式打开数据库:
alter database open RESETLOGS;
切换到PDB实例perfeader,并open:
alter session set container=PERFEADER;
select open_mode from v$database;
alter pluggable database PERFEADER open;
下面是从alert日志来看,数据库是使用归档日志、REDO日志恢复到SCN= 1470812+1:
打开redo日志前滚:
12c会依次打开undo表空间:CDB$ROOT->PDB$SEED-> PERFEADER
打开数据库perfeader,报ORA-01110错误:
当查看表空间test02的数据文件状态时,还是offline,并且闪回功能还是关闭的:
set lines 200 pages 200
col name for a53
selectfile#,name,status,checkpoint_change#,last_change# from v$datafile;
当查询test02表空间下的数据会报无法读取数据文件test02_01.dbf,报错如下:
如果以NORESETLOGS方式open数据库,会报如下错误:
SQL> alterdatabase open NORESETLOGS;
alter databaseopen NORESETLOGS
*
ERROR at line 1:
ORA-01610:recovery using the BACKUP CONTROLFILE option must be done
当recovery数据库后,这时可以open数据库了:
SQL> recoverdatabase;
Media recovery complete.
SQL> alterdatabase open;
Database altered.
接下来我们验证问题2.
问题2:关闭“表空间”的闪回,是否还可以闪回数据库?
以open noresetlogs或者open noresetlog方式打开后,如果想要恢复被offline的表空间需要进行以下recover 数据文件步骤:
ALTER DATABASE CREATE DATAFILE 15 AS'/u01/app/oracle/oradata/PROD/test02_01.dbf';
recover datafile 15;
alter database datafile 15 online;
最后查看一下数据文件,表空间的状态:
select file#,name,status,checkpoint_change#,last_change#from v$datafile;
select * from v$tablespace;
select file#,status,recover,CHECKPOINT_CHANGE#from v$datafile_header;
可以看到15号数据文件test02_01.dbf的检查点是比其他的数据文件检查点大。
查询test02表空间下的数据已经闪回到scn=1482450时间点:
select count(*) from allen.test;
select count(*) from allen.test1;
查看闪回后的数据,allen.TEST表的数据是72631,TEST1的数据是78。正是scn=1470812时间点的数据。
结论:是可以做到表空间关闭了闪回功能,而其他的表空间没有关闭闪回功能,将关闭闪回的表空间offline后,可以将数据库闪回到指定的时间点,而数据库闪回后需要将关闭闪回的表空间数据文件recover,并online该表空间,数据就可以恢复到指定的时间点。
总结:
序号 |
问题 |
结果 |
1 |
关闭表空间的闪回功能,闪回数据库会给出什么告警信息? |
如果数据库中有表空间没有开启闪回,将告警显示没有该表空间的闪回日志可以闪回。无论是在开启数据库闪回之前,还是之后,都将会报没有闪回日志。说明,如果在一个连续的数据库闪回日志,该闪回日志过程中某一个表空间关闭了闪回,都将无法将数据库闪回到之前的某一时间点。 |
2 |
关闭“表空间”的闪回,是否还可以闪回数据库? |
是可以做到表空间关闭了闪回功能,而其他的表空间没有关闭闪回功能,将关闭闪回的表空间offline后,可以将数据库闪回到指定的时间点,而数据库闪回后需要将关闭闪回的表空间数据文件recover,并online该表空间,数据就可以恢复到指定的时间点。 |
文章转自数据和云公众号,原文链接