背景
採用mysql(5.0)的innodb儲存引擎儲存兩張表,一張表的資料規模在20w行左右,另一張表的資料規模在10w行以下。以select, update操作居多,delete非常少(因此,應該不存在索引或資料頁片段的問題)。伺服器的cpu、記憶體、io的使用率都不高。
問題
就在幾天前(令人髮指的國慶期間,叫天天不應,叫地地不靈),對那兩張表的事務操作變得奇慢無比,在慢日誌裡,一個commit的時間從2s 一直飆升到上千秒,童鞋們,操作的時間單位是秒唉。
問題排查
0. 應用程式層面,沒有任何最佳化可做。
1. 把需要對資料庫進行操作的服務停掉。
2. 嘗試(從下午一點半一直持續到下午六點)
2.1 mysql 系統變數最佳化
buffer、cache相關的變數最佳化,重啟mysql,耗時10分鐘以上,在一張空表裡插入一行記錄,耗時 1~3秒。
2.2 關閉bin-log
和2.1相比,沒有明顯的變化。
2.3 而後,我們發現,任何select 操作都非常快,包括,select count(*) from LIF; 基本上都是幾十、幾百毫秒內響應。而任何更新操作都非常非常慢,耗時分鐘層級,包括,create database test_xxxxx; use test_xxxxx; create table test_update(int, varchar, .....); insert into test_update(.....) values(......);
2.4 mysqldump,把對應資料庫的資料dump,一至兩分鐘就dump完了。18M。
2.5 初步懷疑,問題是作業系統層級的。猜想,在mysql需要對資料庫進行更新操作時,需要向os申請某些資源,而這些資源是稀缺的,因此,mysql的更新線程一直在等待。
2.6 解決問題的暫時方案:將資料庫移到另外一台負載較小的伺服器,將資料匯入,整個過程匯入處理程序幾分鐘就完成了。嘗試幾個簡單的create database XXX; create table XXX; insert into xxxxx; 基本上都是幾十幾百毫秒內響應。
問題挖掘和流程梳理
ok, 問題是暫時解決了,但問題的根源還是沒有發現。
在問題伺服器上,我們在一個session內執行了一次慢操作,如create database xxxxx; 而後,在另外一個session上strace mysql_pid. 發現mysql此時在做的一個耗時的系統調用是futex(), 參數略。
那麼,futext又是個啥玩意兒呢?
http://zh.wikipedia.org/zh-cn/Futex
Futex 由一塊能夠被多個
進程
共用的
記憶體
空間(一個對齊後的
整型
變數)組成;這個整型變數的值能夠通過
組合語言
調用CPU提供的
原子操作
指令來增加或減少,並且一個進程可以等待直到那個值變成正數。Futex 的操作幾乎全部在
應用程式空間
完成;只有當操作結果不一致從而需要仲裁時,才需要進入
作業系統核心
空間執行。這種機制允許使用 futex 的鎖定原語有非常高的執行效率:由於絕大多數的操作並不需要在多個進程之間進行仲裁,所以絕大多數操作都可以在應用程式空間執行,而不需要使用(相對高代價的)核心
系統調用
。
發現關鍵字了,鎖
,工程師的噩夢。
再google一下 “mysql 死結”,出一大票連結
http://www.chinaz.com/Program/Mysql/1219553B2008.html
這個說得比較全面了,很有參考價值,show innodb status; 回頭再好好分析一下。(未完待續)