曾经有将近半年的时间,我都在跟log file sync打交道,每次查看系统压测期间的TOP 5等待事件,log file sync都稳稳的排在第一的位置,而且平均响应时间已经达到了10ms,随着一步步的优化,系统压测的TPS从刚开始时候的4000到6000到8000,TPS提升的过程也是对log file sync等待事件优化的过程。本章主要介绍log file sync相关的原理和优化技巧,希望本章的内容能或多或少的帮助到你。
在事务提交时,Lgwr需要把事务产生的日志刷新到磁盘以实现持久化,做到ACID的D的要求,前台进程从发出提交指令到接受到Lgwr进程日志写完成的通知,这整个过程都会等待log file sync等待事件。前台进程在等待log file sync的过程中是被阻断的,不能做其它事,当Lgwr刷新日志到在线日志后会通知前台进程日志写完成,前台进程接受到通知后,继续做其它事。日志一旦被刷新到磁盘标志着事务持久化的结束,通过日志来实现事务的持久化已经成为各个数据库的通用准则,之所以用日志来实现事务的持久化,速度快是最重要的一个原因,我们可以想象一个事务对一个具有3个索引表上插入10个记录,如果是通过刷新数据脏块来持久化,需要刷新多少个数据块,由于堆表的特性,10个记录可以认为是聚集在1个数据块上,但是10个记录针对索引,非常可能的索引块数能有二三十个,因为索引是有序的,不像堆表可以对记录不加区分的聚集在一起,当然使用了ASSM管理后,插入记录的时候,会根据进程的pid做hash去选择插入的数据块,因此一定程度上,对于10条记录,如果是多个进程所插入,也非常有可能是在不同的数据块中,不过我们这里说的是一个事务,当然指的就是一个进程了。按照我们的推算的话,我们仅仅是插入了10条记录,但是涉及到的脏块可能有30个左右,每次事务提交都需要刷新离散的30个数据块,这个性能实在是太低了,而日志在磁盘是有序的,因此刷新效率上要高出很多,日志还为数据库实现其他功能提供了基础,例如提供实例突然down机后的实例恢复,为实现日志挖掘提供了基础,为备库的恢复提供了基础等等。
log file sync是Oracle数据库中最普遍的等待事件之一,一般log file sync的等待时间都非常短 1-8ms,这个时间取决于你数据库的硬件配置、主机的负载情况等等,一般情况下把日志盘放在高端存储上,log file sync的时间应该能维持在1-5ms之间,如果使用的是pc,有raid卡的话,log file sync的时间应该能维持在3-15ms,但是这些数据并不绝对,还要依据你数据库的配置和负载情况来定,例如我曾经遭遇过在把日志放在本地盘,raid卡的cache有512m,log file sync接近30ms的情况,后面经过分析是由于日志写入量和脏数据块的写入量太大,导致raid卡的cache有被击穿的问题,而且当时并没有关闭raid卡的读cache,保留的默认的7:3的读写比例,一般如果使用的不是raid 5等需要做校验的raid设置例如raid 1或raid10,都可以把raid卡的cache策略全部用于写cache。但是对于存储就不能这么搞了,不能够把读cache全部关掉,只用作写cache,因为相对于raid卡的cache来说,本身的cache大小都比较小,所以就显得特别宝贵,但是存储的cache一般都比较大,例如一个中断存储的机头cache也能够8G或者16G,他们一定程度上既可以用作写cache,又是对于主机内存的一个延续。
log file sync等待事件的P1,P2,P3参数的含义:
· P1 : buffer# ,log buffer中buffer的编号
· P2,P3 未使用
产生log file sync的场景,常见有以下几种:
· commit操作
· rollback操作
· DDL操作(DDL操作实施前都会首先进行一次commit)
· DDL操作导致的数据字典修改所产生的log file sync
· 某些能递归修改数据字典的操作:比如查询SEQ的next值,可能会导致修改数据字典。一个典型的情况是,SEQ的cache属性设置为nocache,那么会导致每次调用SEQ都要修改数据字典,产生递归的log file sync。
一个正常的系统里,绝大多数的log file sync等待都应该是commit操作造成的log file sync等待,某些异常的系统,比如频繁的rollback、seq的cache设置为nocache的系统,也可能会造成比较多的log file sync等待。