1. 程式人生 > >MySQL所有操作hang住了,怎麼破?

MySQL所有操作hang住了,怎麼破?

作者介紹

王鬆磊,現任職於UCloud,從事MySQL資料庫核心研發工作。主要負責UCloud雲資料庫udb的核心故障排查工作以及資料庫新特性的研發工作。

系統環境

CentOS release 6.7

MySQL社群版MySQL-5.5.24

故障簡述

首先收到故障告警,所有的監控無法讀取到資料。稍後收到客戶的反饋,無法正常連線資料庫。

故障排查

1、嘗試登陸資料庫

發現登陸發生hang住的情況,無法正常連線。無任何提醒資訊報出。

shell>mysql -h192.168.150.21 -P50001 -uabc -pabc

shell>mysql  -S /var/lib/mysql/mysql.sock  -uabc -pabc

2、檢視錯誤日誌

錯誤日誌完全正常,無任何錯誤日誌報出。

3、使用pstack

使用pstack工具檢視程序內各個執行緒的堆疊資訊。執行命令:

shell>pstack  <mysqld  pid>  >  pstack.log

將堆疊日誌存放到pstack.log檔案中,分析堆疊日誌的內容。發現存在很多執行緒處於等待執行緒互斥量mutex的狀態,並且等待的mutex是兩個不同的mutex,猜測是因為原始碼記憶體在bug,所以造成了程序死鎖:

pstack

其中執行緒2和執行緒3分別在等待不同的mutex。

mutex

而其它新連線或者已經連線無應答的程序,也在等待其中的一個mutex。

4、使用gdb檢視具體資訊

執行如下命令attach到mysqld程序,檢視當前執行緒堆疊的具體情況。

shell>gdb -p  <mysqld  pid>

執行命令info thread檢視執行緒的具體資訊,發現很多執行緒均在等待鎖資訊。通過上面描述的pstack日誌資訊,我們知道執行緒2和執行緒3存在等待不同鎖的行為且可疑性比較高。

切換到執行緒2檢視,執行緒在等待的mutex為LOCK_index。

LOCK_index

切換到執行緒3檢視,執行緒在等待的mutex為LOCK_thread_count。

由此猜測,是原始碼中由於存在LOCK_index和LOCK_thread_count相互等待的BUG,導致兩個mutex均未被釋放,從而發生死鎖情況。其它需要獲得鎖的操作均發生一致等待的情況(即發生hang住)。

5、檢視原始碼

根據gdb除錯中執行緒2和執行緒3的資訊,檢視命令purge binlog和reset master對應的原始碼。檢視發現兩個命令對於LOCK_thread_count和LOCK_index呼叫順序是不同的。導致同時執行時會發生相互等待,發生死鎖的情況。

原始碼

解決問題

通過與客戶溝通,得到確認,客戶同時執行了purge binlog和reset master命令。最終也確認了我們的猜想,由於上述原因導致了問題的產生。

在檢視官方修復後,發現該bug已經修復。升級到高版本,將客戶資料遷移後解決了此問題。

文章來自微信公眾號:DBAplus社群