BIND_MISMATCH导致过多VERSION COUNT的问题
并不是用了綁定變量就一定都會(huì)游標(biāo)共享,下面我們介紹的就是一種例子。BIND_MISMATCH導(dǎo)致VERSION COUNT過(guò)多的原因解釋:
This is due to the bind buffer mismatch of the current child cursor. If oracle is unable to bind the current value to the existing child cursors bind buffer,?
Oracle upgrades the existing child cursor with a high bind buffer. This will force the query to do a hard parse and a new child cursor will be created.
對(duì)于綁定變量,ORACLE根據(jù)變量長(zhǎng)度進(jìn)行了分級(jí),對(duì)于VARCHAR2類型共有如下4級(jí):
第一級(jí): 1-32
第二級(jí): 33-128
第三級(jí): 129-2000
第四級(jí): 2000+
Oracle在進(jìn)行bind graduation的時(shí)候,使用的是綁定變量的聲明類型長(zhǎng)度。對(duì)于定義的變量在同一級(jí)可以共享游標(biāo),否則會(huì)生成子游標(biāo),如下:
SQL> desc t
?名稱 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?是否為空? 類型
?----------------------------------------- -------- ----------------------------
?X ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?VARCHAR2(30)
SQL>?variable v_x varchar2(32)
SQL> exec :v_x:='a';
PL/SQL 過(guò)程已成功完成。
SQL> select * from t where x=:v_x;
未選定行
SQL> ?select sql_id,child_number,executions from v$sql where sql_text='select * from t where x=:v_x';
SQL_ID ? ? ? ?CHILD_NUMBER EXECUTIONS
------------- ------------ ----------
1pqg8dpwthcp3 ? ? ? ? ? ?1 ? ? ? ? ?1
SQL>?variable v_x varchar2(33)
SQL> exec :v_x:='a';
PL/SQL 過(guò)程已成功完成。
SQL> select * from t where x=:v_x;
未選定行
SQL> select sql_id,child_number,executions from v$sql where sql_text='select * from t where x=:v_x';
SQL_ID ? ? ? ?CHILD_NUMBER EXECUTIONS
------------- ------------ ----------
1pqg8dpwthcp3 ? ? ? ? ? ?1 ? ? ? ? ?1
1pqg8dpwthcp3 ? ? ? ? ? ?2 ? ? ? ? ?1
SQL> select ?child_number,bind_mismatch from v$sql_shared_cursor where sql_id='1pqg8dpwthcp3';
CHILD_NUMBER B
------------ -
? ? ? ? ? ?1 N
? ? ? ? ? ?2 Y
SQL>?variable v_x varchar2(129)
SQL> exec :v_x:='a';
PL/SQL 過(guò)程已成功完成。
SQL> select * from t where x=:v_x;
未選定行
SQL> select sql_id,child_number,executions from v$sql where sql_text='select * from t where x=:v_x';
SQL_ID ? ? ? ?CHILD_NUMBER EXECUTIONS
------------- ------------ ----------
1pqg8dpwthcp3 ? ? ? ? ? ?1 ? ? ? ? ? 1
1pqg8dpwthcp3 ? ? ? ? ? ?2 ? ? ? ? ?1
1pqg8dpwthcp3 ? ? ? ? ? ?3 ? ? ? ? ?1
SQL> ?select ?child_number,bind_mismatch from v$sql_shared_cursor where sql_id='1pqg8dpwthcp3';
CHILD_NUMBER B
------------ -
? ? ? ? ? ?1 N
? ? ? ? ? ?2 Y
? ? ? ? ? ?3 Y
SQL>?variable v_x varchar2(2001)
SQL> exec :v_x:='a';
PL/SQL 過(guò)程已成功完成。
SQL> select * from t where x=:v_x;
未選定行
SQL> select sql_id,child_number,executions from v$sql where sql_text='select * from t where x=:v_x';
SQL_ID ? ? ? ?CHILD_NUMBER EXECUTIONS
------------- ------------ ----------
1pqg8dpwthcp3 ? ? ? ? ? ?1 ? ? ? ? ?1
1pqg8dpwthcp3 ? ? ? ? ? ?2 ? ? ? ? ?1
1pqg8dpwthcp3 ? ? ? ? ? ?3 ? ? ? ? ?1
1pqg8dpwthcp3 ? ? ? ? ? ?4 ? ? ? ? ?1
SQL> ?select ?child_number,bind_mismatch from v$sql_shared_cursor where sql_id='1pqg8dpwthcp3';
CHILD_NUMBER B
------------ -
? ? ? ? ? ?1 N
? ? ? ? ? ?2 Y
? ? ? ? ? ?3 Y
? ? ? ? ? ?4 Y
具體可以參考:High Version Count Due To BIND_MISMATCH [ID 336268.1] ? ?
ORACLE文檔說(shuō)可以通過(guò)設(shè)置10503事件來(lái)搞定這個(gè)問(wèn)題 ,?10503 =>?enable user-specified graduated bind lengths
(1)查詢綁定變量最大長(zhǎng)度:假如最大長(zhǎng)度為128
select max(max_length) from v$sql_bind_metadata where datatype=1;
(2)在參數(shù)文件中設(shè)置:
event="10503 trace name context forever, level 128"
或
SQL> alter system set event='10503 trace name context forever, level 128' scope=spfile;
(3)該參數(shù)在會(huì)話級(jí)別雖然能夠成功設(shè)置,但是無(wú)效。
Bug 10274265 - Event 10503 does not work at session level [ID 10274265.8]SQL> select * from v$version;BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE ? ?10.2.0.1.0 ? ? ?Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production ??
SQL> alter system flush shared_pool;
系統(tǒng)已更改。
SQL> alter system set events '10503 ?trace name context forever ,level 4096';
系統(tǒng)已更改。
SQL> variable c varchar2(32);
SQL> exec :c := 'zheng';
SQL> select id from edu.zhhtest where name= :c and rownum=1;
SQL> variable c varchar2(33);
SQL> exec :c := 'zheng';
SQL> select id from edu.zhhtest where name= :c and rownum=1;
SQL> select sql_id,child_number,executions from v$sql where sql_text='select id from edu.zhhtest where name= :c and rownum=1';
SQL_ID??????? CHILD_NUMBER EXECUTIONS
------------- ------------ ----------
grzn6d2ak22j4??????????? 0????????? 2
SQL> select s.child_number, m.position, m.max_length,
???????? decode(m.datatype,1,'varchar2',2,'number',m.datatype) as datatype
? 3??? from v$sql s, v$sql_bind_metadata m
? 4??? where s.sql_id = 'grzn6d2ak22j4'
? 5??? and s.child_address = m.address
? 6??? order by 1, 2;
CHILD_NUMBER?? POSITION MAX_LENGTH DATATYPE
------------ ---------- ---------- ----------------------------------------
?????????? 0????????? 1?????? 4000 varchar2
?
?
Bind Graduation的目的是什么?可能原因有如下兩個(gè):
?
?
從效果來(lái)看,Oracle bind graduation會(huì)增加子游標(biāo)的數(shù)量。如果單就bind peeking而言,在Oracle 11g的ACS(Adaptive Cursor Sharing)出現(xiàn)之前,
Oracle綁定變量使用的子游標(biāo)數(shù)量是很少的。Bind graduation出現(xiàn)之后,我們最直觀的感覺(jué)是child cursor增多,對(duì)應(yīng)的執(zhí)行計(jì)劃增多。
原有的可能只用一個(gè)執(zhí)行計(jì)劃可以覆蓋的綁定變量語(yǔ)句,可能要有多個(gè)執(zhí)行計(jì)劃才能覆蓋。
?
對(duì)綁定變量語(yǔ)句而言,每次生成子游標(biāo),就意味著要進(jìn)行一次hard parse,就意味著要進(jìn)行一次peeking。生成與Peeking value對(duì)應(yīng)的執(zhí)行計(jì)劃。
代碼中對(duì)變量聲明長(zhǎng)度的不一致,直接意味著不同的程序模塊和功能模塊。Oracle也許認(rèn)為這樣出現(xiàn)bind peeking問(wèn)題的幾率較高。于是取巧采用變量聲明的方式進(jìn)行區(qū)分管理。
同時(shí),劃分區(qū)域又不是很多,從而限制了子游標(biāo)出現(xiàn)的數(shù)量。多次peeking,形成多個(gè)子游標(biāo),配對(duì)更合適的執(zhí)行計(jì)劃。
?
?2.?? 綁定變量存儲(chǔ)
?
對(duì)執(zhí)行計(jì)劃而言,Oracle是需要單獨(dú)分配內(nèi)存空間給執(zhí)行計(jì)劃進(jìn)行保存的。如果其中有使用綁定變量,Oracle是會(huì)將綁定變量保存在child cursor中的。
在分配varchar2類型的綁定變量大小空間時(shí),使用bind graduation可以分配略小的適當(dāng)空間。
雖然會(huì)存在bind graduation現(xiàn)象,但是我們說(shuō)實(shí)現(xiàn)graduation的分區(qū)數(shù)量是有限的。也就是說(shuō),即使多次生成child cursor,帶來(lái)version count過(guò)多的風(fēng)險(xiǎn)也是有限的。
如果要是很極端的情況,比如項(xiàng)目組希望實(shí)現(xiàn)絕對(duì)的共享或者說(shuō)變量數(shù)目較多引起version count過(guò)多,可以使用10503事件控制bind graduation的出現(xiàn),或者直接在代碼中聲明
varchar2(2000)的綁定變量即可。
?相關(guān)的視圖:
- ?v$sql_bind_capture;
- ?v$sql_bind_metadata?
- ?v$sql_shared_cursor?
- ?v$sql?
- ?v$sqlarea
select s.child_number, m.position, m.max_length,decode(m.datatype,1,'varchar2',2,'number',m.datatype) as datatype
from v$sql s, v$sql_bind_metadata m where s.sql_id = 'abz9zj4ryuw67' and s.child_address = m.address order by 1, 2;
select sql_id,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='abz9zj4ryuw67';
11GR2的測(cè)試結(jié)果是第一次會(huì)是BIND_LENGTH_UPGRADEABLE,然后才會(huì)出現(xiàn)BIND_MISMATCH,估計(jì)是單純的增加了綁定變量buffer的長(zhǎng)度,從而生產(chǎn)一個(gè)新的計(jì)劃.
而不是重新bind peeking 然后生產(chǎn)計(jì)劃。當(dāng)對(duì)于一個(gè)SQL_ID有過(guò)一次bind_length_upgrade后,如果再次因?yàn)榻壎ㄗ兞块L(zhǎng)度不一樣,不能重用計(jì)劃是,就會(huì)bind peeking產(chǎn)生新的計(jì)劃。
參考鏈接
http://blog.itpub.net/17203031/viewspace-704144
http://blog.itpub.net/17203031/viewspace-704348
http://blog.itpub.net/758322/viewspace-750315/
http://www.net527.cn/shujukuguanli/Oracle/2012/0407/22446.html
轉(zhuǎn)載于:https://www.cnblogs.com/princessd8251/p/3843850.html
總結(jié)
以上是生活随笔為你收集整理的BIND_MISMATCH导致过多VERSION COUNT的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Using dbms_shared_po
- 下一篇: 函数模板的载体-HPP