MySQL在使用過程當中遇到訪問速度慢,或者沒法響應這類的問題,解決方式基本都有定式,通常第一反應都會是登陸到MySQL, show processlist看看當前鏈接狀態。php
雖然說簡單,但show processlist顯示的信息確實是至關有用,有一回,三思收到反饋說MySQL查詢很慢,因而,趕忙登陸到mysql中,執行show processlist查看當前鏈接信息:前端
mysql> show processlist;mysql
+--------+-------------+--------------------+-------+---------+-------+----------------------------------+----------------------------------------------------------------------------------+ios
| Id | User | Host | db | Command | Time | State | Info |sql
+--------+-------------+--------------------+-------+---------+-------+----------------------------------+----------------------------------------------------------------------------------+操作系統
| 1 | system user | | NULL | Connect | 342266| Waiting for master to send event | NULL | 線程
| 2 | system user | | hdpic | Connect | 872 | Locked | UPDATE a SET STATE=0 WHERE ID=83752 | debug
| 123890 | hdpic_read | 192.168.1.79:54910 | hdpic | Query | 1512 | Sending data | select z.ID,z.TITLE,z.CREATOR_USER_NICK,z.CREATOR_USER_IDEN,z.LASTEDITOR_TI | 隊列
| 124906 | hdpic_read | 192.168.1.39:18844 | hdpic | Query | 845 | Locked | select * from a where ((ID = 78789) AND (STATE != 0)) | ssl
| 124912 | hdpic_read | 192.168.1.39:18862 | hdpic | Query | 845 | Locked | select * from a where ((ID = 16031) AND (STATE != 0)) |
| 124914 | hdpic_read | 192.168.1.39:18865 | hdpic | Query | 837 | Locked | select * from a where ((ID = 39109) AND (STATE != 0)) |
| 124917 | hdpic_read | 192.168.1.39:18875 | hdpic | Query | 833 | Locked | select * from a where ((ID = 16031) AND (STATE != 0)) |
一堆的Locked,怪不得慢啊,阻塞的時間不短了,十幾分鍾。
一般來講存在Locked就說明當前讀寫操做存在被阻塞的狀況,通常咱們看到鎖都會下意識認爲是因爲寫阻塞了讀,上面的結果看彷彿也符合這一特徵: 只有一條UPDATE,而無數條的SELECT。這畢竟是線上系統,就算想殺鏈接的線程,也是要殺掉形成阻塞的那個,不能把全部 Locked的全殺了。
從show processlist查看到的信息來看,UPDATE的語句是很簡單的,分析a的表結構,該表爲MyISAM表,ID爲該表主鍵,該條更新應該可以瞬間執行完,即便系統繁忙也不該該,並且經過查看當前的系統狀態,總體負載很低,iostat中看I/Owait幾可忽略,該寫操做不太可能這麼長時間都沒有執行完。
這個時候再分析show processlist中顯示的信息,發現id 123890的語句執行時間最長,確定是在該UPDATE語句以前執行 的,經過show full processlist查看語句詳表,看到該查詢也訪問到了a表,經此分析,應該是該語句長時間的讀阻塞了寫,而被阻塞的寫操做因爲處於最優先處理隊列,又阻塞了其它的讀。不過這些都還只是咱們的推論,考慮到線上系統服務的可靠性,最好仍是能找到更確切的證據,然後再作操做。
mysqladmin命令有一個debug參數,能夠分析當前MySQL服務的狀態信息,同時也能夠用來幫助咱們定位當前鎖的詳細狀況,執行mysqladmin命令以下:
[root@phpmysql02 data]# mysqladmin -uroot -p -S /data/3306/mysql.sock debug
debug會將狀態信息生成到mysql的錯誤文件,通常鎖的信息都會保存在最後幾行,這裏咱們在操做系統層error log最後幾行:
[root@phpmysql02 data]# tail -10 phpmysql02.err
Thread database.table_name Locked/Waiting Lock_type
2 hdpic.t_wiki_zutu Waiting - write Highest priority write lock
123890 hdpic.t_wiki_zutu_category Locked - read Low priority read lock
123890 hdpic.t_wiki_zutu_photo Locked - read Low priority read lock
123890 hdpic.t_wiki_zutu Locked - read Low priority read lock
124906 hdpic.t_wiki_zutu Waiting - read Low priority read lock
從上述信息能夠看出,123890持有的讀鎖阻塞了2的寫入和124906的讀操做,這個狀態符合咱們的推論,若是現狀不可接受,不能繼續等待,將123890殺掉,釋放資源便可:
mysql> kill 123890;
Query OK, 0 rows affected (0.00 sec)
再次執行show processlist查看:
mysql> show processlist;
+--------+-------------+--------------------+-------+---------+--------+----------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+--------+-------------+--------------------+-------+---------+--------+----------------------------------+------------------+
| 1 | system user | | NULL | Connect | 342390 | Waiting for master to send event | NULL |
| 124906 | hdpic_read | 192.168.1.39:18844 | hdpic | Sleep | 1 | | NULL |
| 124912 | hdpic_read | 192.168.1.39:18862 | hdpic | Sleep | 2 | | NULL |
| 124914 | hdpic_read | 192.168.1.39:18865 | hdpic | Sleep | 1 | | NULL |
已經沒有Locked的鏈接,此時向前端人員詢問,告知響應慢的現象也已經消除,服務恢復正常。