最近一套12C庫出現大量cursor:mutex X異常等待的故障,借此機會在這里和大家分享下分析過程及后續處理。先簡單介紹下故障過程,一天數據庫突然等待事件異常告警,登上數據庫查看異常等待事件發現大量cursor:mutex X,基于優先恢復業務的原則,將其kill之后數據庫恢復正常。后續開始對故障進行分析及進行后續處理,欲知詳情,請聽下面分解。
1、查看故障時段AWR:
發現cursor:mutex X異常等待事件占了54%的DBTIME
2、cursor:mutexx等待事件原理:
cursor正在被解析并嘗試以獨占(exclusive)模式獲取cursormutex時產生的等待即為cursor:mutexx。
引起問題的原因包括頻繁硬解析、highversioncount、cursor失效及未知BUG等。但本質上是一些會話長時間持有互斥鎖,以至于其他會話不得不等待資源。如果在保護庫緩存結構的latches/mutexes上發生爭用,這意味著解析面臨壓力。解析SQL需要更長的時間,因為它無法獲得所需的資源。這會延遲其他操作,并且通常會降低系統的速度。
查看問題剛出現時的歷史會話(DBA_HIST_ACTIVE_SESS_HISTORY)如下:
從上圖我們可以看到多個會話同時執行SQL_ID:3t5xt2hkrchpy,a9xqubd880h5n,且堵塞源不停在變,會話相互之間發生cursor:mutex X等待。
3、查看故障時段的AWR:
從以上圖我們可以看到SQL_ID:3t5xt2hkrchpy執行時間及CPU消耗TOP1,其SQL及其他SQL的版本數都很高。
4、查看故障時段做的hang分析日志如下:
通過hang分析日志我們可以看到Blcoking其他session的會話操作是查找子Currsor,所以故障大概率是由于子Cursor過多,進行查找時發生等待導致。而產生大量的子Cursor的原因是NLSSettings。
普及下什么是versioncount?
一個SQL第一次執行時,會進行硬解析,同時創建parentcursor和childcursor。
當這個SQL時再次執行時,首先會對SQL語句進行特殊的hash運算,對應生成一個hashvalue。Hashvalue存放在parentcursor中,然后會用這個hashvalue到paranetcursor的bucket中匹配,如果相同的hashvalue 已存在parentcursor里,則繼續遍歷這個childcursor,如果可重用,那么就沿用childcursor的信息,如果不能重用,就會重新生成一個新的childcursor。一個parentcursor下childcursor的總數,就是這個SQL的versioncount。
highversion count指的就是childcursor總數很高。在AWR報告中,默認verioncount超過20的SQL就會顯示在orderby version count中。根據經驗versioncount如果超過100,可能就需要引起注意了。
5、綜上所述,我們發現本次故障大概率是由于highversion count導致,那為啥這么多SQL的versioncount都這么高呢,初步懷疑是觸發BUG了,我們這庫是CDB模式,并且多個PDB的字符集不一致,通過MOS查找到一篇類似的文章:
通過SR確認有可能觸發BUG25054064,該BUG在2020年1月份的DBRU中fixed了,我們只需要打上
Patch31741641: DATABASE OCT 2020 RELEASEUPDATE12.2.0.1.201020即可,因為DBRU都是累積的。
查看其readme提供的BUG修復的連接發現BUG25054064已在補丁集中。
6、打完補丁之后截止目前為止再沒出現過類似的故障,我們查看SQL的versioncount發現降低了一個數量級。
另外由于字符集不匹配導致的highversion count在DocID 2542447.1也詳細介紹了處理方法,用于緩解子Cursor過多查找緩慢導致的等待:
1)通過具體SQL_ID將其從sharedpool清除掉。
SQL>select address,hash_value,version_count from v$sqlarea wheresql_id=a9x5sbz88kmfh;
ADDRESSHASH_VALUE VERSION_COUNT
---------------- -----------------------
000000006BFFAC00 3498659280 2
SQL>exec dbms_shared_pool.purge(,C);
Ex:
SQL>exec dbms_shared_pool.purge(000000006BFFAC00,3498659280,C);
PL/SQLprocedure successfully completed.
2)將_cursor_obsolete_threshold參數設置為較低的值減少子Cursor數量,不過這個取決于應用程序需求,_cursor_obsolete_threshold的默認值是8192,可以將其設置為2048或1024,重啟生效。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/130070.html
摘要:什么時候會出現線程不安全操作并非原子。只有單個組件,且它是線程安全的。這種情況下,就是的線程安全實際是委托給了整個表現出了線程安全。 當多個線程去訪問某個類時,如果類會表現出我們預期出現的行為,那么可以稱這個類是線程安全的。 什么時候會出現線程不安全? 操作并非原子。多個線程執行某段代碼,如果這段代碼產生的結果受不同線程之間的執行時序影響,而產生非預期的結果,即發生了競態條件,就會...
閱讀 1346·2023-01-11 13:20
閱讀 1684·2023-01-11 13:20
閱讀 1132·2023-01-11 13:20
閱讀 1858·2023-01-11 13:20
閱讀 4100·2023-01-11 13:20
閱讀 2704·2023-01-11 13:20
閱讀 1385·2023-01-11 13:20
閱讀 3597·2023-01-11 13:20