理解redo(4)redo log buffer和LGWR

二者的由来,有二:

1)redo records的产生十分频繁
2)server process每次产生的量却不大

倘若每次产生的redo就须由大量高并发sp写入redo log file,则存在两个问题:

1)I/O开支大
2)redo file争用

由此,oracle在redo log机制中引入了log buffer和LGWR。

redo log buffer缓存了sp产生的redo records,提高了oracle高并发的性能。LGWR则将log buffer中的records批量flush到redo file。对于oracle而言,只要对数据库的改变写入到redo log file,那么相关的事务绝不丢失。

在事务提交时,会产生一个commit的change vector,这个CV被写入log buffer后,sp会发出一个信号,要求LGWR将和这个事务相关的redo records写入到redo file,只有这个事务相关的redo全部安全着陆,sp才会向client发出事务提交成功的信息“Commit Complited”。

由于redo entries实是娇贵且重要。为了保障redo records的安全,oracle还实现了:

1)LGWR绕过OS的缓冲直接写到redo log file,避免宕机而丢失redo
2)redo log file的block size和数据库的block size是完全不同的,事实上,和OS的I/Oblock size如出一辙,从而一个redo block在一次物理i/o时可以同时写入而不出现块断裂。

redo buffer是一个循环使用顺序读写的buffer:
1)redo records写入log buffer是按顺序的
2)当log buffer写满后,会从头开始写(这种情况是不会出现的)

log buffer数据的写入是由sp完成的,这个写操作属于高并发,而log buffer的空间分配是个串行操作。所以需要锁的保护:
1)redo copy latch:写redo 到redo log buffer
2)redo allocation latch:控制log buffer空间分配

为了腾出更多的log buffer,oracle设计了LGWR写的触发条件:
1)commit时
2)1M redo entries时
3)超过_log_io_size参数指定的大小时

缺省值是LOG BUFFER大小的1/3,这个参数单位是REDO LOG BLOCK

SQL> col name for a15
SQL> col value for a10
SQL> 
SQL> select a.ksppinm name,b.ksppstvl value,a.ksppdesc description
  2  from x$ksppi a,x$ksppcv b
  3  where a.indx = b.indx
  4  and a.ksppinm like '%log_io_size%'
  5  /
 
NAME            VALUE      DESCRIPTION
--------------- ---------- --------------------------------------------------------------------------------
_log_io_size    0          automatically initiate log write if this many redo blocks in buffer


4) 每3秒
5)DWWn写之前写

LGWR写的具体过程:

1)先尝试获取redo writing latch,确保其他process不会继续触发lgwr(这里可能会产生log file sync等待事件

2)获取redo allocation latch(public redo allocation latch),防止有新的change vector继续写入log buffer,造成LGWR无法确定应该写多少redo.

3)LGWR确定写的范围(从上次lgwr启动所写的最后一个日志块到这个时间点时的最后一个被使用的所有写满or未写满的日志块)此时前台process仍可以向这个范围内的redo block(buffer)写内容(从PGA写)所以lgwr不阻碍其它进程获得redo copy latch(即:不阻止其它进程向log buffer 中可用块中写change vector)

4)确定redo block(buffer)后生成新SCN号

5)LGWR释放redo allocation latch与redo writing latch

6)LGWR需要等待 其它进程对要写入日志文件的block的更新操作完成(pga-log buffer的操作),通过判断日志block(buffer)上的redo copy latch是否都释放。

7)将第4步scn号copy到要写入logfile的log buffer的块头里,然后触发物理的写操作,将这些待写日志块写入redo file

LOG BUFFER大于3M浪费空间,对性能影响不大的观点”是错误的,因为存在LOG FILE SYNC等待事件:指等待LGWR将log buffer的数据写入到redo log file中。一般:
1)如果事务在做commit时,会有log file sync等待事件。
2)redo writing latch竞争过多,sp会有log file sync等待事件。
这种情况下,加大log buffer,适当调整_log_io_size大小,就可能可以减小log file sync等待事件。

计算redo的大小
法一:
利用下列sql语句在sql语句执行前后取差值即为此session产生的redo

19:33:31 hr@ORCL (^ω^) select name, value
19:33:59   2  from v$mystat a, v$statname b
19:33:59   3  where a.statistic# = b.statistic#
19:33:59   4  and b.name = 'redo size'
19:33:59   5  /

NAME            VALUE
---------- ----------
redo size        1084

19:34:01 hr@ORCL (^ω^) insert into t1 values(112,'yaoqinqin');

已创建 1 行。

19:36:54 hr@ORCL (^ω^) select name, value
19:37:08   2  from v$mystat a, v$statname b
19:37:08   3  where a.statistic# = b.statistic#
19:37:08   4  and b.name = 'redo size'
19:37:08   5  /

NAME            VALUE
---------- ----------
redo size        1084

19:37:12 hr@ORCL (^ω^) commit;

提交完成。

19:37:53 hr@ORCL (^ω^) select name, value
19:38:13   2  from v$mystat a, v$statname b
19:38:13   3  where a.statistic# = b.statistic#
19:38:13   4  and b.name = 'redo size'
19:38:14   5  /

NAME            VALUE
---------- ----------
redo size        1632



法二:基于一天产生的日志

Select trunc(completion_time),sum(blocks*block_size)/1024/1024 mb 
  from v$archived_log group by trunc(completion_time)
 order by trunc(completion_time)

TRUNC(COMPLETION_TI SUM(BLOCKS*BLOCK_SIZE)
------------------- ----------------------
2012/06/07 00:00:00               10374144
2012/06/08 00:00:00                3863040
................
2012/09/03 00:00:00               37682176
2012/09/04 00:00:00               48241152



你可能感兴趣的:(buffer)