天天看點

Oracle背景專家解決library cache鎖争用的終極武器

Oracle背景專家解決library cache鎖争用的終極武器

11月19日,雲汝網絡科技合夥人宋日傑(roger song)在“dba+東北群”進行了一場關于“使用hotcopy緩解 library cache: mutex x 的争用”的線上主題分享。小編特别整理出其中精華内容,供大家學習交流。

嘉賓簡介  

dba+原創專家團成員

超過13年it及oracle資料庫經驗

曆任中國聯通系統工程師、維布絡資訊科技oracle erp管理顧問

2008年加入oracle全球技術支援(gcs),專注性能分析

2012年協助建立oracle內建系統中國支援團隊(eest),任首席技術支援工程師

現任雲汝網絡科技(上海)有限公司合夥人,正在轉型網際網路解決方案

對oracle資料庫全線産品子產品有全面的深入了解,曾作為dsi講師為oracle國内原廠技術團隊提供教育訓練

擅長oracle原理,性能診斷,及複雜環境下的對問題的隔離與分析

演講實錄  

今天來給大家分享一個oracle使用中的小技巧。 當某條sql語句或者對象被反複通路,過多的軟解析可能會造成大量的“library cache:mutex x”争用,有什麼樣的方法處理此類問題呢?這是個頭疼的問題。 今天的話題,就是介紹如何利用hotcopy來緩解library cache中的熱點争用。在oracle 11g中,“library cache:mutex x”是個有點特殊的mutex,因為它存在于幾個不同的位置,需要進一步的資訊進行分辨。這裡還會簡單描述library cache的結構,了解library cache對認識oracle是非常重要的。

Oracle背景專家解決library cache鎖争用的終極武器

解決性能問題沒有特别的方法,主要靠對資料庫整體結構的準确了解。了解各種等待發生的原因,以及其在整個體系中的位置,才能做出正确的判斷。 是以我會先大緻介紹下10g和11g對library cache這個結構的保護方式。 這樣你就會了解這個問題發生的可能原因。 然後,我們來嘗試通過建立對象的hotcopy來緩解這類争用。

其中個别内容是我自己摸索和猜測出來的,難免有錯誤和不準确的地方,歡迎大家指正。

Oracle背景專家解決library cache鎖争用的終極武器

也許不是所有的同學都清楚library cache的結構,先在這裡簡單描述一下。

我們知道,當編譯過的sql已經存在于library cache中的時候,oracle會進行軟解析,重用這個結構。 那麼oracle如何知道是否已經存在可用的sql呢? 是通過如圖中的hash結構。所有已經編譯過的library cache object會被組織在一個hash結構中。 當進行搜尋時, oracle會對sql語句進行hash計算,根據結果找到相應的hash bucket,比如bucket 6, 然後再搜尋連結在這個bucket上的所有handle,這裡你可以認為每個handle對應唯一的sql文本。

一種情況,如果“handle x” 正好是要找的sql,則會向内搜尋“handle x”包含的child,尋找可用的cursor。 如果有完全符合條件的可用child,則重用,完成軟解析。 如果沒有,則建立一個新的child,完成一次硬解析。

另一種情況,如果沒有找到符合條件的handle,說明sql 文本是新的,則需要建立一個新的handle和第一個child。 同樣完成一次硬解析。

Oracle背景專家解決library cache鎖争用的終極武器

那麼為什麼要在這個結構上進行鎖保護呢?什麼操作需要加鎖?

一個很簡單的例子,如果沒有鎖的話,假設process 1和process 2同時執行同一個sql,當他們都沒有找到比對的handle時,有可能重複添加針對同一sql的handle y。

同樣的,當兩個程序同時搜尋handle x下是否有比對的child時,也有可能在此handle下,添加兩個相同的child。

是以,為了避免這種情況發生,對此結構的鎖是必要地。 由于這些操作都是快速的記憶體操作,此類鎖不宜采用複雜的結構,沒有共享模式和獨占模式之分。 是以,隻有一個程序可以對某個結構進行搜尋和修改。也就是說,即使是軟解析,在結構内進行搜尋時,也是串行的。

在10g和11g,library cache鎖的粒度是不同的。

Oracle背景專家解決library cache鎖争用的終極武器

10g的時候,保護這個結構的是 latch: library cache。 這個latch的預設數量為大于cpu count的最小質數,而預設最小的bucket個數為509,這就意味着每個latch要保護多個hash buckets以及相應的handle。 也就是說,對于一組bucket和handle,每次隻有一個程序可以搜尋修改。是以,這個latch經常成為熱點。

Oracle背景專家解決library cache鎖争用的終極武器

11g以後,此latch被替換為library cache: mutex x。鎖的粒度變小,每個bucket和每個handle都被一個單獨的mutex保護,大幅度減小了争用

然而,從latch名字本身,我們區分不出等待是發生在hash bucket上,還是handle上。需要通過p1來進行分辨。

Oracle背景專家解決library cache鎖争用的終極武器

如果p1是bucket的編号,通常比較小。 如果下面查詢傳回結果,說明争用發生在hash bucket上。 傳回結果為連結在此bucket上的對象。

select kglnahsh, substr(kglnaobj, 1, 30) name,

         kglhdnsp namespace, kglnahsv hash

from x$kglob where kglhdbid = &p1;

這種情況下,鎖是在bucket上,即對handle進行通路操作時發生的。

實際上,這種情況并不常見,因為每個bucket上連結到的handle通常不會很多。 為了提高hash表的效率,當bucket上平均handle數量超過2時,oracle會将bucket的個數翻倍,重建hash表,用空間交換時間。 在鍊不長的情況下,一般handle上會先遇到瓶頸。

Oracle背景專家解決library cache鎖争用的終極武器

更常見的争用位置,是在 handle上,這說明某個特定cursor或者object被搜尋時發生争用。

如果下面查詢傳回結果,則說明是這種等待。傳回結果為handle所對應的對象。 可能是cursor,也可能是object

    select kglnaown, kglnaobj

      from x$kglob

     where kglnahsh = &p1;

Oracle背景專家解決library cache鎖争用的終極武器

明白了大緻的原理之後,就可以想象到這個mutex争用的可能原因。

首先,它有可能是硬解析造成的。 當發生硬解析時,無論要建立一個新的handle,還是要建立一個新的child,都需要額外大量的時間來完成,相應地,對這個mutex的持有時間會明顯變長,造成争用。

由于硬解析會向shared pool申請大量的記憶體,是以這種情況會伴随一系列其他等待如 latch: shared pool, library cache load lock。 解決辦法就是分析硬解析過多,或者version count過高的問題。

還有一種情況,就是os資源不足,特别是cpu資源緊張。 這種情況下,oracle程序無法擷取足夠的資源去完成相應的工作,無法及時釋放此mutex,造成請求的堆積。

Oracle背景專家解決library cache鎖争用的終極武器

再有,就是某個持有者長時間不釋放此mutex,造成請求的積壓。這是不正常的, 需要對mutex持有者的目前狀态進行分析。 errorstack, process dump。 如果持有者被其他程序阻塞,則通過hanganalyze等工具繼續查找最終持有者。

另外,個别oracle bug也會造成此類問題。

如果,以上原因都被排除掉,那麼,對某熱點sql或熱點object的頻繁通路,也會造成此問題。 也就是我們之前說過的,哪怕是軟解析,也會在查找library cache結構的時候串行。 這類問題比較讓人頭疼,一方面,sql語句來自業務,我們不能人為減少sql的執行次數和效率。 另一方面,如果sql的文本相同,就一定會被hash到一個特定的handle上,這個是無法改變的。從前遇到這類問題非常讓人頭疼,一般可能的解決辦法見下一頁。

Oracle背景專家解決library cache鎖争用的終極武器

那麼接下來該怎麼辦呢?

首先,可以查下是否有連接配接風暴。 連接配接風暴可能造成某些plsql對象的頻繁執行,是造成此類問題的常見原因之一。

version count如果很高,也會引發這個問題,因為找到handle以後, 對child的搜尋是用周遊的方式,如果version很高child很多,則每次搜尋的時間很可能會變長。會造成對handle上的鎖,持有的時間也變長。是以,這也是一個可能的原因。

另外,和開發聯系,研究sql或某個對象如此高的并發是否正常的。 如果sql來自不同的子產品,則可以試着修改來自不同位置的sql文本(比如加空格,或無用注釋),使他們hash到不同的handle上。

增加session_cache_cursors是個可能的嘗試,如果cursor被cache住,child的位置會被儲存在pga中,那麼查找child的速度會明顯加快,對mutex的持有時間也會變小。

如果以上方法均不适用,我們最後可以嘗試建立hotcopy來改善此問題。

Oracle背景專家解決library cache鎖争用的終極武器

對于資源争用的問題,解決辦法隻有兩個,要麼減小需求,要麼增加資源數量。而hotcopy的原理,實際就是在hash sql文本的時候,加上pid的部分。 這樣,哪怕執行相同的sql文本,不同程序就有可能會被hash到不同的handle上。 這實際增加了資源的數量。當然,copy的數量是可控的。

制作了hotcopy以後,相同的對象和child可能多次出現在library cache的不同位置,造成了一部分空間浪費,但卻可以解決library cache中熱點對象或熱點cursor的争用。也是一種用空間換時間的辦法。

Oracle背景專家解決library cache鎖争用的終極武器

hotcopy這個功能是通過fix 9239863和fix 9282521引入的。 11.2.0.2以上版本可以直接使用。 低版本資料庫需要安裝相應地更新檔。 針對11.2之前版本的資料庫,需要設定兩個隐含參數。 slide裡有詳細的描述。針對cursor 和 object對應不同的方法。

Oracle背景專家解決library cache鎖争用的終極武器

11.2之後,可以通過标準api進行設定。

Oracle背景專家解決library cache鎖争用的終極武器

下面我們用一個簡單的實驗,檢視到底發生了什麼。 在試驗中,我模拟了一個場景,大量session反複執行某一個sql。

從查詢結果來看,記憶體中ash捕捉到的等待事件, library cache: mutex x 占據了很高的比例。

Oracle背景專家解決library cache鎖争用的終極武器

awr報告反應了類似的内容。等待進入了top 1。

Oracle背景專家解決library cache鎖争用的終極武器

經查詢,library cache: mutex x等待的p1非常集中。

Oracle背景專家解決library cache鎖争用的終極武器

經過驗證,p1的值指向該條cursor的handle。 其實你看這個數字的長度,就知道不可能是hash bucket。 這個handle所在的bucket是14503。

Oracle背景專家解決library cache鎖争用的終極武器

接下來, 我們用之前介紹的方法來激活基于此cursor的hotcopy。

由于我的實驗機器cpu太少,是以 我提前設定了隐含參數”_kgl_hot_object_copies”=4來指定copy的個數。

在這裡我們使用了11.2提供的api進行hotcopy的實施,針對cursor,需要完整的hash,可以從x$kglob.kglnahsv中擷取。

然後再次送出同樣的負載。

Oracle背景專家解決library cache鎖争用的終極武器

這一次,我們看到,ash捕捉到的mutex等待開始分散到多個p1上,總數量在變少(忽略32127143,這是第一次試驗遺留的結果)。 通過進一步驗證能夠确認,每個handle的内容都是這個cursor。

Oracle背景專家解決library cache鎖争用的終極武器
Oracle背景專家解決library cache鎖争用的終極武器
Oracle背景專家解決library cache鎖争用的終極武器

這裡我也注意到14503這個hash bucket上的争用增加,如果你還記得之前的輸出,這其實是修改前那個cursor所在的hash bucket。 我猜測即使做了hotcopy,請求仍舊會經由這個bucket跳轉。由于handle上的請求處理速度變快了, bucket上的争用開始顯現,從library cache的結構來看,這些是合理的。

Oracle背景專家解決library cache鎖争用的終極武器

從library cache dump 中驗證,的确增加額外4個handle,相同的對象名。

Oracle背景專家解決library cache鎖争用的終極武器

在新生成的awr報告中, library cache: mutex x 等待時間下降了50%, 從1882秒,下降到942秒.  由此可以驗證,針對純粹的library cache的熱點争用,hotcopy是可以進行緩解的。

Oracle背景專家解決library cache鎖争用的終極武器

最後做一個簡單地小結。

首先,從library cache的結構看, 即使是軟解析,對child和handle的搜尋,也是串行的。 雖然這個操作速度很快,但仍會造成熱點争用。

另外,造成library cache: mutex x争用的原因很多,隻有純粹的熱點争用才需要用hotcopy來解決。

最後,以我的經驗來看,解決資料庫性能問題,沒有固定的套路。 oracle是個極其龐大複雜的體系,幾乎不可能通過幾個簡單的等待事件推測出根本原因,不會有這樣的“神”。 正确的分析方法是,盡可能多的收集證據,然後利用自己的知識和對整體結構的了解,推導出一個“故事”把所有證據串聯起來,有了“故事”以後,再收集更多的證據,反過來來驗證故事的正确性。

<b>本文來自雲栖社群合作夥伴"dbaplus",原文釋出時間:2015-11-21</b>