1. 程式人生 > >Systemstate Dump分析經典案例(下)

Systemstate Dump分析經典案例(下)

oracle 數據庫

前言


接上一期:(上一期的閱讀方法:關註“中亦安圖”公眾號後回復‘007’)


4.3.4

SSD中library cache lock的分析


接上一期:

分析到這步,前邊看似毫無頭緒的問題似乎理清了,大量cursor:pin S wait on X已經理清楚,所有的矛頭走指向了sid 859


離真相只差一步了,我們只需要分析library cache lock的源頭就能解釋整個謎團了,前面老K已經提到了分析library cache lock等待事件的方法了,現在我們就來結合trace文件看看如何定位library cache lock的阻塞關系。


那好,我們就來看sid 859:


技術分享

這個會話信息中我們能看到:

>> 會話在等待library cache lock等待事件,等待時間4429秒

>> 會話以S模式請求句柄為700000209bb9d80的library cache對象(request=S)

>> 句柄為700000209bb9d80的library cache對象是SYS.C_OBJ#_INTCOL#,是一個cluster(簇聚)對象。


我們就看到,會話859正在以S模式請求700000209bb9d80上的library cache lock而產生了等待,那麽我們就可以確認系統中一定有另一個會話以X模式持有了700000209bb9d80上的library cache lock;同樣,我們在trace文件中搜索關鍵字”700000209bb9d80”再過濾後能看到下面的條目:

技術分享


我們定位到該條信息後,再確認該條信息所屬的會話,確認其會話信息如下:


技術分享


看到這裏,大家有沒有柳暗花明的感覺呢,我們看到持有700000209bb9d80上library cache lock的會話是624,而會話624正在等待”cursor:pin S wait on X”事件,等待的對象正是bbcee4f7;現在我們再來完善上面的等待鏈圖:

技術分享


到最後,我們發現在會話859和會話624之間,形成了死鎖,具體的情況就是:

>> 會話859持有bbcee4f7上的mutex,請求700000209bb9d80上的library cache lock

>> 會話624持有700000209bb9d80上的library cache lock,請求bbcee4f7上的mutex

>> 其他會話產生大量的cursor:pin S wait on X等待事件,都是由於859長時間持有bbcee4f7上的mutex未釋放導致的


到了這一步,是不是一切謎團都解開了?我們的分析是不是就完成了呢?

答案是:NO


Part 5

根因分析

5.1 第三次頭腦風暴


經常做根因分析的老K此時還有疑惑:

>> 如果當時不重啟,而kill掉死鎖鏈上的會話,問題是否會解決?

>> 會話859和會話624都在做什麽,為什麽會死鎖?

>> 單個會話持有一個cursor的mutex,怎麽會讓系統處於夯住的狀態?


5.2 柳暗花明之會話859


現在老K重點關註的就是如何解開上面的兩個疑惑了,繼續分析trace。

先看會話859,截取trace文件中的信息,如下:

技術分享

從標黃處的信息我們知道,這是一個數據庫的後臺進程;我們可以通過查看trace中這個會話所屬的進程信息如下:

技術分享

先回答第二個問題:會話859在做什麽?

後臺進程是CJQ0,這個進程是ORACLE用來調度job的;我們知道,如果某個會話以S模式請求某個對象上的library cache lock,這個會話通常是在解析某個語句或者編譯某個package時需要從library cache中查找該語句涉及對象的信息;在PROCESS 24的trace文件中查找“oper EXCL”關鍵字,我們查到以下三條記錄


在PROCESS 24的trace文件中查找“oper EXCL”關鍵字,我們查到以下三條記錄

Mutex 7000001e7d04898(859, 0) idn bbcee4f7 oper EXCL

Mutex 7000001e5fbe4e0(859, 0) idn fb52493f oper EXCL

Mutex 7000001e8faa990(859, 0) idn a8bbc174 oper EXCL


可能有人會問?一個會話怎麽同時有三個cursor?

大家不要忘了ORACLE數據庫中有遞歸調用的說法,也就是說前端發起一條簡單的sql,ORACLE後臺實際上產生了一系列的遞歸調用,那些調用實際上也是一些sql的集合。通過idn值繼續查找,提煉一下,當前正在解析的三條sql語句分別是:

技術分享

這裏說明一下:其實,SSD中對sql的遞歸調用關系是不體現的,不過從上面的三條sql語句老K還是能推斷出其調用關系的;


CJQ0進程是用來調度oracle job的,從三條語句能大致的看到:a8bbc174是用來查詢系統中job相關信息的sql, fb52493f是通過對象號用來查詢某個對象的信息的sql,而bbcee4f7則是用來查詢直方圖信息的sql。


a8bbc174調用fb52493f,fb52493f調用bbcee4f7,如果這是bbcee4f7出問題,另外兩個肯定無法正常執行。這裏正是因為bbcee4f7無法完成解析,而導致其上層的fb52493f和a8bbc174阻塞;


新的疑點:三條SQL和C_OBJ#_INTCOL#有什麽內在聯系?


會話正在請求C_OBJ#_INTCOL#上的library cache lock而產生等待,而從這三條sql的文本來看,似乎都跟C_OBJ#_INTCOL#這個對象扯不上關系,這又怎麽解釋呢?有細心的讀者可能已經註意到了,前面老K特意指出了C_OBJ#_INTCOL#是一個cluster(簇聚)對象,cluster對象不是表,而是用來存儲多個表的共同列的,那這裏我們就可以註意最底層調用的sql中的histgrm$對象是否與C_OBJ#_INTCOL#有關,我們來看看histgm$的定義:

技術分享

又解開了一個謎題,histgrm$確實使用了C_OBJ#_INTCOL#這個cluster對象,所以在解析使用了histgrm$表的sql語句時,需要獲取C_OBJ#_INTCOL#上的library cache lock。


5.3 柳暗花明之會話624


接下來,再來看看會話624,像分析會話859一樣,把單個進程的trace摘出來,我們來截取部分信息如下:

技術分享

從這裏看,這是一個被調起的job進程,PROCESS號為42;

技術分享

這不是一個數據庫的後臺進程,所以,相比於之前看到的859進程,我們能看到更多的信息,我們大致知道,這個進程是數據庫調起的收集統計信息的job任務,在等待”cursor:pin S wait on X”事件,等待的解析對象是bbcee4f7;

因為它以X模式持有C_OBJ#_INTCOL#這個對象的library cache lock而阻塞了關鍵的會話859,那麽我們來看看它為什麽會持有這個library cache lock;我們到PROCESS 42的進程信息中搜索oper EXCL的關鍵字,搜索到兩條相關信息如下:

技術分享

同樣,我們也能從sql語句的語義上猜到兩者的遞歸調用關系;

技術分享

技術分享

會話624持有了C_OBJ#_INTCOL#和I_OBJ#_INTCOL#的library cache lock,其中I_OBJ#_INTCOL#是CLUSTER的索引。現在所有疑團都解開了。可以放松一下,從頭捋順思路了。


Part 6

情景再現


終於看到了全景,看看數據庫故障時刻在做什麽。


技術分享

在本場景中,t1時刻,數據庫自動收集統計信息任務調度J000進程收集整個數據庫統計信息,在收集cluster對象時,數據庫只能使用analyze的方式分析;


t2時刻,因為C_OBJ#_INTCOL#對象的統計信息被更新,因為histgrm$與C_OBJ#_INTCOL#的關聯關系,與histgrm$相關的sql(包括bbcee4f7)也就需要重新解析;


t3時刻,J000先收集C_OBJ#_INTCOL#統計信息,接著繼續使用analyze的方式收集其索引I_OBJ#_INTCOL#的統計信息;


t4時刻,這時CJQ0進程定時查詢系統JOB時,需要硬解析,遞歸調用bbcee4f7時對其進行解析;

解析的過程中需要以S模式請求持有histgrm$及其相關對象(也就包括C_OBJ#_INTCOL#及其索引I_OBJ#_INTCOL#)的library cache lock;


t4時刻,J000進程正在analyze索引I_OBJ#_INTCOL#,也就以X模式持有了I_OBJ#_INTCOL#上的library cache lock;


在J000使用analyze的過程中,同樣需要執行相關遞歸sql,需要進行硬解析,也就調用了上面說到的關鍵sql bbcee4f7;

所以最後造成了死鎖。


Part 7

問題定位


其實在上述分析的過程中,我們基本可以判斷為bug,(MOS):1628214.1 Database Appears to Hang with Deadlock Involving SYS.C_COBJ# or C_OBJ#_INTCOL# While Statistics Maintenance Job is Running


Part 8

寫在最後


到上面為止,我們已經定位bug,也獲得了事中和事後的解決方案,不過老K更關註的是大家是否能從這個CASE中獲得一些收獲,這裏不妨問問自己:

>> Systemstatedump中的cursor:pin S wait on X 我會查了嗎?

>> Systemstatedump中的library cache lock 我會查了嗎?

>> 如果我要模擬讓我的數據庫夯我會做嗎?

>> 還有一個沒有回答的問題?如果下次再遇到同樣的問題,我能通過殺掉死鎖鏈條裏的進程解決這個問題麽?


如果你的答案都是肯定的,那麽老K覺得這篇分享很有價值。

如果以上問題你還有疑問,可以通過微信或者QQ共同交流討論


Systemstate Dump分析經典案例(下)