Oracle高并发系列1:DML引起的常见问题及优化思路
《Oracle高并发系列1:DML引起的常见问题及优化思路》要点: 作者介绍 Oracle数据库是设计为一个高度共享的数据库,这里所说的“共享”,可以从数据库共享内存、后台进程、cursor、执行计划、latch等方面去理解.Oracle如此设计的目的是以最小的系统开销、最大化地支持更多的并发会话.也是基于这个设计思想,所以Oracle单个实例的垂直扩展能力一直是DB领域内的佼佼者. 之前曾经看到PG大牛的文章分析关于Oracle的CursorPin S为什么不会在PostgreSQL里面出现,其主要原因是PostgreSQL的执行计划不是全局共享的,而Oracle里面同样的Cursor在不同session间一般情况下都是可以共享的(Oracle在某些条件下会也触发重新硬解析).这样的设计客观来讲其实各有优劣,虽然PG的plan cache是不同会话不共享的,避免了高并发时不同会话对同一个cursor产生争用,但是也意味着同样的并发会话数的情况下,PG的会话所需求的cache会更多,而且每个会话都至少要parse一次;或者反过来说同样的资源限制的前提下,Oracle支持的并发数更高. 引用一位Oracle 7的OCP,资深Oracle老司机的一段话:“早期Oracle就是使用session私有内存,但当负载并发增加时,内存消耗成了问题,而且执行计划无法共享,增加率parse时间,对于OLTP系统parse时间的增加对于整体执行时间影响较大.因此Oracle基于这一点进行了优化,包括session cached cursor和shared pool等,减少了SQL执行过程中的parsing time和planning time.但没有免费的午餐,肯定会有其它消耗,类似内存结构的并发保护上的成本.总之:
这里不探讨哪个数据库更NB,每种数据库技术的发展会受多种因素的影响,包括商业战略、市场需求、软硬件技术成熟度等.我们采用Oracle多年,对于Oracle数据库有深厚的感情,但是目前也同时义无反顾地投入开源数据库和NoSQL的怀抱,技术无好坏,最适合应用场景的就是最好的.这里只重点探讨,当Oracle数据库的这些“共享”资源,遭遇高并发时的问题发生的原因和应对措施. 这里谈的是思路,不是具体的命令. 这里的处理方法,是基于过往发生过的实际案例总结而来. 高并发的DML引发的问题Oracle的表是堆表,索引是B树,当对表做DML时,Oracle会对table的block进行操作,同时也对索引树的block进行维护,那么当同一时间有大量会话都需要对索引(或表)的同一个block做维护时,就会产生索引(或表)上面的争用.当出现争用时,v$session_wait显示了当前的会话正在等待的event name. 这个等待事件表明,当前的会话正在等待一个block上面的事务槽的分配,可能是table block或index block. 可能的原因有:
解决思路:
小知识点: 在v$lock中若看到某个会话正request一个lmode为4的锁,其原因之一就可能是ITL等待造成的,其它原因可能是并发操作主键、位图索引、分布式事务等. 这个问题一般发生在表在高并发insert操作时,等待在字段类型是日期、自增序列的索引block上.因为应用始终插入的都是最新(high key)的值,导致这些索引一般都是右倾斜增长的,也就是说最近最频繁的操作都发生在索引最右边的那个叶子块上,叶子块的free空间很快被填满,然后叶子块要分裂,分裂过程总要去找free block,index spliter的进程会持有一个enq:TX锁,其它并发insert的进程一般也正是需往最右边的这个index leaf block去insert数据,所以都要等待这个spliter进程完成并释放这个锁.(竞争更加激烈时,甚至会在branch block的split时产生) (编辑:ASP站长网) |