晶晶实验十一_相关重做日志的闩 .

一,相关闩的介绍
  重做是先产生在各个会话的PGA中,再由各个会话的服务器进程,将重做记录拷贝到SGA中的log buffer中,再由LGWR进程刷新到redo log文件中.整个这个过程,涉及到3个比较重要的闩.分别是redo copy latch,redo allocation,和redo writing.下面先介绍下这3个闩,在重做产生的流程中,各自的作用.明白了这一点,对这3个闩的调优会有很大的帮助.
1,redo copy latch
  redo copy latch 的数量可以有多个,可以通过_log_simultaneous_copies参数来设定,缺省值是两倍CPU的个数.当前台进程将自己PGA中的重做记录拷贝到日志缓存中时,此闩用于保护日志缓存中的信息.LGWR工作时并不需要再获得此闩.
  注意.此闩主要的用途是从PGA拷贝重做记录到日志缓存,LGWR的工作是将日志缓存写到磁盘.因此,LGWR不需要此闩,但是,oracle也不会允许某前台进程一边对重做记录A进行修改,LGWR一边将重做记录A写进磁盘.因此LGWR虽然不需要获得redo copy latch,但是在他开始工作时,必须等待正持有此闩的前台进程,将要刷新的重做记录拷贝完毕,redo copy latch是保护日志缓存的.LGWR不持有此闩的目的就是在LGWR工作时,任一前台进程仍可以向日志缓存中拷贝自己的重做日志.所有正在进行的工作都可以继续,而不必等待LGWR完成.
  如果此闩的数量设置的多一些,这将有助于降低前台进程对此闩的争用.但这又势必增加LGWR等待此闩释放的时间.资料视图(v$sysstat)中的redo writer latching time资料记录的就是LGWR等待此闩释放的总的时间.
2,redo allocation
  LGWR和前台进程都需持有.当前台进程在日志缓存中分配空间时,必须先持有此闩,当LGWR刷新缓存时,它持有此闩,以阻止前台进程在日志缓存中分配空间.但LGWR持有此闩的时间是很短暂的.当它一旦确定要刷新的缓存范围后,再开始真正的写磁盘操作前,它就会释放此闩,以便让其他的前台进程可以继续向日志缓存中拷贝重做条目.
  从以上两个闩可以看到,oracle把向log buffer中写缓存这样一个操作.分做两个步骤.1是先在log buffer中分配一块空间,2是向这块空间中实际的写入重做信息.分成两步之后,多个服务器进程,在log buffer中申请空间的操作,会互相阻塞.一旦空间分配成功,多个进程可以同时向自己所属的那块空间写入信息.分配空间时,必须持有redo allocation闩,这个闩数量只有一个.这就意味着多个进程分配空间的操作将会互相阻塞.向log buffer中写信息时,必须持有redo copy 闩,redo copy闩的数量可以有多个.也就是说,在空间分配好后,向各自的空间中的写操作可以同时进行.但是,计算机的总限宽度和CPU资源是有一定限制的.如果同时向 log buffer中写信息的进程太多.反而会使速度降低.因此redo copy 闩虽然可以有多个,但数量上很受限制.一般都是CPU的两倍.目的就是为了限制同时向log buffer中写信息的进程数.如果oracle不把向log buffer中写信息的过程分为两步,那么在某一个进程,在log buffer中分配空间并向空间写信息的时候其他所有进程都必须等待.分做两步后,在log buffer中分配空间这个步骤必须是串行的,而向各自已分配的空间写信息则可以并行. oracle会尽量让可以并行的操作并行来处理.以减少阻塞和等待.
3,redo writing
  当日志缓存中没有空间时,前台进程必须通知LGWR刷新日志缓存,只有第一个得到此闩的进程可以通知LGWR,它用来阻止其他进程通知LGWR,前台进程取得此闩,通知LGWR刷新缓存,然后马上就释放此闩,它不会一直占有此闩,通常闩的持有都是很快的.
  LGWR接到前台进程的通知,同样,当它写日志缓存到文件前,它也得到此闩,这样,其他需要刷新日志缓存的进程,就无法再次呼叫它,它可以专心完成刷新缓存的工作,当一个新的前台进程得到此闩后,第一件事情就是检测LGWR是否已经准备好了可用的空间.如果是这样,进程释放闩并不再通知LGWR,这是很有可能的,因为,如果同时有十个进程争用此闩,第一个获得此闩的进程需要400字节的缓存,它呼叫LGWR刷新日志缓存,LGWR不可能只为此前台进程只腾出400字节就完了,它每次都要把所有满的日志块和必须要同步的重做信息写进磁盘,也就是说LGWR每刷新一次,很可能会腾出许多空间,因此,后得到此闩的进程就不必忙着呼叫LGWR,有可能他需要的缓存空间已经有了。
   总结一下此闩的作用,当写日志缓存到文件时,只有LGWR能完成这个工作.既然只能有LGWR自己可以写日志文件,那么日志文件不必再有闩来保护.但是同时可能会有多个服务器进程(又称前台进程)呼叫LGWR写缓存,这就需要按次序进行,此时需要此闩来保护.还有,在LGWR正在写缓存时,也不希望别的进程再来打扰,因此,当LGWR开始写缓存时,它先获得此闩,这样,在他完成写操作前,其他想要呼叫它的进程只有等待.综上所述,此闩是在呼叫LGWR写缓存时必须先获得的闩.
二,LGWR的工作流程:
  综上所述,我们先来了解一下LGWR的工作流程,在LGWR被触发时,它必须先获得redo writing闩,确保其他进程不会再通知它写缓存,然后LGWR获得redo allocation闩,以组织前台进程分配更多的重做空间,然后 LGWR确定要写的buffer是哪些,这包括所有满的,或者必须被同步的buffer.此时,还要分配一个新的SCN,这主要用于RAC环境,确保不会在同一SCN刷新缓存两次,这些完成后,redo allocation被释放,根据情况,有时LGWR还要计算Target RBA.在这完成后,redo writing闩也被释放,可以看到,redo writing与redo allocation都是持有很短的时间.在真正的写磁盘操作开始前就被释放了.因为其他进程中,重做的生成仍然要继续.
  LGWR在刷新缓存前,必须确保前台进程完成对要刷新缓存的修改.这就是它必须等待redo copy闩的释放,此时LGWR将暂停工作,等待一个唤醒通知.即相关的redo copy闩被释放时,LGWR会被唤醒继续工作,如果持有redo copy闩的前台进程,正在修改的缓存并不是LGWR要刷新的缓存,LGWR并不需要等待此redo copy闩的完成.
  在这些操作都完成后,LGWR开始真正的写磁盘,在磁盘写时,它并不持有上述三个闩中的任一个.
   下面用一个图来说明一下:



   上图中,都是假设每给进程的重做记录正好占满一个重做块,其实,重做记录有大有小,不可能都那么凑巧.就象上面所讲的例子,在11号重做块中提交的进程.并没有将11号块占满.假如说只使用了200个字节,LGWR在刷新重做时,也必须将整个11号重做块刷新到重做日志文件中.这可能会造成一些空间上的浪费,在资料视图v$sysstat中有一个redo wastage资料,是专门记录重做日志文件中,浪费空间的数量.
三,重做的产生流程
  1,先在PGA中生成重做记录,并计算出重做记录大小.
  2,由服务器进程申请redo copy latch 如果成功的话,
  3,再去申请redo allocation,成功分配空间后.
  4,释放redo allocation.
  5,开始把PGA中的重做记录写往log buffer.
  6,记录写完后,释放redo copy latch.
  在第1步,计算出重做记录大小后,还将更新资料视图中的重做信息.redo size.我们可以通过它来了解生成了多少重做.
  如果在第2步时,分配不成功的话,会等待.
  如果在第3步时,redo allocation 闩无法获得,那么会等待,第2步获得的闩不释放像这样进程已持有某个闩,但在等待另外一个闩的次数,可以在v$latch中的watis_holding_latch列查看.如果获得了reod allocation闩,但是log buffer中没有空间,会去通知LGWR写日志.并且把第1,第2步所获得的闩都释放.当LGWR刷新过缓存.log buffer中已经有了可用空间后,进程将从头开始重新申请第2步的redo copy latch.此时会增加资料视图中'redo buffer allocation retries'的值.
   如果在上面步骤3时,log buffer中空间不足,服务器进程把redo allocation和redo copy latch释放.然后服务器进程将申请redo writing闩,获得后,会再次检查一次log buffer中空间是否足够.如果空间仍然不足,LGWR就必须要去刷新缓存了,在LGWR刷新缓存前.会再检查一次当前连机重做日志文件中是否有足够空间.如果有的话,服务器进程将释放redo writing闩.并通知LGWR开始刷新缓存.此时服务器进程将等待.相关等待信息会被记录进log buffer space等待事件.
四,简述LGWR的触发
   LGWR的触发已经有很多人说过了,我就不详细再讲了.下面我简单的列举下LGWR的触发条件:
   1,lgo buffer不足 服务器进程通知LGWR刷新缓存.
   2,事务提交时.
   3,log buffer 满1/3时.
   4,每3秒一次.
   5,重做信息满1M时.
   6,日志切换时.
   7,在DBWn写之前.
     因为oracle有一个规定:Write-Ahead Loggin(在write前loggin) 它有两点要求: (1)在数据缓存块被改变前,重做必须先被写进日志缓存.(2)在DBWN写缓存块到数据文件前,LGWR必须写日志缓存到日志文件.因此,如果DBWN沿检查点队列写缓存块到磁盘时,此缓存块对应的重做记录还没有被写进日志文件,DBWN会暂停写此块.并通知LGWR刷新日志缓存.额外说一点,此时DBWN并不会停止,他可以转去写LRUW中的块.等等,总之DBWN在这种情况下不会等待.
  注意 LGWR的写是连续的,它必须按重做记录生成时的顺序.也就是按照RBA的大下,顺序写.
***小结:了解咯重做产生的流程以及redo copy.redo allocation和redo writing这3个闩在重做生成的流程中扮演了什么样的角色,当这3个闩出现争用时,会更容易的判断问题出现在什么地方以及下一步该采取什么样的行动. redo.gif (18.55 KB)
标签: 暂无标签
fishcat

写了 55 篇文章,拥有财富 503,被 40 人关注

oracle爱好者
转播转播 分享分享 分享淘帖
回复

使用道具

成为第一个吐槽的人

您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

意见
反馈