Why does ORACLE make more Redo Log than Flashback Log ?

        今天周六,早上在家跑完步了,保证了相当的运动量(30分钟的慢跑+冲刺)。然后舒服得洗完澡,吃了(早餐+中餐),午觉后,应该是写博时间了:)

明天又要飞北京,最近一直在出差。身体确实是革命的本钱啊,能挺住,无压力~~

 

我们在10g学习闪回特性的时候,可能会有个疑问,同样是日志文件,为什么Flashback Log要比Redo Log 少的多呢?

这是由Flashback 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 flashback_on from v$database;

FLASHBACK_ON
------------------
YES

 

SQL> show parameter recover

NAME         TYPE  VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest       string  /u01/recovery_area
db_recovery_file_dest_size      big integer 1G
db_unrecoverable_scn_tracking      boolean  TRUE
recovery_parallelism       integer  0

 

--创建测试表

SQL> create table pjh1 (c1 number) tablespace users;

Table created.

 

SQL> insert into pjh1 (c1) values (0);

1 row created.

SQL> commit;

Commit complete.

 

 

 

--重新连接会话,并查看当前度量值

SQL>   1  select ss.name,ms.value
             2  from v$mystat ms,v$sysstat ss
             3  where ss.statistic#=ms.statistic#
             4* and ss.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                                                           17
flashback log write bytes                                        3383296

 

 

 

 

SQL> begin
  2  for i in 1..5000 loop
  3  update pjh1 set c1=c1+1;
  4  commit;
  5  end loop;
  6  end;
  7  /

PL/SQL procedure successfully completed.

 

SQL> select * from pjh1;

 C1
----------
      5000

--再次查看Redo Log 与 Flashback Log 的概况

SQL> 

  1  select ss.name,ms.value
  2  from v$mystat ms,v$sysstat ss
  3  where ss.statistic#=ms.statistic#
  4* and ss.name in ('redo size','db block changes')


NAME              VALUE
---------------------------------------------------------------- ----------
db block changes            20000
redo size           2990276

 

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

NAME              VALUE
---------------------------------------------------------------- ----------
flashback log writes        19
flashback log write bytes         4014080

 

现象的结论:

对于热块,在产生20000个block changes的情况下 产生了约 3000k 的redo log 和 大约630k  (即4014080-3383296)的 flashback log 。

 

 

 

原理概述:

实际上这个问题再往前一步,则为:

1. RVWR( Recovery Writer)每3s检查flashback generate buffer中的block before image的具体算法是如何的?

2. 是否每一次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或者时间点。

 

需要注意的是不是数据库中的每一次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的产生量!

 

现在做以下测试,顺便熟悉一下常用的oradebug方法:

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> create table pjh2 (c1 varchar2(200)) tablespace users;

Table created.

 

SQL> insert into pjh2 (c1) values ('BONDlovesU');         

1 row created.

 

SQL> commit;

Commit complete.

 

SQL> startup force
ORACLE instance started.

Total System Global Area 1043886080 bytes
Fixed Size      2234960 bytes
Variable Size    603981232 bytes
Database Buffers   432013312 bytes
Redo Buffers      5656576 bytes
Database mounted.
Database opened.


SQL> update pjh2 set c1='BOND';    --会产生一个前镜像块

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 pjh2;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)
------------------------------------ ------------------------------------
     535     4

 

datafile 4 block 535 对应RDBA rdba: 0x01000217 (4  /   535 转换为16进制)

 

SQL> ! ps -elf | grep rvwr| grep -v grep
0 S oracle   20777     1  0  75   0 - 316970 -     02:44 ?        00:00:00 ora_rvwr_papa

 

SQL> oradebug setospid 20777
Oracle pid: 20, Unix process pid: 20777, image: oracle@centos1.localdomain (RVWR)

 

SQL> oradebug dump fbtail 1;    --To dump the last 2000 flashback records
Statement processed.

 

SQL> oradebug tracefile_name   --得到指定spid 的trace文件,比手动拼接路径的方法简便不少
/u01/diag/rdbms/papa/papa/trace/papa_rvwr_20777.trc

 

(这时候,我们处于简便目的,可以将trace文件down到本地windows中,使用Editplus这类编辑器查看)

在trace文件中,使用  file#: 4 rdba: 0x01000217   定位,可找到:

 **** Record at fba: (lno 1 thr 1 seq 1 bno 642 bof 2076) ****
    RECORD HEADER:
      Type: 1 (Block Image)  Size: 28
    RECORD DATA (Block Image):
      file#: 4 rdba: 0x01000217
      Next scn: 0x0000.00000000 [0.0]
      Flag: 0x0
      Block Size: 8192
    BLOCK IMAGE:
      buffer rdba: 0x01000217
      scn: 0x0000.0010f393 seq: 0x02 flg: 0x04 tail: 0xf3930602
      frmt: 0x02 chkval: 0xddbf type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00002B87DD863C00 to 0x00002B87DD865C00
2B87DD863C00 0000A206 01000217 0010F393 04020000  [................]
2B87DD863C10 0000DDBF 00000001 00012C22 0010F393  [........",......]
2B87DD863C20 00000000 00320002 01000210 001E0003  [......2.........]
2B87DD863C30 00000353 00C000AB 00280090 00000001  [S.........(.....]
2B87DD863C40 00000000 00000000 00000000 00000000  [................]
        Repeat 1 times
2B87DD863C60 00000000 00010100 0014FFFF 1F761F8A  [..............v.]
2B87DD863C70 00001F76 1F8A0001 00000000 00000000  [v...............]
2B87DD863C80 00000000 00000000 00000000 00000000  [................]
        Repeat 501 times
2B87DD865BE0 00000000 00000000 00000000 012C0000  [..............,.]
2B87DD865BF0 4F420A01 6F6C444E 55736576 F3930602  [..BONDlovesU....]
Block header dump:  0x01000217
 Object id on Block? Y
 seg/obj: 0x12c22  csc: 0x00.10f393  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x1000210 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0003.01e.00000353  0x00c000ab.0090.28  ----    1  fsc 0x0000.00000000
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
bdba: 0x01000217
data_block_dump,data header at 0x2b87dd863c64
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x2b87dd863c64
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f8a
avsp=0x1f76
tosp=0x1f76
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f8a
block_row_dump:
tab 0, row 0, @0x1f8a
tl: 14 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [10]  42 4f 4e 44 6c 6f 76 65 73 55
end_of_block_dump

 

 

--回头查看一下前镜像的dunp结果,当然与trace文件中是一致的

SQL> select dump('BONDlovesU',16) from dual;        --

DUMP('BONDLOVESU',16)
--------------------------------------------
Typ=96 Len=10: 42,4f,4e,44,6c,6f,76,65,73,55

 

 

当然,阅读trace 文件是很费劲的,如何活用oradebug也是一个重要技巧,今后有机会,再加总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值