遊標共享verion count

1 10g版本,綁定變量窺視。

2 11g版本,自適應遊標。

一個sql_id,對應多個執行計劃,具有不同的plan_hash_value。例如version_count爲200個,load_VERSION 爲3.

從awr使用

select *from table(dbms_xplan.display_awr('sql_id');查看歷史的執行計劃有2個,形同的sql_id,不同的plan_hash_value,走不一樣的索引

轉自

http://blog.csdn.net/notbaron/article/details/50927492

 

在Oracle 10g以上的版本,High version count可謂是一個臭名昭著的問題。Hight version count不僅僅產生的原因多種多樣,並且會導致各種令人頭痛的問題,輕導致數據庫的性能急劇下降,CPU利用率劇增,重則導致數據庫掛起,觸發ORA-04031或者其它bug導致宕機。

什麼是verion count,什麼是high?

在弄清楚診斷和解決這個問題之前,首先需要清楚什麼是version count,什麼是high?換而言之就是產生version count的原因,多高的version count纔算high。

一個SQL 第一次執行時,會進行硬解析,同時創建parent cursor 和child cursor。

當再次執行這個SQL時,那麼首先會對SQL 語句進行特殊的hash 運算,對應生成一個hash value。Hash value存放在parent cursor中,然後會用這個hash value到paranet cursor的bucket中匹配,如果相同的hash value 已存在parent cursor裏,則繼續遍歷這個child cursor,如果可重用,那麼就沿用child cursor的信息,如果不能重用,就會重新生成一個新的child cursor。

一個parent cursor下child cursor 的總數,就是這個SQL的version count。

事實上,我們很難去準確定義一個high version count的值,只能根據不同的系統來判斷是否爲high verison count。在AWR報告中,默認verion count超過20的SQL就會顯示在order by version count一欄中。根據經驗version count如果超過100,可能就需要引起注意了。

我們可以通過查看v$sqlarea視圖的loaded_versions來判斷當前這個SQL的version count是多少,然後再通過address的值來查詢v$sql_shared_cursor視圖看那些字段的返回值爲Y,Y代表mismatch。Mismatch是引起產生version count的直接原因。通常我們可以綜合:

v$sqlarea, v$sql_shared_cursor, v$sql_bind_metadata, v$sql_bind_captures來診斷這類問題,但是手工去查這些表往往過於繁瑣,  Abel Macias 開發了一個小工具叫做version_rpt,這個工具可以用來診斷導致是那個模塊出現mismatch,從而導致了high version count。我們可以到High SQL Version Counts – Script to determine reason(s) (DOC ID 438755.1)上下載這個小工具。

Cursortrace和cursordump

當然有時候我們會遇到某些SQL的$sql_shared_cursor所有的字段的結果都爲N,但是其version count還是很高的情況,那麼這些查詢這些視圖就不管用了,主要的原因是存在部分bug,可能導致v$sql_shared_cursor的信息不準確。例如:

Bug 12539487 – gv$sql_shared_cursor may not show all reasons to not share a cursor (Doc ID 12539487.8)

所以在10g以上版本可以使用cursortrace來查找high version count的原因。

可以使用以下方式打開cursortrace:

SQL>alter system set events

'immediate trace name cursortrace level 577, address <hash_value>';

其中可以使用三個level,level 1爲577, level 2爲578, level 3爲580(實際上還有其它level,只是沒有文檔記載)

如需關閉cursortrace,則可以使用以下方式進行關閉:

SQL>alter system set events

'immediate trace name cursortrace level 2147483648, address 1';

或者使用以下方式關閉:

SQL>alter session set events 'immediate trace name cursortrace level 128 , address <address>';

當然也可以通過oradebug的方式來進行cursortrace,這裏就不詳述了。

注意在10.2.0.4以下版本存在Bug 5555371導致cursortrace無法徹底關閉的情況,最終導致其trace文件不停的增長,從而可能導致oracle文件系統被撐爆的現象。

在實際幫助客戶處理查找high version count的原因時,我們發現即使在10.2.0.5以上的版本也可能會出現cursortrace無法徹底關閉的現象。

如果數據庫版本在10.2.0.4 以下,生產系統上不建議使用cursortrace ,

生產環境在10.2.0.4 以上版本,建議謹慎使用cursortrace 。例如注意觀察,如果無法關閉則通過修改MAX_DUMP_FILE_SIZE 參數限制cursortrace trace 文件的最大大小,或者寫一個crontab 的job 定期清理其trace 文件。

在11g中引入cursordump,我們可以使用如下方式進行cursor dump:

alter system set events 'immediate trace name cursordump level 16'

這種方式收集的信息比較全:例如它可以採集到部分別的方式無法看到的px_mismatch以及它會進一步展開optimizer_mismatch的信息等。

在10gR2版本中, 我們更傾向於使用processstate dump和errorstack的信息來替代cursordump,因爲processstate dump中也存在cursordump的信息:

先找到high version count SQL對應的spid,然後執行以下SQL:

SQL>oradebug setospid

SQL>oradebug ulimit

SQL>oradebug dump processstate 10

SQL>oradebug dump errorstack 3

一些可能導致問題的SQL和配置

我們通常可以使用AWR和ASH來找出這些可能存在問題的SQL。根據以往的經驗,最容易導致出現version count的SQL包括以下類型:(只是列出最常見的寫法,並不是很全)

1.       Insert 語句使用綁定變量

Insert into table(column1, column2, column128, …) values (:1,  :2, :3, … :128, …)

尤其是對於某些表字段類型特別多的,並且把這個表所有字段都寫到insert語句裏面的表現得尤爲明顯。

2.       select into 語句使用綁定變量

select a, b, c, … into :1,:2,:3 from table1

3.       使用insert … returning 語句

4.       使用一個很長的inlist ,並且裏面都是綁定變量

select * from table where column1 in (1,  :2, :3, … :128, …)

5.       SQL 非常長並且裏面帶有多個綁定變量

如果一個SQL語句特別長,並且使用了綁定變量,那麼這樣的SQL更傾向於出現high version count。

6.       Dblink 調用SQL 語句,最好不要使用綁定變量

Bug 12320556  High version count for child cursors referencing a remote object due to AUTH_CHECK_MISMATCH

這一類語句其實從應用的層面都比較好改寫,改寫的思路如下:

  1. 對於insert into 或者select into可以考慮不要使用綁定變量。
  2. 對於一個字段很多的表,在insert的時候不要把所有字段都列出來
  3. 儘量不要使用insert into這樣生僻的寫法
  4. 對於inlist 應該控制其內部綁定變量的個數,如果無法控制,則可以將這些變量存入到一張臨時表中,去掉inlist,要用的時候再從臨時表獲取。
  5. 儘量不要寫特別長的SQL語句,這種SQL不僅易讀性差難於維護,並且很容易導致shared pool的一些爭用。
  6. 儘量避免在dblink調用的SQL語句中使用綁定變量。

在配置方面, cursor_sharing和Adaptive cursor sharing的設置不當容易導致high version count的問題。

請不要使用cursor_sharing=similar ,這句話再怎麼強調都不過分。

ANNOUNCEMENT: Deprecating the cursor_sharing = ‘SIMILAR’ setting (Doc ID 1169017.1)  

在10gR2以上版本,cursor_sharing設置爲similar可能會導致各種各樣的bug,其中之一就是可能會導致出現大量的不可共享的child cursor,從而引發出high version count的問題。

Oracle在12c已經不支持cursor_sharing=similar, 在11.2.0.3版本,cursor_sharing設置爲similar與設置爲force的效果相同。

另外cursor_sharing最好設置爲exact,在沒有經過充分的測試下,不要將其設置爲force。因爲設置爲force同樣有一定的機率可能導致high version count。

參見: High Version Count with CURSOR_SHARING = SIMILAR or FORCE (Doc ID 261020.1)

如果SQL 語句的共享性很差,首先要做的應該是對SQL 進行調整,而不是調整cursor_sharing 參數。

在11g中引入的adaptive cursor sharing(ACS)特性。在沒有經過充分測試之前,請關閉此特性,這個特性很容易導致high version count的問題。

Bug 12334286  High version counts with CURSOR_SHARING=FORCE (BIND_MISMATCH and INCOMP_LTRL_MISMATCH)

Bug 7213010 – Adaptive cursor sharing generates lots of child cursors

Bug 8491399 – Adaptive Cursor Sharing does not match the correct cursor version for queries using CHAR datatype

常見的bug和workaround

在10gR2版本中存在一個臭名昭著並且隱匿得很深的Bug,它們曾經摺磨過無數DBA:

Patch 6795880: BATCH JOBS HANG WAITING ON ‘KKSFBC CHILD COMPLETION’

Bug 8575528  Missing entries in V$MUTEX_SLEEP.location

這兩個bug本質是同一個問題,只是因爲前一個問題修復不徹底,反而導致了後一個問題。它存在的缺陷在於如果high version count的SQL,那麼去查找child cursor的過程中效率會非常低,從而導致kksSearchChildList/ kqlfMutexClnFetch這些過程會導致掛起。數據庫的等待事件上表現爲大量的latch,mutex等待,典型的有latch: library cache lock, kksfbc child completion, cursor: mutex pin S, Latch: Row Cache Objects, library cache: mutex X。而這些等待事件基本都是平時難得一見的奇觀。

最終的結果往往有兩種:

  1. 數據庫一直掛起必須手工重啓;
  2. 數據庫掛起一段時間,然後恢復
  3. 系統資源耗竭導致宕機
  4. 觸發出其它的bug例如某ORA-600 [kkssearchchildlist*]或者ORA-07445[kkssearchchildlist*]導致數據庫宕機

這個問題號稱在10.2.0.5已經修復,但是這個問題在10.2.0.5版本上依然很常見。主要原因有兩點:

  1. 10.2.0.5雖然包含了修復這個問題的代碼,但是默認情況下是不生效的,需要用戶手工將”_cursor_features_enabled” = 10。
  2. 即使設置了”_cursor_features_enabled” = 10,依然還有遇到KKSFBC CHILD COMPLETION的概率,根本原因還是在於child cursor過多,這一系列的函數調用過程依然過於低效。

遺憾的是如果在10.2.0.5以上版本碰到這個問題,除了按照上文的要求調整SQL或者升級到11gR2以外,從數據庫現有的手段幾乎無解。

另外一個常見的問題是數據表義使用varchar類的變長字符串類型,而應用可能傳入的字符串長度爲個位數,也可能傳入的字符串長度爲四位數。換而言之,就是應用程序傳入變量的長度範圍過大,導致bind mismatch,最終child cursor不能共享從而重新進行hard parse,這樣的結果就導致child cursor的急劇膨脹。

根據

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. The previous one will be marked ‘dont use’. 

這個問題可以通過設置固定的字符串buffer的長度來減少其對應的version count。通過level爲4000的10503事件來達到此目的,注意這裏的4000爲字符串buffer的長度。在SQL中可變字符串varchar2最大的長度爲4000。

SQL>alter system set events '10503 trace name context forever, level 4000';

還有一個非常有殺傷力的Bug爲

Bug 8981059  High Version Count (due to USER_BIND_PEEK_MISMATCH) with bind peeking

這個Bug幾乎影響了所有的10gR2的版本。

這個bug典型的cursor dump信息如下:

KKSCS sharing succeed xsc=1106ac818 childno=3370 reason=BND

Checking for already pinned child. fbcflg 1

Object is invalid

No valid child pinned

Parent 70000065e35bb50(70000065f702598) ready for search

kksSearchChildList outside while loop

kksCheckCursor: next child is #3370

kksCheckCursor: pinning child #3370 in shared mode 70000065e35b960

0000065f41e8f0

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=NFP

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=SQT

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=OPT

...

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=BDM

...

KSCS sharing failed xsc=1106ac818 childno=3370 reason=UBP

kksUnlockChild: releasing child

Failed sharing : 8000000

kksCheckCursor: next child is #3402

kksCheckCursor: pinning child #3402 in shared mode 70000065e35b960

0000065e615f88

KKSCS sharing succeed xsc=1106ac818 childno=3402 reason=NFP

KKSCS sharing succeed xsc=1106ac818 childno=3402 reason=SQT

在堆棧信息中還會找到kksfbc以及 kksLoadChild這樣的函數。

這個問題實際上是因爲綁定變量窺測導致的child cursor不能共享。並且在某些情況下可能導致查詢出來的結果是錯誤的,也就是我們所說的wrong result。

通常這一類問題在10.2.0.5以上版本可以通過關閉綁定變量窺測來規避:

SQL>alter system set "_optim_peek_user_binds"=false
  • 監控version count特別高的語句,如果到了特定的閾值,就將其從shared pool中踢出去,在10.2.0.4和10.2.0.5通過以下方式清除特定的SQL:
SQL>alter session set events '5614566 trace name context forever';

SQL>exec dbms_shared_pool.purge('&address, &hash_value', c);

前面event 5614566設置的目的是爲了規避Bug 5614566導致的使用dbms_shared_pool.purge 無法將parent cursor清除出shared pool的問題。

雖然Bug 5614566在10.2.0.5已經修復,但是在某些情況下,依然會遇到dbms_shared_pool.purge的情況。

  • 使用dbms_shared_pool.keep這個包將特定high version count的SQL進行keep。

此建議爲Bug 10157392  High version counts for SQL with binds (BIND_MISMATCH)給出的一個workaround,這種方法大多數情況都不起作用。

  • 定期的對shared pool進行flush。

在某些負載比較低的系統中,可以考慮使用這種方法來防治high version count的問題。在業務繁忙的系統中刷新shared pool存在很大的風險,以來大量被刷出去的SQL需要重新進行硬解析,有可能會導致CPU短時間內的迅速增加。還有就是某些SQL被刷出shared pool以後重新解析其執行計劃可能會發生變化,由此容易造成性能的不穩定。

11g的cursor特性的增強

在10gR2中,child cursor的最大上限爲32768。Child cursor的數量如果超過了32768,那麼這個session就會拋出ORA-600 [17059]的錯誤,然後這個session就會crash,在10.2.0.4和10.2.0.5上有一個增強補丁:Bug 8946311  Increase max children before reporting ORA-600 [17059]。如果應用了這個patch,那麼child cursor的上限就可以提高到65535了。

但是允許child cursor的上限到一個非常大的值並不是什麼好主意,只能暫時緩解因爲high version count而導致的ORA-00600的錯誤。但是同時也會引發新的問題,例如最典型的是因爲child cursor過多,導致了單個SQL語句佔用的shared pool的空間非常大,最終導致ORA-004031.

到了11g,Oracle已經充分意識到high version count是一個很嚴重的問題,儘管mismatch是客觀存在的,但是可以通過其它的一些手段限制child cursor的數量。

Enhancement Request Bug 10187168 : OBSOLETE PARENT CURSORS IF VERSION COUNT EXCEEDS A THRESHOLD   引入了一個隱含參數叫_cursor_obsolete_threshold,此參數用來限制單個parent cursor下child cursor的數量,默認值爲100。如果child cursor的數量超過了這個閾值就會cursor obsolescence的特性,也就是說這個時候parent cursor會被廢棄,並且同時重新創建一個新的parent cursor。 這樣雖然mismatch會繼續存在,但是一勞永逸的解決的high version count的問題。這個patch已經集成到11.2.0.3版本。如果低於11.2.0.3版本,除了需要應用這個patch,同時需要設置一下參數:

11.2.0.1:

SQL> alter system set "_cursor_features_enabled"=34 scope=spfile;

SQL> alter system set event='106001 trace name context forever,level 1024' scope=spfile;

11.2.0.2:

SQL> alter system set "_cursor_features_enabled"=1026 scope=spfile;

SQL> alter system set event='106001 trace name context forever,level 1024' scope=spfile;

小結

High version count由於產生原因紛繁多樣,並且產生的結果表現形式各不相同,再加上其複雜的診斷方法,往往令很多DBA都束手無策,這不能不說是早期產品設計上的一個缺陷。好在從11gR2開始,通過_cursor_obsolete_threshold這個特性,我們很快可以和high version count說再見了。但是探索的過程永遠比結果重要,我們收穫到的不僅僅是知識,而是一種鑽研的精神。

 

 

###############sample:

問題

數據庫版本是10.2.0.4 數據庫負載很低,5%左右,數據庫等待事件正常,

做了一些檢查,發現數據庫有一些SQL 有很多的SQL 有很多的versiou_count ,10.0.2.4 會有一些BUG 導致version count 過高。j進而導致 libaray change 問題 

1.檢查數據庫共享sql 情況,SQL 如下:


select sql_id,version_count,sql_text from v$sqlarea where version_count >200;

->1 8n5bcvc2mwjmj 237 insert into 

(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,:20,:21,:22,:23,:24,:25,:26,:27,:28,:29,:30,:31,:32,:33,:34,:35,:36,:37,:38,:39,: 
40,:41,:42,:43,:44,:45,:46,:47,:48,:49,:50,:51,:52,:53,:54,:55,:56)

 


2.檢查SQL的不能共享的原因,主要是bind_mismatch 不一致

select * from v$sql_shared_cursor where sql_id='8n5bcvc2mwjmj'

1 8n5bcvc2mwjmj C0000006C458E180 C0000006C68E5458 228 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
2 8n5bcvc2mwjmj C0000006C458E180 C000000555C98B70 229 N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
3 8n5bcvc2mwjmj C0000006C458E180 C0000006A8ABF2C0 230 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
4 8n5bcvc2mwjmj C0000006C458E180 C0000005C5787B08 231 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
5 8n5bcvc2mwjmj C0000006C458E180 C000000507BC45A8 232 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
6 8n5bcvc2mwjmj C0000006C458E180 C00000062728C9A8 233 N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
Y N N N N N
7 8n5bcvc2mwjmj C0000006C458E180 C0000006DED66D38 234 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
8 8n5bcvc2mwjmj C0000006C458E180 C000000627282A38 235 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N
9 8n5bcvc2mwjmj C0000006C458E180 C000000653E0BDD8 236 N N N N N N N N N
N N N N N Y N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N
N N N N N N


Y
代表bind_mismatch

 

 

###############################

建議如下:


建議1:

數據庫本身是10.2.0.4 的db ,這個版本存在很多未知的問題,強烈建議儘快升級數據庫11G。

 

建議2。如何修復BIND_MISMATCH 。可以看看是程序SQL 是否存在以下現象。並且進行調整。

現象1:定義的SQL的字段長度不一樣,如下

**BIND_MISMATCH

The bind metadata does not match the existing child cursor. For example, in the following, the definition of the bind variable 'a' has changed 
between the 2 statements:

variable a varchar2(100); 
select count(*) from emp where ename = :a ->> 1 PARENT, 1 CHILD

variable a varchar2(400); 
select count(*) from emp where ename = :a ->> 1 PARENT, 2 CHILDREN

 

現象2:

最容易導致出現version count的SQL包括以下類型:

Insert 語句使用綁定變量

Insert into table(column1, column2, column128, …) values (:1, :2, :3, … :128, …)

尤其是對於某些表字段類型特別多的,並且把這個表所有字段都寫到insert語句裏面的表現得尤爲明顯。


SQL 非常長並且裏面帶有多個綁定變量

如果一個SQL語句特別長,並且使用了綁定變量,那麼這樣的SQL更傾向於出現high version count。

 

 


解決方法:

這一類語句其實從應用的層面都比較好改寫,改寫的思路如下:

對於insert into 或者select into可以考慮不要使用綁定變量。
對於一個字段很多的表,在insert的時候不要把所有字段都列出來


這2種方案都需要經過在測試環境進行測試,才能在生產環境部署。

 

 

 

 

 

 

 

 

################Bug 7122093 : LIBRARY CACHE CHILD LATCH HELD FOR EXCESSIVE TIME IF SCAN X$KGLDP


dr: 7122093 10.2.0.3 RDBMS 10.2.0.3 LIB CACHE PRODID-5 PORTID-23
Abstract: LIBRARY CACHE CHILD LATCH HELD FOR EXCESSIVE TIME IF SCAN X$KGLDP

*** 05/23/08 01:57 pm ***
Logged out of bug 7116507 for clarity
The customer issue involves a third party monitoring tool.
The test here is simplified just to show the underlying problem.
========================= 
PROBLEM:
Under certain conditions a scan of the X$KGLDP fixed table
can cause very long latch hold times of a child library cache latch
causing an instance wide hang.
In particular if a cursor has a high version_count in V$SQLAREA
ie; has a lot of child cursors, and if it depends on a lot of
other objects.


####################
Bug 7122093 - 'latch: library cache' contention caused by queries on V$ views. (文檔 ID 7122093.8)


Description

Querying [G]V$ views based on X$KGLDP can hold library cache child latches for
too long potentially causing 'latch: library cache' contention.

 

 


###############################
Troubleshooting: High Version Count Issues (文檔 ID 296377.1)

**BIND_MISMATCH

The bind metadata does not match the existing child cursor. For example, in the following, the definition of the bind variable 'a' has changed 
between the 2 statements:

variable a varchar2(100); 
select count(*) from emp where ename = :a ->> 1 PARENT, 1 CHILD

variable a varchar2(400); 
select count(*) from emp where ename = :a ->> 1 PARENT, 2 CHILDREN

 

###ORACLE 10G

http://blog.csdn.net/notbaron/article/details/50927492

 

在10gR2以上版本,cursor_sharing設置爲similar可能會導致各種各樣的bug,其中之一就是可能會導致出現大量的不可共享的child cursor,從而引發出high version 
count的問題。

Oracle在12c已經不支持cursor_sharing=similar, 在11.2.0.3版本,cursor_sharing設置爲similar與設置爲force的效果相同。

另外cursor_sharing最好設置爲exact,在沒有經過充分的測試下,不要將其設置爲force。因爲設置爲force同樣有一定的機率可能導致high version count。

參見: High Version Count with CURSOR_SHARING = SIMILAR or FORCE (Doc ID 261020.1)

如果SQL 語句的共享性很差,首先要做的應該是對SQL 進行調整,而不是調整cursor_sharing 參數。

在11g中引入的adaptive cursor sharing(ACS)特性。在沒有經過充分測試之前,請關閉此特性,這個特性很容易導致high version count的問題。

Bug 12334286 High version counts with CURSOR_SHARING=FORCE (BIND_MISMATCH and INCOMP_LTRL_MISMATCH)

Bug 7213010 – Adaptive cursor sharing generates lots of child cursors

Bug 8491399 – Adaptive Cursor Sharing does not match the correct cursor version for queries using CHAR datatype

常見的bug和workaround

在10gR2版本中存在一個臭名昭著並且隱匿得很深的Bug,它們曾經摺磨過無數DBA:

Patch 6795880: BATCH JOBS HANG WAITING ON ‘KKSFBC CHILD COMPLETION’

Bug 8575528 Missing entries in V$MUTEX_SLEEP.location

這兩個bug本質是同一個問題,只是因爲前一個問題修復不徹底,反而導致了後一個問題。它存在的缺陷在於如果high version count的SQL,那麼去查找child cursor的 
過程中效率會非常低,從而導致kksSearchChildList/ kqlfMutexClnFetch這些過程會導致掛起。數據庫的等待事件上表現爲大量的latch,mutex等待,典型的有latch: 
library cache lock, kksfbc child completion, cursor: mutex pin S, Latch: Row Cache Objects, library cache: mutex X。而這些等待事件基本都是平時難得一 
見的奇觀。

最終的結果往往有兩種:

數據庫一直掛起必須手工重啓;
數據庫掛起一段時間,然後恢復
系統資源耗竭導致宕機
觸發出其它的bug例如某ORA-600 [kkssearchchildlist*]或者ORA-07445[kkssearchchildlist*]導致數據庫宕機
這個問題號稱在10.2.0.5已經修復,但是這個問題在10.2.0.5版本上依然很常見。主要原因有兩點:

10.2.0.5雖然包含了修復這個問題的代碼,但是默認情況下是不生效的,需要用戶手工將”_cursor_features_enabled” = 10。
即使設置了”_cursor_features_enabled” = 10,依然還有遇到KKSFBC CHILD COMPLETION的概率,根本原因還是在於child cursor過多,這一系列的函數調用過程依然 
過於低效。
遺憾的是如果在10.2.0.5以上版本碰到這個問題,除了按照上文的要求調整SQL或者升級到11gR2以外,從數據庫現有的手段幾乎無解。

另外一個常見的問題是數據表義使用varchar類的變長字符串類型,而應用可能傳入的字符串長度爲個位數,也可能傳入的字符串長度爲四位數。換而言之,就是應用程序 
傳入變量的長度範圍過大,導致bind mismatch,最終child cursor不能共享從而重新進行hard parse,這樣的結果就導致child cursor的急劇膨脹。

根據

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. The previous one will be marked ‘dont use’.

這個問題可以通過設置固定的字符串buffer的長度來減少其對應的version count。通過level爲4000的10503事件來達到此目的,注意這裏的4000爲字符串buffer的長度。 
在SQL中可變字符串varchar2最大的長度爲4000。

SQL>alter system set events '10503 trace name context forever, level 4000';
還有一個非常有殺傷力的Bug爲

Bug 8981059 High Version Count (due to USER_BIND_PEEK_MISMATCH) with bind peeking

這個Bug幾乎影響了所有的10gR2的版本。

這個bug典型的cursor dump信息如下:

KKSCS sharing succeed xsc=1106ac818 childno=3370 reason=BND

Checking for already pinned child. fbcflg 1

Object is invalid

No valid child pinned

Parent 70000065e35bb50(70000065f702598) ready for search

kksSearchChildList outside while loop

kksCheckCursor: next child is #3370

kksCheckCursor: pinning child #3370 in shared mode 70000065e35b960

0000065f41e8f0

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=NFP

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=SQT

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=OPT

...

KSCS sharing succeed xsc=1106ac818 childno=3370 reason=BDM

...

KSCS sharing failed xsc=1106ac818 childno=3370 reason=UBP

kksUnlockChild: releasing child

Failed sharing : 8000000

kksCheckCursor: next child is #3402

kksCheckCursor: pinning child #3402 in shared mode 70000065e35b960

0000065e615f88

KKSCS sharing succeed xsc=1106ac818 childno=3402 reason=NFP

KKSCS sharing succeed xsc=1106ac818 childno=3402 reason=SQT
在堆棧信息中還會找到kksfbc以及 kksLoadChild這樣的函數。

這個問題實際上是因爲綁定變量窺測導致的child cursor不能共享。並且在某些情況下可能導致查詢出來的結果是錯誤的,也就是我們所說的wrong result。

通常這一類問題在10.2.0.5以上版本可以通過關閉綁定變量窺測來規避:

SQL>alter system set "_optim_peek_user_binds"=false
監控version count特別高的語句,如果到了特定的閾值,就將其從shared pool中踢出去,在10.2.0.4和10.2.0.5通過以下方式清除特定的SQL:
SQL>alter session set events '5614566 trace name context forever';

SQL>exec dbms_shared_pool.purge('&address, &hash_value', c);
前面event 5614566設置的目的是爲了規避Bug 5614566導致的使用dbms_shared_pool.purge 無法將parent cursor清除出shared pool的問題。

雖然Bug 5614566在10.2.0.5已經修復,但是在某些情況下,依然會遇到dbms_shared_pool.purge的情況。

使用dbms_shared_pool.keep這個包將特定high version count的SQL進行keep。
此建議爲Bug 10157392 High version counts for SQL with binds (BIND_MISMATCH)給出的一個workaround,這種方法大多數情況都不起作用。

定期的對shared pool進行flush。
在某些負載比較低的系統中,可以考慮使用這種方法來防治high version count的問題。在業務繁忙的系統中刷新shared pool存在很大的風險,以來大量被刷出去的SQL 
需要重新進行硬解析,有可能會導致CPU短時間內的迅速增加。還有就是某些SQL被刷出shared pool以後重新解析其執行計劃可能會發生變化,由此容易造成性能的不穩定 

 

 

 

#############sample 2


select distinct(bind_equiv_failure) from v$sql_shared_cursor where sql_id='6t2grcwkfpjnt'

select * from v$sql_shared_cursor where sql_id='6t2grcwkfpjnt'

 

SELECT sql_id,count(*) FROM v$sql_bind_capture group by sql_id having count(*) > 100

select sql_id,count(*) from v$sql group by sql_id having count(*) > 100

 

 

workaroud:

Disable Extended Cursor Sharing (ECS) and Adaptive Cursor Sharing (ACS) by setting:

alter system set "_optimizer_extended_cursor_sharing"=none scope=both;
alter system set "_optimizer_extended_cursor_sharing_rel"=none scope=both;
alter system set "_optimizer_adaptive_cursor_sharing"= false scope=both;

and restarting the instance afterwards. This is the workaround for bugs 15881004, 14033503 and 14772891. There is no performance impact.

 

 

 

Bug 7330694 : TOO MANY VERSION OF THE QUERIES, CAUSING SHARED_POOL CONTENTION

ALTER System SET EVENTS '10503 trace name context forever, level 4000';

 

 Extract the Values of Bind Variables used by all the SQL Cursors in a Stored Procedure from the Data Dictionary (文檔 ID 1351206.1)

 

 

 ####sample 3


##監控SQL區使用量超過5G的shared_pool 的數據庫
select * from V$SGASTAT where pool='shared pool' and name='SQLA' AND bytes/1024/1024/1024 > 5


###監控硬解析高於5000的非綁定變量的SQL
select FORCE_MATCHING_SIGNATURE, count(1)
from v$sql
where FORCE_MATCHING_SIGNATURE > 0
and FORCE_MATCHING_SIGNATURE != EXACT_MATCHING_SIGNATURE
group by FORCE_MATCHING_SIGNATURE
having count(1) > 5000
order by 2;


### 如果監控出現SQL 該如何查出SQL具體內容

shared pool現有內存24G,還是產生大量硬解析,那就是說明不是因shared pool size設置不當所致,那就是非常有可能是由於程序代碼所致。
5. 調研分析是那些代碼導致hard parse,從awr的sql order by executions上看,最有可能是以下語句造成的:


step 1. 進一步確認,找出硬解析最多的SQL語句如下:
select to_char(force_matching_signature),count(*) hard_parses
from v$sqlarea
group by to_char(force_matching_signature)
having count(*)>5
order by 2 desc;

step 2:
select * from v$sqlarea
where force_matching_signature=7756258419218828704;


step 3:
整合step1/step 2後:
select b.*,a.* from v$sqlarea a,(
select force_matching_signature,count(*) hard_parses
from v$sqlarea
group by force_matching_signature
having count(*)>5) b
where A.FORCE_MATCHING_SIGNATURE=b.force_matching_signature
and b.force_matching_signature >0
order by 2 desc;

 

step 4:  重新整合step 1/step 2

 

DECLARE
T VARCHAR2(50);
v_signature VARCHAR2(50);
v_no NUMBER(5);
v_sqltext VARCHAR2(2500);
cursor STSCUR is select force_matching_signature,count(*) from v$sqlarea group by force_matching_signature having count(*)>1000;
STSCUR_1 v$sqlarea%ROWTYPE; 
BEGIN
--for ORA-20000: ORU-10027: buffer overflow, limit of 2000 bytes
DBMS_OUTPUT.ENABLE (buffer_size=>null);
OPEN STSCUR;
LOOP 
fetch STSCUR into v_signature,v_no;
EXIT WHEN STSCUR%NOTFOUND; 
-- DBMS_OUTPUT.PUT_LINE(T);
--commit;
-- DBMS_OUTPUT.PUT_LINE(STSCUR_1.SQL_ID);
select sql_text into v_sqltext from v$sqlarea where force_matching_signature=v_signature and rownum < 2;
DBMS_OUTPUT.PUT_LINE(v_signature||','||v_no||','||v_sqltext);
--換行
dbms_output.new_line;
END LOOP; 
CLOSE STSCUR; 
END;

 

判斷硬解析的重要指標force_matching_signature,當該指標具有相同值時,就是說明採用同一語句,只是條件值不同,在cursor_sharing=force的情況下是可以共享同一計劃,在exact下不能,必須顯式使用綁定變量方式。
舊辦法:

 

col sqltext format a50
select dbms_lob.substr(sql_text,20,1 ) sqltext,count(*)
from dba_hist_sqltext
group by dbms_lob.substr(sql_text,20,1 )
having count(*)>=2
order by 2;
7. 找出問題語句,改造爲綁定變量方式。
解決方法:
1. 找出問題的語句,改爲綁定變量的方式:
2. 綁定變量的使用如下:
plsql:
execute immediate "select * from t1 where col1=:1" using v_col1;
Java方式:
String v_id = 'xxxxx';
String v_sql = 'select name from table_a where id = ? '; //嵌入綁定變量
stmt = con.prepareStatement( v_sql );
stmt.setString(1, v_id ); //爲綁定變量賦值
stmt.executeQuery();

補充備註與shared pool使用相關的系統表:
select * From SYS.V_$SHARED_SERVER_MONITOR;

select * from SYS.V_$SHARED_POOL_RESERVED;

select * from SYS.V_$LIBRARYCACHE;

select * from SYS.V_$LIBRARY_CACHE_MEMORY;

select * from SYS.V_$SGASTAT where pool='shared pool'
order by 3 desc;

 

##############

將指定SQL_ID 的執行計劃 flush出shared pool

2015年04月08日 09:22:26 Pdata 閱讀數:470 標籤: flush執行計劃shared更多

個人分類: ORACLE

 

在調試某特定SQL時,爲避免緩存帶來的影響,常常需要先將原來 的緩存清空而需要使用下面命令:

SQL>ALTER SYSTEM FLUSH SHARED_POOL;
  • 1

但是在生產系統中,使用上面命令對系統整體會有一個較大影響,如何將特定的SQL刷出緩存?

SQL>SELECT address,
           hash_value,
           executions,
           parse_calls
    FROM   v$sql
    WHERE  sql_id='0g9au25ax7mx8';

SQL>exec dbms_shared_pool.purge('0000001053A9EF20,1439944616','C');

######ref 

https://blog.csdn.net/tuning_optmization/article/details/46695257

oracle11g中SQL優化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)

 

1.   ACS簡介

Oracle Database 11g提供了Adaptive Cursor Sharing (ACS)功能,以克服以往不該共享的遊標被共享的可能性。ACS使用兩個新指標:sensitivity and bindawareness來實施該特點。

2.   ACS機制

2.1.  Adaptive Cursor Sharing Metadata:Oracle 11g也提供了三個新視圖和動態視圖V$SQL的兩個新列來允許DBA來確定優化器是否已經確定一個SQL語句爲一個ACS的候選,並且,也可以通過它們來觀察優化器分類SQL語句用以共享的執行計劃所使用的業務規則:

視圖

描述

V$SQL

Two new columns are added:

  • IS_BIND_SENSITIVE indicates if a SQL statement is bind-sensitive. If this column contains a value of (Y)es, it means that the optimizer peeked at the values of the statement’s bind variables so that it can calculate each predicate’s selectivity.
  • Likewise, IS_BIND_AWARE indicates if the optimizer has also decided that the statement’s cursor is bind-aware after additional execution of the statement.

V$SQL_CS_HISTOGRAM

Distributes the frequency (within a three-bucket histogram) at which Oracle 11g used to decide if a SQL statement was bind-sensitive, including how many times a particular child cursor has been executed.

V$SQL_CS_SELECTIVITY

Contains information about the relative selectivity of a SQL statement’s predicates, including the predicates themselves, and their high and low value ranges. These values are also termed the cursor’s selectivity cube.

V$SQL_CS_STATISTICS

Lists the statistics of whether and/or how often an Adaptive Cursor has been shared. The PEEKED column will display a value of Y(es) if the bind set had been used to build the Adaptive Cursor.

表-1 ACS 視圖

2.2.  Bind Sensitivity:當帶有綁定變量的SQL語句首次被解析時,在優化器窺探了綁定變量的值,並確定了語句謂詞的相關選擇率後,把該遊標標記爲 bind-sensitive(綁定敏感的)。期間也保留了這些敏感測量值,以便今後帶有同樣變量、不同值的同樣語句再次執行時進行比較,看一個已經存在的執行計劃是否能被新綁定變量值的語句利用。

2.3.  Bind Awareness:一旦一個SQL語句的遊標被標爲 bind-sensitive,優化器也可以確定遊標是bind-aware。通過檢查隨後執行的同樣SQL語句綁定變量的值和所有匹配計劃已被捕獲的綁定變量的值,優化器完成這個步驟。如果優化器確定該語句能利用已存在的計劃,那麼,只需要更新遊標執行柱狀圖來反應語句的執行即可。另外,如果綁定變量值足夠不同,優化器也許決定創建一個新的子游標和執行計劃。一旦這些發生,Oracle11g也把子游標的相關選擇率存儲到ACS元數據中。在遊標隨後的執行過程中,優化器比較存在的統計選擇性數據和遊標最近執行的統計數據,如果觀察到大多數執行使用近似同樣的選擇性範圍,那麼,遊標將會被標記爲bind-aware。

當查詢以一套超出一個已存在的bind-aware的遊標綁定變量的選擇率範圍界限的不同的綁定變量值被執行時會發生什麼呢?在該語句的硬解析期間,優化器也許僅僅決定擴展那個遊標的選擇率範圍來包含新的變量值,通過產生一個合併兩套綁定變量值的新游來做到這點。可見在必要的時候,也僅僅是增加了新遊標。Oracle11g中,ACS特點默認被開啓,且完全獨立於CURSOR_SHARING參數。

2.4.  對SQLPlan Management (SPM)影響:最後,如果你瞭解古Oracle11g的SPM特點,你可能想知道ACS和SPM是否會相互影響,下面做一些簡短的總結:

如果初始化參數OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES已被設置爲TRUE來開啓自動計劃捕獲,那麼,帶綁定變量的一個SQL語句將被標作對應的能用和可接受的執行計劃。

如果同樣語句的第二個執行計劃被創建——對ACS特點來說這並不新鮮——那麼,計劃僅僅被增加到語句的計劃歷史裏,但並能被立刻使用,因爲SPM要求新執行計劃首先被驗證爲一個較好的計劃。

不幸的是,這意味着一個好的計劃也許被忽視掉,哪怕是其遊標的選擇性範圍可能會導致一個較好的性能。繞過該問題的一個很好的辦法是保持自動計劃捕獲爲默認設置False,接着把所有library cahce裏的子游標都捕獲到SMB裏去。這將會迫使ACS產生的遊標的所有計劃都被標爲SQL PLAN BASELINES。

3.   限制

Oracle11gR2爲止,ACS特性存在以下限制(當以下場景出現時,會導致ACS不會把遊標標記爲bind sensitive):

Ø  擴展遊標共享被關閉;

Ø  查詢中沒綁定變量;

Ø  某些參數被設置(例如:綁定變量窺探被置爲flase);

Ø  語句正使用並行查詢時;

Ø  語句使用了hints;

Ø  Outlines正被使用;

Ø  查詢爲遞歸查詢;

Ø  綁定變量數超過14;

4.   關閉及開啓

Ø  ACS默認情況下是開啓的,爲了關閉ACS,我們需要修改以下三個參數:

alter system set"_optimizer_extended_cursor_sharing_rel"=none;

 altersystem set "_optimizer_extended_cursor_sharing"=none;

 altersystem set "_optimizer_adaptive_cursor_sharing"=false;

Ø  爲了開啓ACS,我們需要修改以下四個參數:

_optim_peek_user_binds=true(一定要開啓綁定變量窺視)_optimizer_adaptive_cursor_sharing=TRUE(以下三個參數默認開啓ACS)_optimizer_extended_cursor_sharing=UDO

_optimizer_extended_cursor_sharing_rel=SIMPLE

5.   注意:

Ø  相關hint:Oracle11g中有個新的 hint,當使用此hint時,即使把ACS特性關掉,ACS特性在語句級依然會生效,該hint的語法爲:/*+ BIND_AWARE*/;

Ø  關於Outlines:在Outlines存在的場景下,無論在系統級啓用還是語句級通過hint啓用,ACS都會失效;

6.   結論:

Oracle Database 11g的新特點ACS功能爲帶綁定變量的SQL語句執行計劃高效共享提供了一個簡單的方法。由於只有當綁定變量值選擇率必要時,ACS也會產生一個新的執行計劃,因此,共享遊標的數目會保持最小。

 

--------------------- 本文來自 lhdz_bj 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/tuning_optmization/article/details/46695257?utm_source=copy 

 

######ref 2  cat bind sql value

To see a colleague wrote a SQL bound variables are interesting, again to reprint:

--Find the last word values in SQL_ID
select * from v$sql where sql_id='0z25ncfbunafk'
--Bind variable transformation corresponding value
SELECT position,value_string
FROM TABLE(DBMS_SQLTUNE.EXTRACT_BINDS('BEDA0A20050052366ECE000307F0012003540CB9E2CFCBBDD3C8EBBACFCDACF0021604C32C6256F0012003540CB9E2CFCBBDD3C8EBBACFCDAC'));
--If there is no v$sql, can obtain the bind variable values by this method
select dbms_sqltune.extract_bind(bind_data, 1).value_string || '-' ||
dbms_sqltune.extract_bind(bind_data, 2).value_string || '-' ||
dbms_sqltune.extract_bind(bind_data, 3).value_string || '-' ||
dbms_sqltune.extract_bind(bind_data, 4).value_string || '-' ||
dbms_sqltune.extract_bind(bind_data, 5).value_string || '-' ||
dbms_sqltune.extract_bind(bind_data, 6).value_string
from sys.wrh$_sqlstat
where sql_id = '0z25ncfbunafk'
--To view the corresponding SQL 
SELECT * FROM SYS.WRH$_SQLSTAT WHERE SQL_ID='0z25ncfbunafk';
SELECT * FROM SYS.WRH$_SQL_BIND_METADATA WHERE SQL_ID='0z25ncfbunafk';
select t.sql_id,t.name,t.position,t.datatype_string,t.value_string,t.last_captured from v$sql_bind_capture t where sql_id='f78cpkf8cc003';

 

###no data in sql_bind:

he value for the bind :B that is included in the select list will not be populated in V$SQL_BIND_CAPTURE:

Bind in Select

For Example:

 
SQL> var A number
SQL> var B varchar2(32)
SQL> exec :A := 7902;

PL/SQL procedure successfully completed.

SQL> exec :B := 'Emp No.';

PL/SQL procedure successfully completed.

SQL> select :B, empno from emp where empno=:A;

:B                                    EMPNO
-------------------------------- ----------
Emp No.                                7902

SQL> SELECT NAME,POSITION,DATATYPE_STRING,VALUE_STRING FROM gv$sql_bind_capture WHERE sql_id='0mutxd0a9c3r7';

NAME      POSITION      DATATYPE_STRING      VALUE_STRING
-----     --------      ---------------      ------------
:B        1             VARCHAR2(32)
:A        2             NUMBER               7902

CAUSE

This is expected behavior. Binds that are part of the SELECT list are not populated in V$SQL_BIND_CAPTURE since these values are not used by the optimizer when deciding on the execution plan (bind peeking) .

SOLUTION

 There is no solution since this behavior is expected.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章