log file sync问题的解决是一个系统工程,除了上面一节描述的调优方式,我们看看对于其他组建是否也需要调优。例如commit本身作为一个redo record也是需要被拷贝进log buffer的,如果此时log buffer太小没有了空间,那么岂不是也会在一定程度上影响提交的效率,再如,Lgwr在刷新日志前,需要确认所有分配过空间的buffer都已经拷贝结束,如果发现还有进程在持有redo copy latch就说明还有进程正在往log buffer拷贝日志,那么这个时候也会导致提交变慢。
LOG BUFFER 的调优
10G以后,LOG BUFFER一般情况下已经比较大,一般为1到多个granules大小,除非你看到了比较多的log buffer space等待事件,否则不需要调整log buffer的大小。
redo相关latch的调优
l redo copy latch:仅仅用来跟踪是否有进程正在往log buffer里拷贝数据。lgwr在真正开始写之前,必须等待相关的进程拷贝完毕,在此期间,lgwr会等待LGWR wait for redo copy等待。可以同时向log buffer里进行拷贝的进程的数量由_log_simultaneous_copies决定。除非观察到明显的redo copy latch等待,否则保持默认值。
l redo allocation latch:保护进程在redo buffer里分配空间时使用,保证各个进程间彼此分配的空间不重叠。9.2版本以前由于redo allocation latch只有一把,因此比较容易引起此latch的真用,9.2版本以后,根据主机CPU的多少,log buffer已经被拆分成多个子LOG BUFFER,每个子buffer 都有有对应的redo allocation latch,很大程度上缓解了redo allocatoin latch的争用,除非看到了明显的redo allocation latch的争用,否则不用调整log buffer的数量。10G以后,私有redo和IMU的出现,每一个私有redo都由一个私有的redo allocation latch保护,进一步降低了redo allocation latch的争用。
redo writing latch:这个latch保护的是一个标志位,进程获取这个latch后,修改标志位,比如把0改为1,代表lgwr正在写,这样后续的提交进程,获得这个latch后读取标志位,就知道当前LGWR是不是正在写了,避免了很多不需要的重复通知。
一般是不需要的,除非他们相关的等待已经引起了你的注意,而且ORACLE各个版本也一直在优化相关的latch的获取和释放,比如redo allocation latch,这一块已经做的非常高效了。
10G之前,在事务做提交的时候,必须等待Lgwr刷日志完成才能继续做其它事,也就是说必须符合事务持久化的条件,可能学过其他数据库的同学学ORACLE的时候怪怪的,因为像MYSQL、MONGODB等数据库都支持对日志的异步刷新,我想之所以ORACLE这么晚才推出这一功能,主要还是使用ORACLE的客户都是金融、证券等行业巨多,这些行业对于数据的丢失是零容忍的,因此他们对此并无需求,直到10GR1,ORACLE公司才默默的推出了一个参数:commit_logging,这个参数可以实现让事务在提交时,并不同步刷新日志,而是在合适的时候去触发,这个参数可以有四种组合:
commit write [batch|immediate][wait|nowait]
10GR2版本发布的时候,这个参数被拆成了2个参数,commit_logging,commit_write,个人认为10GR2拆分后的参数,更能准确表达参数的意图。我们先着重的看下commit_write这个参数,它的参数值可以为wait/nowait,代表:前台进程在进行事务提交的时候,通不通知LGWR去刷新日志。wait为通知,前台进程会等待log file sync。nowait为不通知,仅仅等待其他操作触发lgwr去写日志(如3秒,1M大小,1/3满)。如果你的业务对数据的一致性的要求不高,对ACID的D没有要求,为了提高事务数、提高性能,你可以选择commit_write为nowait方式。而在10G以前,ACID的D是必须满足的,也就是说,前台进程在提交的时候,必须要等待LOG FILE SYNC,等待LGWR刷新日志到磁盘。我们再来看下commit_logging参数,参数可以选择的值有batch/immediate,这个参数极其容易引起人的误解,让人误以为batch的含义是,控制着事务是否以group commit的方式打包提交,而immediate含义是让事务一个个的提交,一次提交刷新一次log buffer,但实时不是这样的!
immediate与batch相比,commit的改变向量(修改回滚段头的事务槽)将作为stand alone(单独的)的redo record产生,跟9I的commit记录日志的方式是一样的。batch 模式下commit改变向量的记录方式是合并进事务产生的change vector里,作为一个redo record,这个batch模式依赖是否使用私有redo和IMU,如果私有redo和IMU被关闭的情况下,batch的设置也就没了作用。
我们对insert into a values(1111);commit;来进行dump log file,阐述一下batch/immediate方式的区别 :
DUMP LOG FILE:启用私有redo和IMU,设置commit_logging为immediate,commit的日志作为单独的redo record产生,一共2条redo record,第二个redo record为commit产生的,见加粗部分(OP:5.4,代表为UNDO段头的修改)
REDO RECORD - Thread:1 RBA: 0x00044d.00000002.0010 LEN: 0x0230 VLD: 0x05 |
DUMP LOG FILE:启用私有redo和imu,设置commit_logging为batch,commit作为一个改变向量合并进了事务的redo record里,作为一条redo record,change #3为commit产生的。
REDO RECORD - Thread:1 RBA: 0x00044d.00000002.0010 LEN: 0x0230 VLD: 0x05 |
个人感觉commit_logging参数的作用不大,可能有助于减少ACID的异常时间,对日志量的size在batch模式下有轻微的减少。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。