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的链接,此时向前端人员询问,告知响应慢的现象也已经消除,服务恢复正常。