3.3     控制文件相关的IO事件
这一类等待事件发生在对控制的IO操作时。对控制文件的IO访问一般都是由Redo Log文件切换、Checkpoint等(如更新SCN)引起的。因此,对这类事件的优化处理也就主要是对这些操作的调优处理。
3.3.1      control file parallel write
这一等待事件通常发生在一个服务进程在更新所有控制文件时,通常是以下情况:
 
  • 会话启动了一个控制文件事务(在提交事务之前更新所有控制文件为最新);
  • 会话提交了一个事务到控制文件;
  • 一个控制文件的条目被修改了,该修改要更新到所有控制文件上去
 
如果这一事件明显影响到了系统的IO性能时,可以考虑用以下手段来进行优化:                                                            
 
  • 在保证控制文件的备份数量足够安全(不会出现控制文件全部丢失)的情况下使控制文件数量最少;
  • 如果操作系统支持AIO,设置数据库支持AIO;
  • 将控制文件转移到IO负载比较低的磁盘上去。
3.3.2      control file sequential read
这一等待事件通常发生在对一个单独的控制的IO读操作时。通常可能是以下情况:
 
  • 备份一个控制文件;
  • RAC中在实例之间共享一个控制文件信息时;
  • 读取控制文件的头数据块或者其他数据块时。
 
用以下语句可以找到是访问哪个控制导致的该等待事件:
 

 

select P1 as FileName from V$SESSION_WAIT



where EVENT = 'control file sequetial read' and STATE='WAITING';
 
我们可以采取以下手段来降低这一等待:
 
  • 如果操作系统支持AIO,设置数据库支持AIO;
  • 将控制文件转移到IO负载比较低的磁盘上去。
 
3.3.3      control file single write
 
这一等待事件通常发生在对一个单独的控制的IO写操作时。用以下语句可以找到是访问哪个控制导致的该等待事件:
 

 

select P1 as FileName from V$SESSION_WAIT

where EVENT = 'control file single write' and STATE='WAITING';
 
我们可以采取以下手段来降低这一等待:
 
  • 如果操作系统支持AIO,设置数据库支持AIO;
  • 将控制文件转移到IO负载比较低的磁盘上去。
3.4     Redo Log相关的IO事件
在写Redo Log时,会发生很多等待事件,大部分和IO相关。其中最重要的要属“log file parallel write”和“log file sync”。Oracle的后台LGWR进程会等待“log file parallel write”事件而前台进程会等待“log file sync”事件。
3.4.1      log file parallel write
这一等待事件发生在LGWR进程等待完成将Redo记录写入Redo Log文件时。在LGWR进程将Log Buffer中的数据写入Log File时会发生该事件。
当使用了异步IO时,这种写操作是并行的,否则只会一个接着一个Redo文件的写入。LGWR进程必须等待所有的Redo Log文件都被写入。因而Redo Log文件所在磁盘的IO效率就直接影响了该等待事件的总的等待时间。
 
事件中的P1、P2、P3参数分别代表:
P1:有多少个Redo Log文件在被写入;
P2:有多少个数据块被写入;
P3:IO请求的次数。
 
降低log file parallel write等待的方法有:
 
  • 不要使表空间长期处于热备状态。当表空间处于热备状态时,表空间不再被更新,Redo Log会急剧增加;
  • 将Redo Log文件放在高速存储设备上,千万别放在RAID5上,可以考虑放在裸设备上;
  • Redo log文件所在的磁盘应尽量避免有其他IO操作的存在;
  • 对某些操作,如大批量数据导入,可以设置NOLOGGIN、UNRECOVERABLE选项,或者在SQL语句中使用提示/*+APPEND*/,以减少Redo Log的产生。
  • 在确保Redo Log数据足够安全(不会发生Log文件丢失)的情况下,尽量减少Redo Log组的成员数;
  • 在配置需要使用到Redo Log的功能时,如Streams复制、LogMiner、逻辑模式的DG,尽量设置为最低级别的补充日志(Supplemental Logging);
  • 适当增加Log_buffer的大小
 
我们可以按照以下方法来调整Log_buffer的大小,比较Redo Log buffer分配的重试(在请求log buffer时,无足够buffer,需要重新提交请求)率,如果该比例大于0.1%,我们就需要考虑增加Log_buffer的大小。
 

 

select retries.value/entries.value "Redo Log Buffer Retry Ratio"
from V$sysstat retries, V$sysstat entries
where retries.name =  'redo buffer allocation retries'
and entries.name =  'redo entries';
 
另外,如果系统统计数据中redo log space requests大于0,说明有进程在等待分配Redo Log文件空间,而不是等待Buffer空间。这时我们也需要考虑增加Log_buffer的大小。
 

 

SELECT name, value 

FROM v$sysstat 

WHERE name = 'redo log space requests';
 
但是,Log_buffer的大小不要超过128K*CPU或512K(取两个数字中最大的一个)数。
3.4.2      log file sync
当Oracle前台进程提交或者回滚事务需要等待提交或回滚完成时会产生该等待事件。部分等待的原因可能是等待LGWR进程将会话事务的Redo记录从Log Buffer中拷贝到磁盘上去。这时,就会出现前台进程等待Log File Sync,而后台LGWR进程在等待 Log File Parallel Write的情况。
 
事件中的P1、P2、P3参数分别代表:
P1:发生等待时正在等待哪个Log Buffer数据被写入Log文件;
P2:无意义;
P3:无意义。
 
实际上,一个Log File Sync等待事件包含了多个步骤:
 
1、如果LGWR空闲则唤醒LGWR进程;
2、LGWR收集需要写的Redo记录并提交IO请求;
3、等待写Log的IO完成;
4、LGWR IO提交处理;
5、LGWR提交已经完成了写日志的前台/用户进程;
6、前台/用户进程被唤醒。
 
如果配置了Data Guard,上述步骤中的第三步还需要将Redo记录通过网络写入到standby数据库的Redo Log文件中去。
针对不同步骤的等待时间的不同,我们需要采取不同的优化措施:
  • 第二、三步的相关等待数据可以从statspack或awr的“redo write time”统计项获得;
  • 第三步的等待时间和Log File Parallel Write的等待时间相同;
  • 当系统负载非常高时,第五、六两步的时间就会很长,因为此时尽管LGWR进程已经通知了前台/用户进程写日志已经完成,但是系统负载太高,前台/用户进程需要等待操作系统安排其运行计划。
 
要了解是什么阻滞了Log File Sync的关键是比较Log File Sync和Log File Parallel Write的平均等待时间:
  • 如果他们的等待时间差不多,则说明是Log文件的IO问题(即第三步)导致的Log File Sync等待,我们就需要优化Log文件的IO(如上一节所述的方法);
  • 如果Log File Sync的等待时间远远大于Log File Parallel Write的等待时间,则说明Log File Sync是由于在提交或回滚时的其他Redo Log机制(非IO原因)引起的,如Latch Free、LGWR wait for copy等log buffer相关的latch冲突。
 
可以用下面的语句来获取Log File Sync和Log File Parallel Write的平均等待时间的比值:
 

 

select (sum(decode(name, 'redo synch time', value)) / sum(decode(name, 'redo synch writes', value)))

       / (sum(decode(name, 'redo write time', value)) / sum(decode(name, 'redo writes', value)))

       as sync_cost_ratio

from v$sysstat

where name in ('redo synch writes', 'redo synch time', 'redo writes', 'redo write time');
 
我们还可以采取以下调优手段来降低Log File Sync等待:
 
  • 按照上一节中的方法减少Redo Log的产生、提供Redo Log的IO效率、减少Redo Log与其他IO的冲突;
  • 将一些小事务合并成批量事务,以减少提交和回滚次数。
3.4.3      log file single write & log file sequential read
Log file single write只会发生在打开或关闭一个Redo Log文件后,向文件头写入相关信息时。因为文件头的信息中包含了文件号,因此文件头信息不会并行写入多个文件,而是单独一个个写入,因而其等待时间不会被统计到log file parallel write之中。
 
事件中的P1、P2、P3参数分别代表:
P1:写入的Redo Log文件号;
P2:写入的数据块号;
P3:写入的数据块数。
 
当进程从Redo Log文件中读取redo记录时会产生log file sequential read等待事件,如Arch进程读取Redo Log数据。
 
事件中的P1、P2、P3参数分别代表:
P1:读取的Redo Log文件号;
P2:开始读取的数据块号;
P3:读取的数据块数。
 
当Redo Log文件存在IO问题时,以上两个等待事件通常都会和log file parallel write等待事件同时出现。因而可以通过在3.4.1中提到的提高Redo Log文件IO效率、减少Log文件IO冲突的方法来减少这两个等待。
3.4.4      log file switch completion  & switch logfile command & log file switch (clearing log file)
当在产生Redo Log时需要等待LGWR切换Log文件时,会产生log file switch completion等待事件;而switch logfile command则是等待DBA手工执行的切换日志的命令:
 
SQL> alter system switch logfile;
 
System altered.
 
日志切换由以下步骤组成:
 
  • 从控制文件获取下一日志文件的文件号;
  • 获取Redo Copy和Redo Allocation的Latch;
  • 清空Redo,将buffer中的Redo记录写入Log文件中去;
  • 关闭当前Redo Log文件;
  • 更新控制文件,包括:
o        设置下一日志文件为当前日志文件;
o        设置之前的日志文件为INACTIVE
o        如果在Archive模式下,将之前文件加到归档文件列中;
o        打开新的日志文件组中的所有文件;
o        将SCN写入文件头;
o        打开允许产生Redo Log的开关。
 
在等待上述的第三步时,则会产生log file switch (clearing log file) 等待事件。
 
我们可以用以下语句查看当前的日志文件:
 
SQL> select GROUP#, ARCHIVED, STATUS from v$log;
 
    GROUP# ARC STATUS
---------- --- ----------------
         1 NO  INACTIVE
         3 NO  INACTIVE
         2 NO  CURRENT
 
我们可以采取前述方法提高Redo Log文件IO效率来降低这三个等待事件。此外,我们还可以增大Log文件大小,降低日志切换频率(一般来说,在系统运行高峰期以20~30分钟切换一次为佳)。通过以下语句可以查询日志的切换记录及其切换间隔时间:
 
SQL> SELECT to_char(b.first_time, 'YYYY-MM-DD HH24:MI:SS') as swtich_time,
  2         (b.first_time - a.first_time) * 24 as "switch_interval(hr)"
  3  FROM v$log_history a, v$log_history b
  4  WHERE a.SEQUENCE# + 1 = b.SEQUENCE#
  5  AND ROWNUM <= 10
  6  ORDER BY 1;
 
SWTICH_TIME         switch_interval(hr)
------------------- -------------------
2007-08-25 00:28:59              2.3975
2007-08-25 06:04:53          5.59833333
2007-08-25 12:15:52          6.18305556
2007-08-25 21:58:13          9.70583333
2007-08-25 23:50:39          1.87388889
2007-08-26 00:28:42          .634166667
2007-08-26 08:32:04          8.05611111
2007-08-26 17:58:05          9.43361111
2007-08-26 23:26:57          5.48111111
2007-08-27 07:21:35          7.91055556
... ...
另外,从Alert日志中,我们也可以找到日志切换记录。
... ...
Beginning log switch checkpoint up to RBA [0x18106.2.10], SCN: 0x0003.93b3fb7d
Thread 1 advanced to log sequence 98566
  Current log# 7 seq# 98566 mem# 0: /export/home/icssprd/data/data02/icssprd_redo_07a.rdo
  Current log# 7 seq# 98566 mem# 1: /export/home/icssprd/data/data18/icssprd_redo_07b.rdo
Mon May 28 12:35:14 2007
ARC0: Evaluating archive   log 2 thread 1 sequence 98565
ARC0: Beginning to archive log 2 thread 1 sequence 98565
Creating archive destination LOG_ARCHIVE_DEST_1: '/export/home/icssprd/admin/arch/1_98565.dbf'
Mon May 28 12:36:47 2007
Completed checkpoint up to RBA [0x18106.2.10], SCN: 0x0003.93b3fb7d
Mon May 28 12:38:02 2007
ARC0: Completed archiving  log 2 thread 1 sequence 98565
Mon May 28 12:41:26 2007
Beginning log switch checkpoint up to RBA [0x18107.2.10], SCN: 0x0003.93b4a3a6
Thread 1 advanced to log sequence 98567
  Current log# 8 seq# 98567 mem# 0: /export/home/icssprd/data/data10/icssprd_redo_08a.rdo
... ...
3.4.5      log file switch (checkpoint incomplete)
当在做日志切换时,同时会做checkpoint,如果此时有其他checkpoint正在进行时,需要等待正在进行的checkpoint完成,此时就会产生log file switch (checkpoint incomplete)等待事件。通常发生这一等待事件时,日志切换的时间都比平时更长。
要降低该等待事件,就需要降低日志切换时引起的checkpoint遇上系统中其他checkpoint的几率。我们可以通过以下方法来进行调优:
 
  • 增加Redo Log文件的大小,使日志切换频率降低;
  • 增大参数Log_checkpoint_interval大小,该参数设置系统两次checkpoint之间Redo Log数据块(该数据块的大小由操作系统的数据块大小决定)的数量。但是Oracle会限制这些数据块总的大小要小于最小log文件的90%。如最小log文件大小为100M,操作系统的数据块大小为512K,则Log_checkpoint_interval要小于(100 * 90% / 0.5) = 180
3.4.6      log switch/archive & log file switch (archiving needed)
log switch/archive等待事件在会话等待所有Archive线程对当前log文件Archive操作完成。当LGWR进程切换日志时,如果要切入的日志还没有被Archive,需要等待其被完成Archive,这时会产生log file switch (archiving needed)等待事件。这时,在alert log中我们还能发现以下信息:
 
Thread 1 cannot allocate new log, sequence 9556 
All online logs needed archiving
 
这两个事件只有数据库在Archive模式下才会出现。说明Archive操作太慢。对这两个事件的调优主要是针对Archive设置的调优。
要提高Archive的效率,可以采取以下方法:
 
1) 调整Redo Log文件的个数和大小
大多数情况下,Redo Log文件的个数越多、大小越大,就能让归档进程有更多时间做Archive。如果Redo记录急剧增加,可以考虑加多log文件数量,这样能使归档进程有更多时间均衡归档过程。但是,如果ARCH进程无法跟上LGWR进程的处理速度时,增加Log文件数量就于事无补了。
 
2)调整checkpoint的间隔和效率
增大checkpoint的间隔也可以使归档进程有更多时间来处理归档。增大参数log_checkpoint_interval可以增大checkpoint的间隔。另外,增加DBWR进程数量、配置AIO都可以提高checkpoint的处理效率。
 
3)配置多ARCH进程
通过参数log_archive_max_processes可以配置最大ARCH进程数量。我们可以做一个脚本来执行'alter system archive log all;'命令,然后设置一个作业以固定间隔时间来执行该脚本。这个命令可以强制归档所有未归档的日志文件。这可以帮助均衡ARCH进程的归档处理负担。
 
4)调整Archive进程
增加Archive进程的buffer大小可以提高Archive效率,其大小是由参数log_archive_buffer_size控制的。该参数的初始设置为4K,最大可以增加到128K。但是,要注意,增加该参数虽然可以提供Archive效率,但是可能会使系统的整体性能下降;
另外,我们还可以通过增加Archive进程的buffer数量来提高Archive效率。Buffer数量由参数log_archive_buffer控制,最大为8.
 
5)减少系统的IO冲突、提供系统IO效率
系统整体的IO性能及冲突问题也会影响到Archive的效率。我们可以用前面介绍的方法来减少系统中存在的IO冲突、提高整体IO效率来提高Archive的效率。