ITPub博客

首页 > 数据库 > Oracle > LOG FILE SYNC概述(第二篇)

LOG FILE SYNC概述(第二篇)

原创 Oracle 作者:wei-xh 时间:2018-04-19 11:11:09 1 删除 编辑

Commit做了什么?

   commit与log file sync是息息相关的,在每次事务提交时,commit会触发增进系统的SCN(通过函数kcmgas),然后产生一个commit的改变向量被拷贝进log buffer中,commit的改变向量一旦被拷贝到log buffer中,会触发通知Lgwr进程刷新日志。commit的改变向量是用来描述数据块(undo头块)的改变的,commit之所以会产生改变向量是由于commit本身修改了undo段头块的事务表,如:修改了事务表中此事务的提交状态,提交SCN等信息,这些修改信息组合成了一个commit的改变向量。10G之前commit的改变向量都是stand alone(独立的)的redo record,10G之后由于出现了私有redo,commit的改变向量可以跟事务的其他改变向量一起组成一个redo record。在10G版本,commit产生的stand alone的redo record有140个字节,如果是非stand alone的会有72字节。我们来简单看一个commit产生的stand alone的redo record的内容:


REDO RECORD - Thread:1 RBA: 0x00010e.00000003.0010 LEN: 0x008c VLD: 0x05

SCN: 0x0000.0040321a SUBSCN: 4 01/13/2006 10:44:07

CHANGE #1 TYP:0 CLS:23 AFN:2 DBA:0x00800039 SCN:0x0000.0040320f SEQ: 1 OP:5.4

ktucm redo: slt: 0x0029 sqn: 0x0000111f srt: 0 sta: 9 flg: 0x2

ktucf redo: uba: 0x0080003e.03d7.0d ext: 0 spc: 6920 fbi: 0

对于以上内容稍作解释如下:

· 第一行LEN: 0x008c 为日志长度,转换为10进制为140字节。

· 第二行的SCN: 0x0000.0040321a为commit SCN。

· 第三行DBA:0x00800039为undo头块的地址。

· 第三行OP:5.4此操作码代表的是对undo事务表的操作。

· 第四行ktucm redo: slt: 0x0029 sqn: 0x0000111f srt: 0 sta: 9 flg: 0x2,代表对于事物表的的slot x29,顺序号为0x0000111f的槽位对应的事务标记为提交。

Note:一个redo record由多个change vector组成,一个change vector包含了一个database block从一个版本变更为另一个版本需要的信息,一般一个修改操作的redo record至少包含2个change vector,一个用来描述对于undo块的插入,一个用来描述对于数据块的修改,例如:一个事务只包含一个操作,update a set b=1 where id=1,假设b字段上无索引,那么对于这个事务,一般会包含2个redo record,第一个redo record会包含3个change vector,第一个描述了对undo段头的修改,标记事务开始,第二个描述了对undo块的插入操作,记录b字段的前镜像,第三个描述了数据块本身的修改,第二个redo record为commit本身产生的change vector,描述了对undo段头块的修改,标记事务已经结束。但是就像上文中已经提到的,commit产生的change vector在10G版本后,可能会跟事务的其他change vector打包进一个redo record里。


log file sync internal

log file sync本身是一个非常复杂的等待事件,我们需要能了解log file sync这一等待事件内部包含的细节,有了这些细节信息优化起来才能事半功倍,我们先来看一副能很好表达log file sync等待事件的流程图,这个图出自Tanel Poder之手,我们这里直接引用一下:

 

这幅图描绘了从用户提交事务到事务提交完成这个过程中经历的环节,如图,大体有6个环节。我对其中6个环节解释如下:

1) 用户进程发起commit

2) 用户进程通知lgwr写日志

3) lgwr接收到请求开始写

4) lgwr写完成

5) lgwr通知用户进程写完成

6) 用户进程获得通知,继续做其他事

1,2 阶段的时间,主要是进程间通信的时间,采用post/wait的方式,典型的这种post/wait一般利用的是操作系统的信号量(IPC)实现,如果系统CPU资源充足,一般不会出现大的延迟。前台进程post lgwr后,开始睡眠,进入log file sync等待。2,3阶段的时间,主要是lgwr接收到前台进程的信号量后苏醒,为了获取CPU资源,等待CPU调度的时间,如果系统CPU资源充足,一般不会出现大的延迟。这里我们需要知道,lgwr只是操作系统的一个进程,它需要操作系统的调度获取CPU资源后才可以工作。3,4阶段的时间,主要是真正的物理IO时间,lgwr通知os把log buffer的内容写入到磁盘,然后lgwr进入睡眠,进入log file parallel write等待,由于写磁盘是比较慢的操作,因此这个时间正常情况下的延迟占整个log file sync的大部分时间,log file parallel write的时间大小主要取决于磁盘的IO性能和需要写入的日志量,如果磁盘的IO性能越好、需要写入的日志量越少,那么log file parallel write的时间就会越小。还需要指出,lgwr在获取CPU资源后,可能并不能马上通知os写磁盘,只有在确保所有的redo copy latch都已经被释放,才能开始真正的IO操作。4,5阶段的时间,os调度lgwr 重新获得CPU资源,lgwr 通知前台进程写完成,这里需要注意lgwr可能会post很多前台进程,这是group commit的副作用。5,6阶段的时间,前台进程接受到lgwr的通知,返回CPU运行队列,处理其他事务,到此log file sync结束。

Note:什么是Group Commit?

不止一次的看到过一些对log file sync调优的建议里写着:打开ORACLE的组提交功能。group commit默认就是开启的,而且你没有任何手段可以关闭它!我一直认为group commit这个词起的名字不是太过恰当,应该起组刷新更恰当,仅仅代表个人意见。


上图是log buffer的抽象图,给大家设定这样一个场景,log buffer此时是非常繁忙的。c1作为一个commit record已经被copy到了log buffer里,一旦commit产生的redo record被拷贝进log buffer就会触发前台进程通知lgwr去写日志,前台进程首先会获取redo writing latch,检查是不是Lgwr已经在写了,如果是则不重复通知,如果没在写,则通知Lgwr去写,在前台进程post lgwr去写,到lgwr真正开始写之前,非常可能存在着时间差,例如等待Lgwr完成当前写、等待获得CPU调度,就在这个时间差里,c2,g1,c3也已经把相应的日志拷贝到了log buffer里,其中c1,c2,c3是commit的记录,g1仅仅是普通的事务日志,不是commit日志。在lgwr真正开始写之前,它会去检查当前log buffer的最高点,发现在c3位置处,把这个点作为此次刷新日志的目标,把c1,c2,g1,c3的日志都刷新到磁盘。虽然刷新日志这个操作是由c1出发的,但是c2,g1,c3也是受惠者搭了便车,日志也被刷新到了日志文件里,这个功能叫组提交,对于一些不太熟悉ORACLE的人容易把组提交误解为,把提交的事务打包刷新到日志里,其实LGWR是不管你的事务日志有没提交的,它只按照log buffer当前分配的最高点来刷新,因此个人认为叫组刷新更好点。图中c1,c2,g1的日志已经拷贝完成,我用filled表示,c3的日志空间已经分配,但是还没完成拷贝,我用allo表示,这个情况下,其实lgwr需要等待c3日志拷贝完成,才能真正的开始刷新操作。Group Commit是一个非常好的特性,能够大大的提升系统提交的吞吐量。我们一般可以通过系统每秒的提交数量除以系统每秒redo writes的数量来知道Group Commit的批次大小,这个批次大小不是固定的,与系统的提交量、写日志的速度、CPU的速度相关。

我们剖析了log file sync的各个阶段后,可以看出,正常情况下,最慢的环节应该在3,4阶段(如上图),典型的IO操作,这个环节对应的数据库等待叫做log file parallel write,是后台进程lgwr上的等待。其他的阶段如调度延迟、IPC时间一般都是极短的。网上、论坛上、包括不少书籍里,在遭遇log file sync性能出现问题后,往往都把责任推卸到IO慢的原因上。绝大多数情况下,这样的推断可能都是正确的,但是,事情不总是这样的,就像我们分析的,log file sync的快慢也是很依赖CPU资源是否富足、系统的负载是否过大。随着系统负载的加大、CPU资源出现瓶颈的情况下,IO部分的延迟可能已经不是整个log file sync时间的最大的罪魁祸首,不过这种情况一般较少出现。

Note:lgwr会post哪些前台进程?

当lgwr刷新完日志后,会post相应的前台进程(wakeup)继续工作,那么lgwr怎么判断应该唤醒哪些前台进程呢?log file sync等待的p1参数的含义为:P1 = buffer# in log buffer that needs to be flushed。当lgwr刷新完buffer后,会扫描活跃会话列表,查看哪些会话在等待log file sync,而且会话的buffer#小于等于它所刷新的log buffer的最大值,这些会话会被唤醒。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22034023/viewspace-2153085/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE组成员,DBGeeK用户组发起人。曾在DTCC、ORACLE技术嘉年华、Gdevops等公开场合做过数据库技术专题分享,2017年应Oracle邀请在世界最大的数据库会议OOW上做技术分享。组织翻译了《拨云见日,解密Oracle ASM内核》一书。

注册时间:2009-07-04

  • 博文量
    422
  • 访问量
    2425300