2017-08-09 DBA日記,併發高頻執行SQL帶來的思考

目的(Why)

深入理解當高頻執行SQL時,oracle所發生的等待事件,併爲此制定解決方案。

執行人員(Who)

ORACLE DBA

運行環境(Where)

  • database : oracle 11.2.0.3 + ASM +SSD # 當然是測試環境。
  • OS:IBM AIX 7.1
  • 模擬工具:在上一篇提到的使用python自主開發的一款併發工具。

模擬場景(What)

模擬30個用戶,併發調用一個存儲過程,該存儲過程每調用一次就循環執行insert語句50W次.

模擬結果

  1. 當insert的目標表,沒有索引時,主要的等待事件爲cursor pin s
  2. 當insert的目標表,有索引時,等待事件如下:
    • cursor pin s
    • latch: cache buffers chains
    • buffer busy waits

結論

  1. cursor pin s
    • 官方解釋: session waits for "cursor: pin S" when it wants a specific mutex in S (share) mode on a specific cursor and there is no concurrent X holder but it could not acquire that mutex immediately. This may seem a little strange as one might question why there should be any form of wait to get a mutex which has no session holding it in an incompatible mode. The reason for the wait is that in order to acquire the mutex in S mode (or release it) the session has to increment (or decrement) the mutex reference count and this requires an exclusive atomic update to the mutex structure itself. If there are concurrent sessions trying to make such an update to the mutex then only one session can actually increment (or decrement) the reference count at a time. A wait on "cursor: pin S" thus occurs if a session cannot make that atomic change immediately due to other concurrent requests. Mutexes are local to the current instance in RAC environments
    • 大概的意思是,session在用mutex以share方式鎖定一個沒有被加上獨佔鎖的遊標時,出現等待,按道理不應該是這樣的,原來是因爲,session在用mutex加鎖前,要先更新mutex結構中的計數器,如果這時mutex的計數器,被另一個session鎖定,則出現等待。
    • 理解完這個等待事件後,大概知道原因了,mutex是一個最輕量級的鎖,按理來說操作應該很快的,估計在毫秒以下的,但是我在使用30個併發會話,調用loop來循環插入,這時候的併發請求(請求執行sql語句)時間,估計也達到毫秒以下,並且是在執行同一條SQL主句(綁定變量),所以30個併發會話,都會同對同一個cursor加share lock,都要調用同一個mutex,而此時cpu的使用率明顯上升到60%左右,cpu能力下降,mutex更新計數器的操作就會變慢,cursor pin s就變成主要等待事件。(當然也有一個原因是採用SSD後,IO性能提升,logfile sync事件就減少了)
  2. latch: cache buffers chains,這個等待事件其實比較常見,在併發執行select時也會出現的,但是這次是在insert時出現的,可能的原因如下:
    • 在insert完後,新增了index的關鍵字值,這時index需要重排序,爲了不影響排序結果,估計這時會所索引的所有數據塊鎖定,進行排序,一般情況下,這個排序應該也是很快完成的,但是這個場景的特點,併發請求數大(大於CPU數量),請求速度快(無須再建立連接,直接使用share sql cursor,ssd),所以此時目標表,數據量大的話,就算排序時間不變的情況下,其它會話會由於不能進行排序,也會出現這個等待事件。
  3. buffer busy waits,熱塊,常見事件,因爲insert到表段及索引段上,都會引發這個事件。這裏不特別說了。

解決方案

  1. 管理上,嚴控這種使用loop/while/for等循環結構的語句,在併發場景下,高頻執行SQL語句。
  2. 監控上,監控活動會話數,以及每秒執行sql語句數。
  3. 優化,對於發現的SQL語句進行優化。

影響

佔用大量的CPU資源,主要是在解釋sql及索引排序時,如果CPU處理能力不足,數據庫就會崩掉。

發佈了73 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章