在做AWR分析时,发现Top 5 Timed Events中,log file swtich(check point incomplete)排在第一位,占比达到了33.3%。联想到某次有一存储过程跑了9个多小时,而正常1个小时就能跑完的情况,估计就是因为这个等待事件了。
首先来分析一下,log file switch事件是什么原因产生的。
oracle文档上是这么形容的:
log file switch (checkpoint incomplete)
Waiting for a log switch because the session cannot wrap into the next log. Wrapping cannot be performed because the checkpoint for that log has not completed.
意思是session不能写入下一个log,导致了日志切换等待。不能写入的原因是下一个log的ckpt检查还没结束。
再来看看《剑破冰山-oracle开发艺术》上怎么描述这个等待事件的:
一般而言,此类等待事件是这么产生的,日志组都写完后,LGWR试图写第一个log file,如果此时数据库没有完成写出记录在第一个log file中的dirty块(如第一个检查点未完成),该等待时间就会出现。
Tom哥的9i&10g编程艺术中这样描述这个事件:如果数据库试图重用一个在线重做日志文件,但是发现做不到,就会把这样一条消息写到服务器上的alert.log 中(Thread 1 cannot allocate new log, sequence 1466
Checkpoint not complete)。如果DBWR 还没有完成重做日志所保护数据的检查点(checkpointing),或者ARCH 还没有把重做日志文件复制到归档目标,就会发生这种情况。对最终用户来说,这个时间点上数据库实际上停止了。它会原地不动。DBWR 或ARCH 将得到最大的优先级以将redo 块刷新输出的磁盘。完成了检查点或归档之后,一切又回归正常。数据库之所以暂停用户的活动,这是因为此时已经没地方记录用户所做的修改了。Oracle 试图重用一个在线重做日志文件,但是由于归档进程尚未完成这个文件的复制(Archival required),所以Oracle 必须等待(相应地,最终用户也必须等待),直到能安全地重用这个重做日志文件为止。
其实还是Tom哥解释的最清楚呀~~
那么怎么解决这个问题呢?
基本上可以从这几个方面来考虑:
1.扩容,就是增大重做日志的容量,增加重做日志组的数量。这样就缓冲了数据归档和循环写的时间。这个方法是最直接,不用动脑子就能想出来的。我首先把重做日志从100M扩容到200M,然后3组重做日志改成6组,每组成员2个(如果每组成员改成1个,这样肯定会更快一些,但是安全性会不会?
)
2.让DBWR跑得更快些。可以考虑多增加dbwr线程。通过调整db_writer_process参数,指定多个dbwr线程。一般8个cpu可以设置一个dbwr线程。如果没有手工设置,oracle会帮你设置。我服务器是16个cpu,但是oracle自动设置成了3个dbwr线程。因此以上对应关系不是很确定,但是oracle确实会自动设置dbwr线程数。
3.将重做日志组在磁盘上分散开来,比如一共有6组重做日志,那么把1,3组放在磁盘A上,2,5组放在磁盘B上,4,6组放在磁盘C上。Tom哥说:在线重做日志文件是一组Oracle 文件,最适合使用RAW 磁盘(原始磁盘)。由于磁盘raid我不是很熟悉,这块的实验还没做过。有熟悉的兄弟麻烦发点资料共享。
4.设置合适的归档数。由于设计之初考虑安全问题,我设置了3个归档路径,即log_arch_dest_1,2,3。现在想来,其实没有必要。可以考虑减少1个。这样写入归档的时间还能进一步减少。归档怎么减少?是不是直接将log_arch_dest_3这个参数设置为空就可以了?待实验。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16591471/viewspace-704839/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16591471/viewspace-704839/