zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

oracle flashback详解3

Oracle 详解 Flashback
2023-09-27 14:28:18 时间

原文转自:http://www.askmaclean.com/archives/why-flashback-log-smaller-than-redolog.html

为什么Flashback Log产生量要远少于Redo Log?

有同学提问关于闪回数据库日志为什么远少于redo log?     RVWR( Recovery Writer)每3s检查flashback generate buffer中的block before image的具体算法是如何的? 是否每一次block change都需要RVWR写出block before image 到flashback log?

为了实现闪回数据库,Oracle需要记录数据块的前景象before image到一种新的日志中,这种日志被命名为flashback database logs闪回日志。   闪回日志总是被循环复用,连续写出。

在一个实例中当一个数据块首次被修改时,前台进程会将该数据块的before image拷贝到位于shared pool中的flashback log buffer中,RVWR进程定期地将flashback log buffer中的记录刷新到磁盘上。 在DBWR进程可以写出相关脏块到磁盘之前,DBWR必须保证该buffer header相关FBA(Flashback Byte Address)的flashback log buffer已经写出到闪回日志。 这被称作 先写闪回日志 机制。

在常规的闪回日志维护操作中 , RVWR进程定期地插入闪回标记(flashback markers)到flashback database logs中。 闪回标记(flashback markers)的作用是在闪回数据库时告知Oracle如何flashback 到之前的某个时间点。  在闪回操作执行过程中, Oracle 会用闪回标记(flashback markers)中的信息来决定多大范围的flashback database log需要用来还原数据块景象block image; 之后Oracle 会利用前向恢复(forward recovery)的方式把数据库穿越到用户指定闪回的SCN或者时间点。

 

flashback markers for example:

 

 **** Record at fba: (lno 1 thr 1 seq 1 bno 4 bof 8184) ****

 RECORD HEADER:

 Type: 3 (Skip) Size: 8132

 RECORD DATA (Skip):

 **** Record at fba: (lno 1 thr 1 seq 1 bno 4 bof 52) ****

 RECORD HEADER:

 Type: 7 (Begin Crash Recovery Record) Size: 36

 RECORD DATA (Begin Crash Recovery Record):

 Previous logical record fba: (lno 1 thr 1 seq 1 bno 3 bof 316)

 Record scn: 0x0000.00000000 [0.0]

 **** Record at fba: (lno 1 thr 1 seq 1 bno 3 bof 8184) ****

 RECORD HEADER:

 Type: 3 (Skip) Size: 7868

 RECORD DATA (Skip):

 **** Record at fba: (lno 1 thr 1 seq 1 bno 3 bof 316) ****

 RECORD HEADER:

 Type: 2 (Marker) Size: 300

 RECORD DATA (Marker):

 Previous logical record fba: (lno 0 thr 0 seq 0 bno 0 bof 0)

 Record scn: 0x0000.00000000 [0.0]

 Marker scn: 0x0000.0060e024 [0.6348836] 06/13/2012 15:56:35

 Flag 0x0

 Flashback threads: 1, Enabled redo threads 1

 Recovery Start Checkpoint:

 scn: 0x0000.0060e024 [0.6348836] 06/13/2012 15:56:12

 thread:1 rba:(0x80.180.10)

 Flashback thread Markers:

 Thread:1 status:0 fba: (lno 1 thr 1 seq 1 bno 2 bof 8184)

 Redo Thread Checkpoint Info:

 Thread:1 rba:(0x80.180.10)

 **** Record at fba: (lno 1 thr 1 seq 1 bno 2 bof 8184) ****

 RECORD HEADER:

 Type: 3 (Skip) Size: 8168

 RECORD DATA (Skip):

 End-Of-Thread reached

 

需要注意的是: 不是数据库中的每一次block change 都会触发before image被记录到闪回日志flashback log中。 如果每一次block change都记录flashback log record 那么闪回日志会要比 redo log大的多!因为毕竟flashback log 是记录整个块的before image 而 redo log只记录 change vector 。  Oracle对于闪回日志使用一种即能够保证可以将数据库一致地穿越到某个历史时间点的状态,又不过分造成I/O损耗和生成大量闪回日志的方法:

对于hot block热块,Oracle仅在一段时间内记录一次block image到闪回日志; Oracle 内部通过闪回分界线(flashback barriers)实现这一点。在常规数据库状态下,flashback barriers被周期性的触发(一般为15分钟),对应每一个闪回分界线(flashback barriers)会有一个(flashback markers)被写出到闪回日志。

 

对于热块, 即那些频繁被change的数据库块, 闪回日志算法要求限制其写出到闪回日志的版本数。举例来说, 在15分钟内对于某个数据块仅限其写出一个版本到flashback log。虽然更多版本的before image有助于减少闪回数据库的时间,但是最小化有效闪回日志的容量是更重要的因素,比起实际闪回所用的时间来说。 为了实现这个目标,闪回日志算法引入了闪回分界线(flashback barriers), flashback barriers会被定期地触发,典型的例如15分钟一次。 对应每一个flashback barriers会有一个闪回标记(flashback markers)被插入到闪回日志中。常规情况下,对于每一个被修改的数据块在一个闪回区域(被分界线barriers分割的区域)内仅记录一个block image ,无论这个数据块在这段区域内被修改了多少次、被写出过多少次到磁盘上。

这就是为什么闪回日志flashback log要原少于redo log的产生量!

 

好了说了,这么多如果不亲身体验一下就太虚了, 我们来做以下的测试。

 

SQL select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

PL/SQL Release 11.2.0.3.0 - Production

CORE 11.2.0.3.0 Production

TNS for Linux: Version 11.2.0.3.0 - Production

NLSRTL Version 11.2.0.3.0 - Production

SQL select * from global_name;

GLOBAL_NAME

--------------------------------------------------------------------------------

www.oracledatabase12g.com

SQL create table flash_maclean (t1 varchar2(200)) tablespace users;

Table created.

SQL insert into flash_maclean values(MACLEAN LOVE HANNA);

1 row created.

SQL commit;

Commit complete.

SQL startup force;

ORACLE instance started.

Total System Global Area 939495424 bytes

Fixed Size 2233960 bytes

Variable Size 713034136 bytes

Database Buffers 218103808 bytes

Redo Buffers 6123520 bytes

Database mounted.

Database opened.

SQL update flash_maclean set t1=HANNA LOVE MACLEAN;

1 row updated.

SQL commit;
Commit complete.
SQL alter system checkpoint;
System altered.
SQL select dbms_rowid.rowid_block_number(rowid),dbms_rowid.rowid_relative_fno(rowid) from flash_maclean;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)
------------------------------------ ------------------------------------  
140431 4
datafile 4 block 140431 对应RDBA rdba: 0x0102248f (4/140431)
SQL ! ps -ef|grep rvwr|grep -v grep
oracle 26695 1 0 15:56 ? 00:00:00 ora_rvwr_G11R23
SQL oradebug setospid 26695
Oracle pid: 20, Unix process pid: 26695, image: oracle@nas.oracle.com (RVWR)
SQL ORADEBUG DUMP FBTAIL 1;
Statement processed.To dump the last 2000 flashback records , 以上ORADEBUG DUMP FBTAIL 1命令可以转出最近2000条的闪回记录
SQL oradebug tracefile_name


/s01/orabase/diag/rdbms/g11r23/G11R23/trace/G11R23_rvwr_26695.trc

在 TRACE文件中可以找到对应block的 before image 

 **** Record atfba: (lno 1 thr 1 seq 1 bno 55 bof 2564) ****

    RECORD HEADER:

      Type: 1(Block Image)  Size: 28

    RECORD DATA(Block Image):

      file#: 4 rdba: 0x0102248f

      Next scn:0x0000.00000000 [0.0]

      Flag: 0x0

      Block Size:8192

    BLOCK IMAGE:

      buffer rdba:0x0102248f

      scn:0x0000.00609044 seq: 0x01 flg: 0x06 tail: 0x90440601

      frmt: 0x02chkval: 0xc626 type: 0x06=trans data

Hex dump of block: st=0, typ_found=1

Dump of memory from 0x00002B1D94183C00 to 0x00002B1D94185C00

2B1D94183C000000A206 0102248F 0060904406010000  [.....$..D.`.....]

2B1D94183C100000C626 00000001 00014AD4 0060903A  [ ........J..:.`.]

2B1D94183C2000000000 00320002 01022488 00090006 [......2..$......]

2B1D94183C3000000CC8 00C00340000D0542 00008000  [....@...B.......]

2B1D94183C40006040BC 000F000A 00000920 00C002E4 [.@`..... .......]

2B1D94183C500017048F 00002001 0060904400000000  [..... ..D.`.....]

2B1D94183C6000000000 00010100 0014FFFF 1F6E1F77 [............w.n.]

2B1D94183C7000001F6E 1F770001 00000000 00000000  [n.....w.........]

2B1D94183C8000000000 00000000 00000000 00000000 [................]

        Repeat 500times

2B1D94185BD0 00000000 00000000 2C000000 4D120102 [...........,...M]

2B1D94185BE0 454C43414C204E41 2045564F 4E4E4148  [ACLEAN LOVE HANN]

2B1D94185BF0 01002C4143414D07 4E41454C90440601  [A,...MACLEAN..D.]

Block header dump: 0x0102248f

 Object id onBlock? Y

 seg/obj:0x14ad4  csc: 0x00.60903a  itc:2  flg: E typ: 1 - DATA

     brn: 0  bdba: 0x1022488 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 Itl           Xid                  Uba         Flag Lck        Scn/Fsc

0x01  0x0006.009.00000cc8  0x00c00340.0542.0d  C---   0  scn 0x0000.006040bc

0x02   0x000a.00f.00000920  0x00c002e4.048f.17  --U-   1  fsc 0x0000.00609044

bdba: 0x0102248f

data_block_dump,data header at 0x2b1d94183c64

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x2b1d94183c64

     76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f77

avsp=0x1f6e

tosp=0x1f6e

0xe:pti[0]     nrow=1  offs=0

0x12:pri[0]    offs=0x1f77

block_row_dump:

tab 0, row 0, @0x1f77

tl: 22 fb: --H-FL-- lb: 0x2  cc: 1

col  0: [18]  4d 41 43 4c 45 41 4e 20 4c 4f56 45 20 48 41 4e 4e 41

end_of_block_dump

SQL select dump(MACLEAN LOVE HANNA,16) from dual;

DUMP(MACLEANLOVEHANNA,16)

--------------------------------------------------------------------

Typ=96 Len=18: 4d,41,43,4c,45,41,4e,20,4c,4f,56,45,20,48,41,4e,4e,41

若我们在短期内在多个事务内反复更新同样的数据块,其在flashback log中的before image版本也不会大幅增长

 

create table flash_maclean1 (t1 int) tablespace users;

SQL select vs.name, ms.value

 2 from v$mystat ms, v$sysstat vs

 3 where vs.statistic# = ms.statistic#

 4 and vs.name in (redo size,db block changes);

NAME VALUE

---------------------------------------------------------------- ----------

db block changes 0

redo size 0

SQL select name,value from v$sysstat where name like flashback log%;

NAME VALUE

---------------------------------------------------------------- ----------

flashback log writes 49

flashback log write bytes 9306112

SQL begin

 2 for i in 1..5000 loop

 3 update flash_maclean1 set t1=t1+1;

 4 commit;

 5 end loop;

 6 end;

PL/SQL procedure successfully completed.

SQL select vs.name, ms.value

 2 from v$mystat ms, v$sysstat vs

 3 where vs.statistic# = ms.statistic#

 4 and vs.name in (redo size,db block changes);

NAME VALUE

---------------------------------------------------------------- ----------

db block changes 20006

redo size 3071288

SQL select name,value from v$sysstat where name like flashback log%;

NAME VALUE

---------------------------------------------------------------- ----------

flashback log writes 52

flashback log write bytes 10338304

 

在以上的测试中可以看到 对于hot block,在产生20006 个block changes的情况下 产生了 3000k 的redo log 和 大约1000k的 flashback log 。