你知道哪些 Cursor共享哪些事

早些年搞Oracle的时刻,最让人头疼的事件就是和共享池关系的,而共享池里遇到疑问最多的事件大少数是和SQL编译关系的,关于十多年前这方面的往事我最近总想写一篇Oracle往事来给大家引见一下。

Oracle共享池最后是为了全局共享SQL口头方案而设计的,全局共享口头方案可以最大限制的缩小SQL解析,在高并发的系统中优化数据库的全体并发才干,这关于二三十年前的计算机配件来说至关关键。其实除了Oracle之外,那个时代开展起来的商用数据库大多也允许全局SQL口头方案共享,比如SQL SERVER 的Parameterized Query Plan Caching。

全局SQL PLAN共享并不是数据库必定具有的性能,也不是一切的数据库都允许全局SQL PLAN共享,MySQL、Postgresql等开源数据库以及绝大少数国产数据库都是会话级共享SQL PLAN的。会话级共享SQL PLAN或许没有全局共享成果好,不过MySQL、PG这些数据库在设计之初并没有思考在复杂业务场景下的超高并发口头疑问,因此全局共享SQL PLAN并不是其触及要点。驳回会话级共享口头方案缩小了数据字典关系的锁以及字典缓冲的闩锁争用,有效的降落了SQL解析器的复杂度,有助于数据库更稳固的运转,特意是在数据字典不太出现变动的场景中。随着现代配件的极速开展,在大少数状况下,SQL解析所消耗的系统资源曾经不成为关键的疑问了,因此没有经常使用全局SQL PLAN CACHE的开源数据库在绝大少数高并发量口头的场景中也都能够胜任。在我所遇到的运维案例中,反而是驳回全局口头方案共享的Oracle数据库经常在负载不算太高的场景中,比如每秒几万次口头的场景中,由于硬解析过多而触发了shared pool、Library cache 、cursor mutex等方面的争用,引发了较为重大的性能疑问。

不论如何,共享口头方案(全局和会话级)确实有效的提高了数据库在SQL解析方面的效率,从而可以更好的撑持高并发场景和一些数据字典经常出现变卦的高并发场景。不同的数据库共享SQL PLAN的成功形式差异很大,Oracle经常使用家传的共享池,随着Oracle数据库的开展,共享池曾经变成了一个极端极端复杂的全局共享数据结构,不只仅用于SQL PLAN共享,其全局内存堆(KGH)治理的形式是一致的。其余数据库普通经常使用相对繁难一点的SQL PLAN CACHE来成功口头方案共享。

成功口头方案共享遇到的第一个疑问是SQL经常使用非绑定变量的疑问,最后的SQL共享齐全是基于SQL文本的,其原理是对SQLTEXT做一个HASH函数,HASH值相反的SQL被以为是相反的,可以共享的。假设咱们在SQL中间接经常使用常量值而没有经常使用绑定变量,那么SQL是无法共享的。Oracle在早期想要共享cursor,必定强迫开发人员在编程时经常使用绑定变量。但是开发人员的水平错落不齐,经常会遗记这个开发规范。于是Oracle经过cursor_sharing参数对SQL启动签名处置。智能将相似的SQL启动归并,从而让SQL能够最大限制的共享。哪怕写程序是没有经常使用绑定变量,SQL解析器会智能帮你成功这个上班。

经过cursor_sharing智能处置非绑定变量的SQL或许经常使用绑定变量必定是件善报件吗?也不必定是这样的,假设某条SQL只要一个最佳的SQL PLAN,这是没有疑问的。不过在事实中或许存在相反的SQL有多种最好的口头方案的状况存在。比如上方这个例子。

当Object_id为20的时刻,记载数有419万行数据,因此全表扫描是比拟正当的口头方案。

而当Object_id=21的时刻,前往数据只要16行,因此此时经常使用索引范畴扫描是比拟正当的口头方案。而假设咱们经常使用绑定变量,select object_name from t1 where object_id=:p,这样两种状况假设共享口头方案,那就清楚是不正当的。

这种状况下假设共享口头方案,那么或许会出现十分怪异的状况。比如说同一条SQL有时刻走索引,有时刻走全表扫描。有时刻突然就会少量SQL不走索引所有走口头方案了。甚至出现同一条SQL在不同RAC节点上,一个节点是走索引的,另一个节点上死活不走索引。其实明白了SQL共享与SQL解析的原理就很清楚了。在解析带有绑定变量或许经过cursor_sharing启动共享的SQL的时刻,会启动绑定变量的窥探,编译时带入的参数就选择了口头方案最终走不走索引。而下一回同一条可共享的SQL口头的时刻,就不会再去窥探参数了,因此就会造成不用要的SQL口头方案失误。

为了处置这个疑问,Oracle推出了Adaptive Cursor Sharing(ACS)。在ACS技术的加持下假设存在数据偏斜,ACS 能够识别不同的绑定变量值具有不同的选用性,从而选用最为正当的口头方案。

当带有绑定变量的 SQL 语句初次被解析时,优化器会窥探绑定变量的值,并依据谓词的选用性生成一个口头方案,同时把该游标标志为 bind-sensitive(绑定敏感的)。当雷同的 SQL 语句再次被口头时,优化器会比拟绑定变量的值和之前的值,假设发现选用性有清楚差异,优化器或许会创立一个新的子游标和口头方案,同时把该游标标志为 bind-aware(绑定感知的)。当雷同的 SQL 语句再次被口头时,优化器会依据绑定变量的值的选用性范畴,婚配最适宜的子游标和口头方案,从而防止经常使用不适宜的口头方案。

目前Oracle ACS可以在绝大少数场所下处置cursor共享的疑问,不过ACS也存在必定的负面作用。比如会参与每次SQL口头的开支,同时会让一个CURSOR发生过多的不共享的口头方案,从而影响这个CURSOR的口头效率,参与MUTEX争用,重大时会引发系统性能疑问。因此在某些运行场景中,用户会选用封锁ACS性能。

看到这里或许大少数好友都会感觉我当天还是在炒Oracle ACS的冷饭,假设能看到这里的好友,当天算是来对了。前面的近两千字的铺垫,只是为了让人更好地理解当天我想带给大家的一些干货。

当天要带给大家的第一点干货是和Oracle ACS关系的。只管很少数据库不允许全局SQL PLAN CACHE,不过普通都允许会话级SQL PLAN CACHE。当某条SQL口头屡次的时刻,就不会再对这条SQL做解析,而间接复用缓冲中的口头方案了。那么与ORACLE 相似的疑问出现了,假设数据是不平衡的,有些时刻要走索引,有些时刻须要走全表扫描怎样办?这种状况下,就会出现相似Oracle出现过的奇异现象,某条SQL,有时刻口头效率高,有时刻口头效率低,而且咱们无法控制。遇到这种状况,有时刻或许就是由于SQL PLAN CACHE缓冲的口头方案不必定适宜某个场景的SQL。

有些用过Oracle的好友或许会想到处置这个疑问的方法,那就不经常使用绑定变量,让SQL PLAN无法共享。其实这个方法在某些开源或许国产数据库中并不必定有效。比如PG数据库,自动就会对SQL启动签名,智能转换成绑定变量格局,就像Oracle数据库里设置了cursor_sharing=FORCE。而且这些数据库往往有不允许相似Oracle ACS的性能,因此经常使用非绑定变量来处置这个疑问是有效的。

咱们该如何处置这个疑问呢?其真实Oracle占主导位置的时代,这个疑问就曾经有解了。假设咱们封锁了ACS性能,但是确实存在某些场景中雷同的SQL带入不同的参数时,须要有不同的口头方案,该如何处置呢。遇到这种状况,咱们就只能经过在SQL语句上加上注释(/* PLAN B */),强迫性的让优化器把这条SQL辨别为两条不同的SQL。实践上,当Oracle还没有推出ACS性能的时刻,咱们就是这样在cursor_sharing=FORCE的数据库里纠正失误的口头方案的,这个方法关于MySQL、PG和一些国产数据库依然有效。

当天的第二点干货是关于散布式数据库的,与集中式数据库不同的是,散布式数据库上的 硬解析的老本要高得多,因此在散布式数据库中,尽或许要成功SQL PLAN CACHE。因此在散布式数据库上,由于SQL PLAN CACHE惹起的SQL PLAN CACHE中的口头方案不适配的疑问依然是存在的,并且在一些高负载的场景中,往往由于此类疑问引发散布式集群范畴的性能疑问。这种状况下,假设你能够很快发现疑问,并且将某个不正当的口头方案从SQL PLAN CACHE中肃清掉,很快就能处置数据库集群的性能疑问。

周五的时刻,张瑞远先生就和我探讨过一个在OB上遇到的SQL PLAN CACHE引发的口头方案疑问。经过剖析发现OB自动的CURSOR_SHARING是FORCE,也就是说自动状况下,OB会智能对SQL启动签名,将没有经常使用绑定变量的SQL转化为经常使用绑定变量的格局。假设访问的数据存在较为重大的列歪斜现象,那么就会遇到SQL PLAN CACHE中的口头方案不实用的疑问。经过和OB的好友一同探讨,对OB中处置这个疑问初步有了一个方案。首先在Oracle上经常使用 的PLAN B方案依然实用。假设某条SQL依据绑定变量不同,有大批的几种状况可以明白辨别,那么PLAN B方案是可行的。假设数据歪斜疑问比拟复杂,不能繁难的分类,那么在OB中可以经过HINT或许outlines,将这条SQL设置为不实用PLAN CACHE来规避这个疑问。

在Oracle数据库中,也有相似的HINT,在数据库产品没有ACS性能或许封锁了ACS性能的 时刻,这是一种十分有效的方法。绕开PLAN CACHE可以让自身就无法共享口头方案的SQL不要去搅扰PLAN CACHE,可以更好的包全全局PLAN CACHE。

没想到当天写着写着就写多了,数据库的疑问,每个小疑问其实都够复杂的,摊开了讲,三五千字基本说不清楚,不过不要紧,花上几年期间,一个个钻研清楚,你也就成了高手了。

您可能还会对下面的文章感兴趣: