天天看點

MySQL執行個體阻塞分析一例(線程statistics狀态)一、 現象二、 分析三、結論

本文用執行個體來分析MySQL阻塞—線程statistics狀态。

某日下午下班後低峰期,現網MySQL一個庫突然報出大量慢sql,狀态是 statistics,但是過後拿這些sql去執行的時候,實際很快。處于 statistics 狀态的線程有個特征:查詢的都是視圖,但看監控那個時間段并沒有明顯的update/detele/insert。

通過我們的快照程式,去分析當時的 innodb status,發現如下資訊:

從上面的資訊知道 Thread 139964610234112 是主線程,在源碼 srv0srv.cc:2132 行的地方等待信号14s,這個信号是在 dict0dict.cc:900 地方建立的 RW-latch 排它鎖。那麼奇怪了,主線程自己在等待自己的互斥鎖。

 由于環境是阿裡雲的RDS(基于MySQL 5.6.16-log 版本),拿不到他們的代碼,找來 5.6.35 的來看,行号對不上。但好在上段資訊的最後面有一個 Main thread state: enforcing dict cache limit,發現在 srv0srv.cc 函數 srv_master_do_active_tasks() 約2137行的位置:

應該是在調用 srv_master_evict_from_table_cache() 從innodb table cache裡面清理緩存的地方waiting(這裡不是一定會清理,而是先判斷空間夠不夠用,參數50表示隻掃描 unused_table list的50%)。srv_master_evict_from_table_cache():

就是在 rw_lock_x_lock(&dict_operation_lock) 這個地方擷取Latch的時候等待了14s,這個鎖就是在資料字典子產品 dict0dict.cc:dict_init() 約1065行的地方建立的,與innodb status輸出基本一緻。 

關于 dict_operation_lock 直接看注釋吧:

在嘗試把表定義逐出緩存時,擷取的是 dict_operation_lock X-mode lock,可是從已有的資訊裡看不到另一個資料字典鎖是什麼。 之前是懷疑是不是 table_definition_cache, table_open_cache, innodb_open_files 設定小了,視圖一般是多表join,更容易消耗打開表的數量,導緻不斷的逐出cache而導緻鎖争用。但是檢查一番并沒發現什麼問題,更何況是14s的等待。關于它們的設定和關系,可以參考我的文章 table_open_cache 與 table_definition_cache 對MySQL的影響(詳見文末參考文獻)。

那麼得換個思路了,processlist裡面有13個長時間處于 statistics 狀态的線程,表示正在計算統計資料,以制定一個查詢執行計劃。 如果一個線程很長一段時間處于這種狀态,可能是磁盤IO性能很差,或者磁盤在執行其他工作。

此時注意到最上面的資訊裡有 Pending normal aio reads: 18 [0, 12, 0, 6] ,有18個讀IO被挂起(實際從監控圖 innodb_data_pending_reads看來,有達到過50),四個read thread有三個處于忙碌狀态。再有 innodb_buffer_pool_pages_flushed 在出異常前10s沒有任何變化,也就是沒有成功的将髒資料刷盤動作。另外這是一個從庫,出異常前10s有出現過瞬間20多秒延遲: 

MySQL執行個體阻塞分析一例(線程statistics狀态)一、 現象二、 分析三、結論
MySQL執行個體阻塞分析一例(線程statistics狀态)一、 現象二、 分析三、結論

(這一切關注的都是 18:59:05 之前的資料,之後的時間,一般恢複了都會有瞬間的讀行數上漲,這個時候别把它們反當做起因)

結合上面的 enforcing dict cache limit 和 statistics IO pending,找到兩個有關的bug report:

https://bugs.launchpad.net/percona-server/+bug/1500176

https://bugs.mysql.com/bug.php?id=84424

第一個是使用 pt-online-schema-change 去更改分區表的結構,可能會出現,但目前bug狀态是Undecided,我們的環境沒有分區表,沒外鍵,也沒有改表動作。 第二個其實 Not a bug:

說到底就是資料庫伺服器IO遇到問題了,可以通過增加 buffer_pool 來緩存更多的資料,或者提高伺服器IO能力,這個範圍就廣了,可參考《8.5.8 Optimizing InnoDB Disk I/O》(詳見文末參考文獻)。  然而生産伺服器都運作了1年之久,高峰期都沒出現過IO問題,現在何況低峰期,也沒有人為操作。那這個鍋隻能交給阿裡RDS了:懷疑是執行個體所在實體機磁盤有抖動。

分析這麼久得出這個結論,卻不能做什麼,因為我們沒辦法看到伺服器級别的IO stats。其實想到去年也有執行個體出現過幾例類似 statistics 問題,向阿裡雲提工單确認實體機狀态,得到的結論都是:“是的,實體機有抖動。需要申請遷移執行個體嗎”,但是從來拿不到依據。如果自己能看到OS級别的監控,其實都不需要本文這麼冗長的分析。

原文釋出時間為:2017-10-25

本文作者:周曉,知數堂第8期學員

繼續閱讀