欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Oracle 下马观花看redo

程序员文章站 2022-05-25 19:45:09
领导*在《在鲁迅艺术学院的讲话》中说过这样一段话:俗话说,走马看花不如驻马看花,驻马看花不如下马看花,我 希望你们都要下马看花。是的,有时候技术学到一定阶段,很多细节知识确实需要我们 穷波讨源,细致的研究,今天和大家聊得是alert 日志中出现Private strand flush not c... ......
-----------------------------------------

--lerning content :oracle 下马观花看redo
--author :如人饮水冷暖自知
--版权所有 :首发于ora-600团队微信公众号:

《oracle 蓝莲花》:转载请注明出处以及作者 

技术分享交流qq群:851604218 

2019年3月中旬,有技术分享交流课程,欢迎加群探讨 

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

 

 

 

Oracle 下马观花看redo

引言

下马看花-redo

Oracle 下马观花看redo


        领导*在《在鲁迅艺术学院的讲话》中说过这样一段话:俗话说,走马看花不如驻马看花,驻马看花不如下马看花,我 希望你们都要下马看花。是的,有时候技术学到一定阶段,很多细节知识确实需要我们 穷波讨源,细致的研究,今天和大家聊得是alert 日志中出现private strand flush not complete提示,这提示背后的故事.



1

背景介绍


Oracle 下马观花看redo
Oracle 下马观花看redo



截图1为简单的qq沟通

初步了解dba排错思路和现场问题情况

Oracle 下马观花看redo


截图2为alert日志中具体的信息提示

Oracle 下马观花看redo

截图3为前台应用给出的另一个报错信息

Oracle 下马观花看redo

awr报告信息提示:

Oracle 下马观花看redo
Oracle 下马观花看redo


Oracle 下马观花看redo

一、分析思路:

Oracle 下马观花看redo


      1.对于log file switch (checkpoint incomplete)等待事件,容易误导dba的排查思路,awr报告里该等待事件平均等待 601.22毫秒,占用当前dbtime 31%,同时db cpu占用dbtime的比例达到41%。这里我们不妨分析这个等待事件产生的成因,log file switch (checkpoint incomplete)指的是当redo需要向下一组redo group切换的时候,发现下组日志是active活动状态的,简单的说就是下组日志中对应的一些buffer cache中的脏块压根没有写入到数据文件中,因此必须等待这些dirty block被flush完毕 后,才可以复用下一组redo group


     2.既然是把dirty block flush到datafile,那么自然是dbwn的工作,实际我们需要更多关注的是dbwn这个进程的写io负载情 况,那么awr里有8.3g的控制文件io负载是为什么,其实是dbw本身的io问题导致 lgwr不断查询control 文件获取redo 状态,获 取状态最根本的目的就是想知道究竟redo切换是否成功,所以后台产生大量控制文件io操作。



       3.在以前的文章中我们分享过log file sync等待事件,写redo很慢,从而导致gc buffer busy acquire /release 等待事件,其 实这个就比较方便定位,只要我们做了addm,可以看到诸如如下的提示:waits on event “log file sync” were the cause of significant database wait on “gc buffer busy” when releasing a data block. waits on event“log file sync” in this instance can cause global cache contention on remote instances,那么基本可以确认gc buffer busy的源头是log file sync(虽然本质上不是),那么优先解决log file sync的问题。



Oracle 下马观花看redo

二、工作原理分析

历史追溯

       oracle 9i时代,企业业务数据还没井喷,无论是事务还是日志生成量都相对较少,那个年代没有所谓大数据的概念,基本都 维持在一次变更,一条数据,一次内存分配即可完成的状态,随着企业业务数据激增,尤其oltp系统,老的redo机制已经无法满足 高并发,大写入量的需求,到10g版本以后oracle推出了private redo 和imu,也就是in-memory undo的机制,这样一来,一个 进程就可以以整个事务的方式去工作,生成所有的改变向量,并将它们存入私有重做日志缓冲区,也就是private redo log buffer 中,当事务提交时,进程将存于私有重做日志缓冲区的记录复制到公共的重做日志缓冲区,这时,跟传统的重做日志缓冲区工作原 理保持一致,那么写到重做日志文件的过程,一个进程在一个事务里只需要获得一次公共的redo allocation latch,而不是每次变 更都要获取一次latch。


赏花望月-imu

     既然是下马看花,为了方便大家理解,我们至少要搞懂几个事情,才能做到真正意义的赏花望月,imu机制带来的in memory undo latch是否影响数据库负载,是否有威胁,同时分析重做日志文件,搞清楚redo entry都记录了什么,同时我们还要 分析x$kcrfstrand x$ktifp理解各种实例活动信息之间的关联关系,这里涉及的技术知识点比较多,由于篇幅原因,和大家分享两个 相对重要的:

     1. 关于redo方面增量的基础结构由两组内存结构组成,一组是x$kcrfstrand私有redo区域,主要处理前滚改变向量, 另一组x$ktifp imu区域,处理undo改变向量,私有redo区域里面也包含传统的公共重做日志缓冲区,因此如果查询这个固化视图 发现有两类不同的信息,不要担心,是正常现象。 

      2. x$ktifp表示imu区域中的池个数,取决于持有事务的细节v$transaction的数组大小,它由oracle的参数 transactions设定,但是这个参数通常随session 或者processes参数调整自动更新,基本上,池的个数默认为transactions/10,比 如transactions是1000,那么池的个数就是100,每个池是由自己的imu latch受保护的。 

      3. x$ktifp中的每一条记录在x$kcrfstrand中都有与之对应的一条私有redo记录,不过x$kcrfstrand还会涉及其他信 息,公共的redo记录个数由cpu_count参数决定,算法是ceiling(1 + cpu_count/16) 

     4. x$kcrfstrand中的每一条私有重做记录都由自身的redo allocation latch来保护,每一条公共的重做记录都由传统 的redo copy latch保护,每个cpu一个redo copy latch



Oracle 下马观花看redo

三、下马看花第一步

Oracle 下马观花看redo

Oracle 下马观花看redo

        根据oracle官方介绍为了减少redo allocation latch等待,在oracle 9i中,引入了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_parallelism控 制的;

        在10g中,该参数成为隐含参数,并新增参数_log_parallelism_max控制shared strand的最大数量; _log_parallelism_dynamic则控制是否允许shared strand数量在_log_parallelism和_log_parallelism_max之间动态变化,这里需

要注意_log_parallelism在12c版本已经弃用

三人行必有我师

Oracle 下马观花看redo

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