天天看点

oracle等待事件11——重做缓冲区上的等待事件

1、latch:redo writing  , latch :redo allocation  ,latch:redo copy

oracle 为了保护将重做记录复制到重做缓冲区的一连串过程,使用以下三个锁存器:

1)rodo writing 锁存器:为了占有重做缓冲区内的空间,向LGWR请求写入工作的进程需要获得redo writing锁存器。因为LGWR的写入工作不能同时执行,所以自然在整个实例上只有一个。redo writing锁存器是因为独立锁存器,所以可以通过v$latch_parent视图观察活动性。

SQL> select name,gets,misses,immediate_gets,immediate_misses,wait_time from v$latch_parent where name='redo writing';

NAME                   GETS           MISSES         IMMEDIATE_GETS        IMMEDIATE_MISSES      WAIT_TIME

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

redo writing        256448           2                                     0                                  0                                      0

redo writing 锁存器是以willing-to-wait模式获取。在获取redo writting 锁存器的过程中,如果发生争用,就会等待latch:redo writing事件。

2)redo copy锁存器:想要将PGA内的change Vector复制到重做缓冲区的进程,全程都要拥有redo copy锁存器。redo copy锁存器的数量是根据_LOG_SIMULTANEOUS_COPIES(日志同时备份数;simultaneous:同时的)这个隐含参数值决定的,缺省值是CPU数量的两倍。通过v$latch_children视图可以了解redo

copy锁存器的活动性。

SQL> select name,gets,misses,immediate_gets,immediate_misses,wait_time from v$latch_children where name='redo copy';

NAME               GETS     MISSES IMMEDIATE_GETS      IMMEDIATE_MISSES      WAIT_TIME

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

redo copy             6          0                 445161                                285                                  0

redo copy             6          0                 281016                                266                                  0

redo copy             6          0                 300597                                 891                                 0

redo copy             6          0                       0                                       0                                     0

redo copy锁存器基本上以no-wait模式获得。以上结果显示,IMMEDIATE_GETS值高就是因为这个原因。如果进程在获取redo copy锁存器失败,将为了获取redo copy锁存器连续尝试,在最后一次获得redo copy 锁存器过程中将使用willing-to-wait模式。若获得redo copy锁存器的过程中发生争用,则等待latch:redo copy

3)redo allocation锁存器:为了将change vector 复制到重做缓冲区,在获取重做缓冲区空间过程中需要拥有redo allocation锁存器。9i起,可将重做缓冲区分为多个redo strands使用,而且一个redo allocation 锁存器管理一个redo strand。因为可以使用多个redo allocation锁存器,稍微能减少锁存器的争用。redo

strands数量由参数LOG_PARALLELISM决定。其缺省值是1。从10g起,此参数改为_LOG_PARALLELISM的隐含参数。

(关于此隐含参数的测试:http://blog.csdn.net/changyanmanman/article/details/7899041)

CPU数量较多(如16个以上)的系统上,发生redo allocation锁存器争用的概率较高,所以最好是将_LOG_PRARLLELISM值设定的较大后,使用多个redo strand和redo allocation锁存器。oracle方面推荐将_LOG_PARALLELISM参数值使用CPU数量的1/8。

从10g起引入了称为  dynamic prarllelism  新功能。dbnamic parallelism功能是将_LOG_PARALLELISM_DYNAMIC隐含参数指定为TRUE就被激活,缺省值是TRUE(每个版本不同),使用这个功能,被视为动态调整redo strands的数量。从10gr2起,可以创建的最大redo

stands 数量基本上是18+_LOG_PARALLELISM_MAX,创建与这个值相同的redo allocation 锁存器。_LOG_PARALLELISM_MAX的缺省值是2,但不能超过CPU数。但创建的锁存器不是一直被使用的,oracle会动态的使用。9i上推荐使用redo allocation锁存器的数量是CPU数的1/8,但是从10gR2起,可使用的redo allocation 锁存器数量大幅增加:

SQL> select name,gets,misses,immediate_gets,immediate_misses,wait_time from v$latch_children where name='redo allocation';

NAME                    GETS     MISSES       IMMEDIATE_GETS          IMMEDIATE_MISSES          WAIT_TIME

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

redo allocation     123126         79              1019511                                       74                               15234

redo allocation      67719          0                    7038                                           0                                      0

redo allocation      28944          0                       0                                               0                                      0

redo allocation       9392            0                      0                                               0                                      0

redo allocation       7797            0                      0                                               0                                      0

redo allocation      22917          0                       0                                               0                                     0

redo allocation       1534           0                       0                                               0                                     0

redo allocation      63787          0                       0                                               0                                     0

redo allocation        185             0                      0                                                0                                    0

redo allocation          77             0                      0                                                0                                     0

NAME                   GETS       MISSES       IMMEDIATE_GETS          IMMEDIATE_MISSES          WAIT_TIME

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

redo allocation         77           0                        0                                                    0                                0

redo allocation         77           0                        0                                                    0                                 0

已选择20行。

若获取redo allocation锁存器过程中发生争用,则等待latch:redo allocation事件。

从10g起,引入了private redo strands功能,进一步扩展了strands的概念。

一般想创建重做数据,在PGA上创建change vector之后,获得锁存器后需要经历复制到重做缓冲区上的一连串过程。相反,如果使用了private redo strands,重做记录将创建在共享池内的private strands区域,进程之间不共享private strands区域,所以在创建重做过程中无需获取锁存器,又因为是利用LGWR直接写入到重做日志文件上,所以不需要从PGA上复制重做缓冲区的过程。这些又称为“zero copy redo”。将隐含参数_LOG_PRIVATE_PRAALLELISM的值修改为TRUE,此项功能就会被激活。

通过v$sgastat视图可以确认在共享池内创建的private strands区域:

SQL> select * from v$sgastat where name like'%strand%';

POOL                          NAME                 BYTES

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

shared pool  private strands           1198080

还可以通过使用查询隐藏参数脚本来查看这个_log_private_parallelism 的值:

SQL> set linesize 132

SQL> column name format a30

SQL> column value format a25

SQL> select

      x.ksppinm  name,

      y.ksppstvl  value,

      y.ksppstdf  isdefault,

      decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE')  ismod

      decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE')  isadj

    from

      sys.x$ksppi x,

      sys.x$ksppcv y

   where

     x.inst_id = userenv('Instance') and

     y.inst_id = userenv('Instance') and

     x.indx = y.indx and

    x.ksppinm like '%_&par%'

   order by

    translate(x.ksppinm, ' _', ' ')

   /

输入 par 的值:  log_p

NAME                                                           VALUE                         ISDEFAULT I         SMOD           ISADJ

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

_flashback_n_log_per_thread                128                                 TRUE                  FALSE           FALSE

_log_parallelism                                         1                                     TRUE                 FALSE           FALSE

_log_parallelism_dynamic                   TRUE                                 TRUE                 FALSE           FALSE

_log_parallelism_max                               2                                     TRUE                 FALSE           FALSE

_log_private_mul                                        5                                     TRUE                 FALSE           FALSE

_log_private_parallelism                      FALSE                               TRUE                 FALSE           FALSE

_log_private_parallelism_mul                10                                   TRUE                 FALSE           FALSE

已选择7行。

2、log file sync

如果服务器进程执行提交或回滚,LGWR就将重做缓冲区上最近写入的时刻到最近提交时刻为止的重做记录,写入到日志文件上,这就是“sync write”,它可通过redo synch writes统计值查询。服务器进程在下达提交命令后,一直等待直到LGWR成功写入为止,这是等待log file sync事件。

事务存在的理由就是修改该数据和执行提交,所以log file sync等待事件是oracle的最普遍等待事件之一。一般执行sync write的时间非常短,所以log file sync等待不会成为问题。但一旦发生,就是难以解决的等待现象。若log file sync等待广泛出现,就应该怀疑以下事实:

1)提交次数是否过多?

过于频繁的提交是log file sync等待的关键因素。一般情况下,每当执行一次提交都发生一次log file sync等待。因此如果多个会话同时执行大量的提交,就可能广泛发生log file sync等待。

通过如下语句查询等待事件中的信息:

SQL> select sid from v$mystat where rownum<2;

       SID

----------

       142

SQL> select event,total_waits,time_waited from v$session_event where sid=142 and event='log file sync';

没有选定行;

查了下没有相关等待,再执行如下语句:

SQL> select event,total_waits,time_waited from v$session_event where sid=142 ;

EVENT                                    TOTAL_WAITS    TIME_WAITED

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

control file sequential read              2                       2

db file sequential read                      5                       8

SQL*Net message to client          189                     0

SQL*Net message from client     188                561364

SQL*Net break/reset to client          2                       0

每次执行update后 执行提交时,log file sync等待时间的等待次数和等待时间会以相应比例增加。因提交每次执行synch write时,可能给整个系统性能带来较坏影响,所以oracle尽量提交请求集结后一次性执行synch write。这就是组提交。PL/SQL上反复提交或因recursive SQL实现提交时,多个会话上同时收到提交请求等情况下使用组提交功能。使用组提交时,user

commits 统计值与调用提交命令次数增加量是相同的。但log file sync等待只发生一次。

创建sequence时,NOCACHE选项有多种,nocache属性会引起许多sequence性能问题,其中代表性的情况就是增加row cache lock 等待。有趣的是nocache属性的sequence可能成为引发log file sync等待的原因,这是因为如果对nocache属性的sequence调用sequence.nextval.,则每次都要更新数据字典表信息后执行提交。使用sequence时考虑到事务的量,必须赋予适当大小的cache属性值。

2)I/O系统是否缓慢?

重做日志文件所在的I/O系统的性能缓慢时,执行LGWR的synch write时间将会延长,因此可能增加log file sync等待时间,这时,服务器进程在等待log file sync事件期间,LGWR会等待log file prarllel write 事件。提交次数适当或因系统的特性无法减少提交次数时,如果广泛发生log file sync 等待,就需要对I/O系统性能改善进行检查。一般LGWR所等待的log file parallel

write 事件的时间长或整个系统上相对等待时间长,就可以理解为重做日志文件所在I/O系统的新跟那个存在问题。

一般oracle指南里会讲,将重做日志文件至于最快的设备上。还有为了避开磁盘争用,互相不同组的重做日志文件应该分散在不同的磁盘上。将重做日志文件分配在与数据文件或控制文件不同的磁盘上也是必要的。

3)重做数据是否不必要地被创建?

执行提交时,只要减少重做日志文件上需要写入的数据量,就可以减少log file sync等待时间。特别是在大而长的事务上减少重做数据量,LGWR的后台写入工作就将减少,与重做相关的争用也可以解除。在erp或dss之类创建后台数据多的系统上,LGWR将较多执行后台写入,因此用户会话可能会长时间等待log file sync事件,LGWR则可能会长时间等待log ile prarllel write事件,LGWR性能下降直接关系到整个系统的性能下降。

oracle中提供了许多可以创建最小化重做数据的方法。创建大量数据的工作上,应该检查能否应用如下方法:

1.能否使用nologing选项?若使用nologging选项,可以最大限度减少重做数据。direct load功能和create。。alter。。之类的工作大部分提供nologging选项。若能灵活应用这些功能,可最大限度减少重做数据量。

2.通过sql*loader装载大量数据时,将使用direct load option。

3.需要临时操作时,尽量使用临时表。如果使用了临时表,虽然因撤销会创建重做,但是不会创建对于数据的重做。因此具有重做数据量整体减少的效果

4.对已有索引的表执行direct load操作时,应该使用如下步骤,防止索引引起的重做的创建

1将索引修改问unusable状态。

2生成数据

3将索引以nologging模式重建。

5.若LOB数据较大,则尽量赋予nologging属性。

4)重做缓冲区是否过大?

一般重做缓冲区过大时,有log file sync等待增加的趋势,这是因为重做缓冲区大时,LGWR引起的后台写入次数相对减少,这时用户会话上执行sync write 时需要写入的数据量增加,因此log file sync等待时间可能延长。

重做缓冲区大小多大合适呢?认为没有正确答案。一般赋予1--5M,然后观察,如果log file sync等待有增加的趋势,那最好减少重做缓冲区的大小,相反,log buffer space 等待有增加的趋势,加大重做缓冲区的大小就是一般的解决办法。在有少量大事务和大量小事务的混合系统上,这两个等待同时出现的情况较多。这是的解决方法是利用_LOG_IO_SIZE隐含参数。_LOG_IO_SIZE参数标识LGWR将重做缓冲区的内容存到重做日志文件里的临界值。如_LOG_IO_SIZE值是128K。LGWR在重做缓冲区的最终写入后,重新积累128K,就会重新开始记录。所以为了减少log

buffer space等待将重做缓冲区加大,与此同时减少log file sync等待,将_LOG_IO_SIZE值调整到较小的值(如64K左右)

3、log file prarllel write

log file parallel write事件是在只有LGWR进程上发生的等待事件,LGWR为了将重做缓冲区的内容记录到重做日志文件里,在执行必要的I/O调用后,在等待I/O工作结束期间等待log file prarlle write 事件,log file parallel write 事件拥有三个值分别是P1=file count(即,member connt)、P2=block count(red

log block count)、P3=I/Orequest count。

log file parallel write 等待,与I/O相关的等待现象上说明过的db file prarllel write 等待属性基本类似。这两个等待从根本上与I/O系统性能问题关联较多。在这里讨论关于性能问题的若干观点,例如以下几个:I/O系统的性能不存在问题,但脏缓冲区的数据量过多时,db file prarllel write 等待可能增加。与此相同,I/O系统上没有任何征兆,但重做数据量过多时,log file prarlle write

等待可能增加。这时的性能问题是过多创建数据的应用程序问题?还是无法以更快的速度处理数据的I/O系统问题?我的观点是一般从应用程序上寻找问题和解决方法,如果找不到更多的解决方法,就应该认为I/O系统问题。特别是从经济角度出发也应该遵循这个方法。

解决log file prarllel write 等待的方法一般与log file sync等待类似。两个事件都被LGWR的性能所左右。

***减少不必要的提交。

***应用nologging 选项,减少重做数据量。

***提高重做日志文件所在的I/O系统的性能。

***还有一点要注意,不能太频繁执行HOT backup,特别是在事物频繁的时刻不应该执行。因为hot backup模式上的重做数据,不是在行级创建的,而是在块级创建的。

不幸的是不能减少提交次数或使用nologging选项的情况较多。特别是使用复杂的应用程序或不可修改的程序包时,有时即便找到问题也无法修改。这时除从物理角度改善I/O系统之外,没有其他方法了。

4、log buffer space

欲向重做缓冲区上写入重做记录的进程,为了确保拥有重做缓冲区内必要的空间,需要获得redo allocation 锁存器。已获得redo allocation锁存器的状态下,想要获得重做缓冲区时,如没有适当的剩余空间,则需要等待直到获得空间为止,这时,根据情况等待两种事件:如果当前正使用的重做日志文件已满,因此无法获得剩余空间,LGWR就会执行日志文件切换,服务器进程则等待log

file switch completion 事件。除此之外,需要等待log buffer space事件,前者在日志文件切换结束后,可能发生log buffer space等待瞬间增加的现象。这时因为欲在重做缓冲区上写入的多数会话,等待日志文件切换的结束,然后争先恐后的为了写入到重做缓冲区而发生争用。

重做缓冲区小于重做数据量时,发生log buffer space等待。所以广泛发生log buffer space等待时,应该调查重做缓冲区是否过小,必要时应该将重做缓冲区调整到足够大。如果log buffer sapce等待和log file switch completion等待同时出现,就有必要怀疑重做缓冲区大小和重做日志文件大小合理与否。许多情况下,这两个等待是同时出现的。若重做日志文件过小,则等待log file switch completion等待会增加,在日志文件切换结束后,重新出现log

buffer spqce等待现象。为减少log buffer space等待,加大重做缓冲区的大小时,log file sync等待可能会增加。对此的解决方法在log file sync等待上已经充分进行讨论了。

log buffer space等待具有与free buffer waits等待相似的属性。free buffer waits等待,是因为DBWR进程无法满足服务器进程需找空闲缓冲区的速度而发生的。与此相同,log buffer space等待,是应为LGWR进程无法满足服务器进程的寻找空闲重做缓冲区的速度而发生的。减少free buffer waits等待一中方法就是改善DBWR的性能。与此同时,减少log buffer space等待,也改善LGWR性能。将更快,更有效的将I/O系统应用与重做日志文件,可改善LGWR的写入性能。

5、log file switch completion,log file switch(checkpoint incomplete),log file switch(archiving needed),log file switch(private strand flush incomplete)

服务器进程正要写入重做记录的时刻,若重做日志文件已满不能继续写入操作,则进程向LWGR请求执行对日志文件的切换。服务器进程由于LGWR,直到日志文件切换结束为止,需要等待log file switch completion 事件,但日志文件的切换结束时,如果将要投入使用的重做日志文件,还没有完成的工作,就需要另外等待如下事件。

1)如果对于重新使用的重做日志文件尚未结束检查点,进程就应该等待由DBWR来结束检查点。这时,进程将等待log file switch(checkpoint incomplete)事件。

2)如果对于重新使用的重做日志文件尚未完成归档(archive)工作,进程就应该等待ARCH进程来结束归档工作。这时进程将等待log file switch(archiving needed)事件。这个事件只在归档模式数据库上发生。

3)如果对于欲重新使用的重做日志文件尚未完成对private srands的flush 工作,就应该等待这个工作结束。这时等待进程将等待log file switch (private strand flush incomplete)事件。这个事件是在oracle 10gR2上新增的,使用前面提交过的private redo strands功能时才会发生。

以上的三种等待现象在重做日志文件被循环使用的情况下,将生成许多重做数据,所以在尚未完成工作就重新使用时发生。因此这些等待现象意向是log file switch completion 等待现象一起出现。准确的说,服务器进程首先等待log file switch completion事件,特殊情况下还会等待log file switch(checkpoint incomplete)、log file switch(archiveing needed) 、log file switch (private strand

flush imcomplete)事件。

因为名字相似,所以给管理人员带来啦相当混乱的四个等待现象,发生原因和解决方向相同。噶生原因是比起事务所创建重做数据,重做日志文件过小。所以解决方法是将重做日志文件的大小调整为足够大。而且,使用directload operation 或nologging选项对减少重做数据的量也是有帮助的。