BIND_MISMATCH导致过多VERSION COUNT的问题
并不是用了綁定變量就一定都會游標共享,下面我們介紹的就是一種例子。BIND_MISMATCH導致VERSION COUNT過多的原因解釋:
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.
對于綁定變量,ORACLE根據變量長度進行了分級,對于VARCHAR2類型共有如下4級:
第一級: 1-32
第二級: 33-128
第三級: 129-2000
第四級: 2000+
Oracle在進行bind graduation的時候,使用的是綁定變量的聲明類型長度。對于定義的變量在同一級可以共享游標,否則會生成子游標,如下:
SQL> desc t
?名稱 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?是否為空? 類型
?----------------------------------------- -------- ----------------------------
?X ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?VARCHAR2(30)
SQL>?variable v_x varchar2(32)
SQL> exec :v_x:='a';
PL/SQL 過程已成功完成。
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 過程已成功完成。
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 過程已成功完成。
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 過程已成功完成。
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文檔說可以通過設置10503事件來搞定這個問題 ,?10503 =>?enable user-specified graduated bind lengths
(1)查詢綁定變量最大長度:假如最大長度為128
select max(max_length) from v$sql_bind_metadata where datatype=1;
(2)在參數文件中設置:
event="10503 trace name context forever, level 128"
或
SQL> alter system set event='10503 trace name context forever, level 128' scope=spfile;
(3)該參數在會話級別雖然能夠成功設置,但是無效。
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;
系統已更改。
SQL> alter system set events '10503 ?trace name context forever ,level 4096';
系統已更改。
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的目的是什么?可能原因有如下兩個:
?
?
從效果來看,Oracle bind graduation會增加子游標的數量。如果單就bind peeking而言,在Oracle 11g的ACS(Adaptive Cursor Sharing)出現之前,
Oracle綁定變量使用的子游標數量是很少的。Bind graduation出現之后,我們最直觀的感覺是child cursor增多,對應的執行計劃增多。
原有的可能只用一個執行計劃可以覆蓋的綁定變量語句,可能要有多個執行計劃才能覆蓋。
?
對綁定變量語句而言,每次生成子游標,就意味著要進行一次hard parse,就意味著要進行一次peeking。生成與Peeking value對應的執行計劃。
代碼中對變量聲明長度的不一致,直接意味著不同的程序模塊和功能模塊。Oracle也許認為這樣出現bind peeking問題的幾率較高。于是取巧采用變量聲明的方式進行區分管理。
同時,劃分區域又不是很多,從而限制了子游標出現的數量。多次peeking,形成多個子游標,配對更合適的執行計劃。
?
?2.?? 綁定變量存儲
?
對執行計劃而言,Oracle是需要單獨分配內存空間給執行計劃進行保存的。如果其中有使用綁定變量,Oracle是會將綁定變量保存在child cursor中的。
在分配varchar2類型的綁定變量大小空間時,使用bind graduation可以分配略小的適當空間。
雖然會存在bind graduation現象,但是我們說實現graduation的分區數量是有限的。也就是說,即使多次生成child cursor,帶來version count過多的風險也是有限的。
如果要是很極端的情況,比如項目組希望實現絕對的共享或者說變量數目較多引起version count過多,可以使用10503事件控制bind graduation的出現,或者直接在代碼中聲明
varchar2(2000)的綁定變量即可。
?相關的視圖:
- ?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的測試結果是第一次會是BIND_LENGTH_UPGRADEABLE,然后才會出現BIND_MISMATCH,估計是單純的增加了綁定變量buffer的長度,從而生產一個新的計劃.
而不是重新bind peeking 然后生產計劃。當對于一個SQL_ID有過一次bind_length_upgrade后,如果再次因為綁定變量長度不一樣,不能重用計劃是,就會bind peeking產生新的計劃。
參考鏈接
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
轉載于:https://www.cnblogs.com/princessd8251/p/3843850.html
總結
以上是生活随笔為你收集整理的BIND_MISMATCH导致过多VERSION COUNT的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Using dbms_shared_po
- 下一篇: 函数模板的载体-HPP