作者:杨涛
对于高并发系统,尤其秒杀系统,很容易因为数据库序列使用不当造成应用堵塞,本次分享我们从数据库等待事件的角度解析下ORACLE数据库序列相关的等待事件,并总结序列使用的最佳实践。
1序列相关基本概念
对于序列有两个重要的属性,一个是序列cache值大小,一个是序列的order属性,下面我们通过两个小测试说明这两个属性对序列的影响。
测试1:ordered和noorder测试
首先我们创建一个noorder属性的序列
微信图片_20180105165751.jpg
在节点一调用该序列:
微信图片_20180105165818.jpg
然后在节点二调用该序列:
微信图片_20180105165844.jpg
我们发现节点一上序列取值是顺序的,而节点二是从序列的cache值之后开始取值的。
然后我们创建一个order属性的序列
微信图片_20180105165905.jpg
在一节点调用
微信图片_20180105165926.jpg
在二节点调用
微信图片_20180105165947.jpg
对于ORDER属性的序列,在RAC的不同节点调用,序列值始终是连续的,跟序列的CACHE值无关。
测试2:序列取不同cache值时候的性能差异测试
我们分别创建nocache、cache值为100和cache值为10000的三个序列
微信图片_20180105170019.jpg
用如下脚本分别用三个序列取10万个值,耗时统计如下
微信图片_20180105170039.jpg
结果我们发现,cache值为100时耗时明显低于nocache,而cache值为10000比cache值为100耗时并没有提升很多,应通过测试对自己的序列选择合适的cache值。
2与序列相关的几个等待事件
与序列相关的等待事件有三个row cache lock、enq:SQ-contention和enq: SV-contention。下边我们分别模拟下这三个等待事件,然后总结如果遇到大量的这类等待事件该如何处理。
我们可以通过如下SQL查看SQ和SV这两种锁的解释。
微信图片_20180105170119.jpg
测试1:row cache lock序列等待模拟
创建一个NOCACHE的序列,并使用NOORDER属性
微信图片_20180105170156.jpg
微信图片_20180105170211.jpg
分别在三个会话执行如下sql
微信图片_20180105170233.jpg
执行asql.sql
微信图片_20180105170254.jpg
NOCACHE属性的序列,在调用SEQUENCE.NEXTVAL时候,会产生等待事件row cache lock。
测试2:enq: SQ - contention模拟
创建一个CACHE为5的序列,并使用NOORDER属性
微信图片_20180105170328.jpg
分别在三个会话执行如下sql
微信图片_20180105170347.jpg
执行asql.sql
微信图片_20180105170407.jpg
有较小CACHE的序列,在多个会话调用SEQUENCE.NEXTVAL的时候,会因为获取SQ锁而产生争用,产生等待事件enq:SQ-contention。其原因是V$SESSION.AUDSID列值是利用序列创建的,Oracle在创建新的会话后,利用名为SYS.AUDSES$的序列的NEXTVAL来创建AUDSID值。Oracle 11g下SYS.AUDSES$的CACHE值默认为10000。
测试3:enq: SV - contention
创建一个CACHE为5的序列,并使用ORDER属性
微信图片_20180105170436.jpg
微信图片_20180105170449.jpg
分别在三个会话执行如下sql
微信图片_20180105170519.jpg
执行asql
微信图片_20180105170546.jpg
在RAC环境下,CACHE+ORDER属性的序列,在多个回话同时调用SEQUENCE.NEXTVAL的时候,会产生enq: SV-contention等待事件,应该尽量设置为NOORDER属性,并扩大其cache值。
3小结
首先,尽量避免nocache序列的使用;其次,在RAC环境下,为避免SV锁的争用,应该尽量避免使用ORDER 属性,尤其避免ORDER+NOCACHE的组合;最后,在序列使用的并发量较高的情况下,可以尝试增大CACHE值来缓解锁争用,一般可以设定到5000左右。
添加新评论3 条评论
2018-01-09 10:15
2018-01-06 10:07
2018-01-06 08:32