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,所以造成了程序死鎖:
其中執行緒2和執行緒3分別在等待不同的mutex。
而其它新連線或者已經連線無應答的程序,也在等待其中的一個mutex。
4、使用gdb檢視具體資訊
執行如下命令attach到mysqld程序,檢視當前執行緒堆疊的具體情況。
shell>gdb -p <mysqld pid>
執行命令info thread檢視執行緒的具體資訊,發現很多執行緒均在等待鎖資訊。通過上面描述的pstack日誌資訊,我們知道執行緒2和執行緒3存在等待不同鎖的行為且可疑性比較高。
切換到執行緒2檢視,執行緒在等待的mutex為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社群