REDO申请原理及优化

        最近客户反馈他们的一个数据同步软件将生产数据同步到备库后,出现数据丢失的问题,想想ORACLE的redo落盘保护机制这么完善还没听说过有丢失的问题,如果真的有这个问题,崩溃恢复和一切需要用到redo的同步ADG等机制,还咋保障。应该是同步软件解析存在问题吧。

        这个问题后面软件运维人员最终答复是需要调整_log_parallelism_max=1,否则会出现不一致。先不管最终什么原因,先对这个参数研究一把。

      这是个redo相关的核心参数。

一、原理:Redo写入redo buffer的整个过程如下

        1、在PGA中生产Redo Enrey 

        2、服务进程获取Redo Copy latch(存在多个---CPU_COUNT*2)

        3、服务进程获取redo allocation latch(仅1个)

        4、分配log buffer

        5、 释放redo allocation latch

        6、 将Redo Entry写入Log Buffer

        7、释放Redo Copy latch

        第4步提到分配log buffer,这个是重哪里分配呢?别急,我们引入2个概念shared strand、private strand

二:shared strand

        为了减少redo allocation latch等待,在oracle 9.2中,引入了log buffer的并行机制。其基本原理就是,将log buffer划分为多个小的buffer,这些小的buffer被成为strand(为了和之后出现的private strand区别,它们被称之为shared strand)。每一个strand受到一个单独redo allocation latch的保护。多个shared strand的出现,使原来序列化的redo buffer分配变成了并行的过程,从而减少了redo allocation latch等待

         shared strand 的分配情况

        查看log buffer中内存空间分配的 shared strand个数数量(每一个shared strand的大小 = log_buffer/(shared strand数量)),也可以用下面语句查询

        select indx,strand_size_kcrfa from x$kcrfstrand where last_buf_kcrfa != '00';

三、Private strand

        为了进一步降低redo buffer冲突,在10g中引入了新的strand机制——Private strand。Private strand不是从log buffer中划分的,而是在shared pool中分配的一块内存空间

        Private strand的引入为Oracle的Redo/Undo机制带来很大的变化。每一个Private strand受到一个单独的redo allocation latch保护,每个Private strand作为“私有的”strand只会服务于一个活动事务。获取到了Private strand的用户事务不是在PGA中而是在Private strand生成Redo,当flush private strand或者commit时,Private strand被批量写入log文件中。如果新事务申请不到Private strand的redo allocation latch,则会继续遵循旧的redo buffer机制,申请写入shared strand中。事务是否使用Private strand,可以由x$ktcxb的字段ktcxbflg的

        对于使用Private strand的事务,无需先申请Redo Copy Latch,也无需申请Shared Strand的redo allocation latch,而是flush或commit是批量写入磁盘,因此减少了Redo Copy Latch和redo allocation latch申请/释放次数、也减少了这些latch的等待,从而降低了CPU的负荷

        每个Private strand的大小为65K。10g中,shared pool中的Private strands的大小就是活跃会话数乘以65K,而11g中,在shared pool中需要为每个Private strand额外分配4k的管理空间,即:数量*69k

        原理(优化后):Redo写入redo buffer的整个过程如下

        1、事务开始 

       2、申请Private strand的redo allocation latch (申请失败则申请Shared Strand的redo allocation latch)

        3、在Private strand中生产Redo Enrey

        4、Flush/Commit

        5、申请Redo Copy Latch

        6、服务进程将Redo Entry批量写入Log File

        7、释放Redo Copy Latch

        8、释放Private strand的redo allocation latch

        Private strand 的分配情况

        查看shared pool中分配的 Private strand个数数量

        select indx,strand_size_kcrfa from x$kcrfstrand where last_buf_kcrfa = '00';

        查看log file  中分配的 Private strand个数数量

参数_log_private_mul指定了使用多少logfile空间预分配给Private strand,默认为5。我们可以根据当前logfile的大小(要除去预分配给log buffer的空间)计算出这一约束条件下能够预分配多少个Private strand:

select count(1) "actual private strands" from x$kcrfstrand where last_buf_kcrfa = '00';

select trunc(((select bytes from v$log where status = 'CURRENT' and THREAD#=1) - (select value from v$parameter where name = 'log_buffer'))*   
         (select to_number(val.KSPPSTVL)   
            from sys.x$ksppi nam, sys.x$ksppsv val   
           where nam.indx = val.indx   
             AND nam.ksppinm = '_log_private_mul') / 100 / 66560)   
         as "calculated private strands" 
from dual; 

        查看有多少事务是否使用Private strand

查看有多少事务是否使用Private strand:(基本上发起一个事物,就会看到count(*) +1)
select decode(bitand(ktcxbflg, 4096),0,1,0) used_private_strand, count(*)   
from x$ktcxb   
where bitand(ksspaflg, 1) != 0   
and bitand(ktcxbflg, 2) != 0   
group by bitand(ktcxbflg, 4096);

        查看sga(shared pool)中内存空间Private strand的使用大小

以下查询结果应该是一致的:

select * from v$sgastat where name ='private strands';  

--10g
select trunc(value * KSPPSTVL / 100) * 65 * 1024   
from (select value from v$parameter where name = 'transactions') a,   
(select val.KSPPSTVL   
from sys.x$ksppi nam, sys.x$ksppsv val   
where nam.indx = val.indx   
AND nam.ksppinm = '_log_private_parallelism_mul') b;   

--11g
select trunc(value * KSPPSTVL / 100) * (65 + 4) * 1024   
from (select value from v$parameter where name = 'transactions') a,   
(select val.KSPPSTVL   
from sys.x$ksppi nam, sys.x$ksppsv val   
where nam.indx = val.indx   
AND nam.ksppinm = '_log_private_parallelism_mul') b;

查看sga(shared pool)中内存空间Private strand的使用大小历史分配趋势

select a.instance_number,to_char(b.end_interval_time,'yyyy-mm-dd hh24:mi:ss'),name,pool,bytes from dba_hist_sgastat a,dba_hist_snapshot b
where a.snap_id=b.snap_id
and a.name ='private strands'
order by 1,2;

四:各相关参数解释

1、参数_log_parallelism_max

关于shared strand的数量设置,16个cpu之内***默认为2,当系统中存在Oracle redo allocation latch等待时,每增加16个cpu可以考虑增加1个strand,***不应该超过8。并且_log_parallelism_max不允许大于cpu_count

shared strand的初始数据量是由参数log_parallelism控制的;在10g中,该参数成为隐含参数,并新增参数_log_parallelism_max控制shared strand的最大数量

在11g中,参数_log_parallelism被取消,shared strand数量由_log_parallelism_max、_log_parallelism_dynamic和cpu_count控制

​​​​​​​2、参数_log_parallelism_dynamic

_log_parallelism_dynamic则控制是否允许shared strand数量在_log_parallelism和_log_parallelism_max之间动态变化

​​​​​​​3、参数_log_private_mul

参数_log_private_mul指定了使用多少logfile空间预分配给Private strand,默认为5。我们可以根据当前logfile的大小(要除去预分配给log buffer的空间)计算出这一约束条件下能够预分配多少个Private strand

五:测试

        于是在测试环境(11G、机器配置不高)上进行了如下测试,3个session同时进行insert操作。在_log_parallelism_max=2和_log_parallelism_max=1(相当于不从shared pool去申请)时候,测试情况如下:

        测试结果表明(仅供参考):插入性能未受明显的影响,等待事件有所差异,但是总量差不多。可能是机器性能差的原因,和无法模拟生产混合场景的情况。没有很明显的测试出Private strand带来的好处。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值