【此为"一森咖记"公众号——第126篇文章】读完需要10分钟速读仅需5分钟
【引言】
如何在MySQL中查看正在执行的SQL语句有哪些,今天念叨下这件事。
大家都知道,linux环境中很容易通过操作系统top看到执行时间长的进程pid号,根据pid号,再通过oracle的视图v$session,v$process,v$sqltext追到到执行sid,从而查到具体的sql语句。
示例如下:
SQL语句SELECT /*+ ORDERED */
Sid,
event,
p1,
p2,
p3
FROM v$session_wait a
WHERE a.sid IN (SELECT b.sid
FROM v$session b
WHERE b.paddr = (SELECT addr
FROM v$process c
WHERE c.spid = '3128'));
SQL语句2SELECT /*+ ORDERED */
sql_id, sql_text
FROM v$sqltext a
WHERE sql_id IN (SELECT NVL (SQL_ID, PREV_SQL_ID)
FROM v$session b
WHERE b.sid = '151')
ORDER BY piece ASC;
其中SQL语句1中标红部分为top命令查到pid号,SQL语句2中的标红部分为根据SQL语句1查到的SQL语句的SID。
那在如何在MySQL中查看正在执行的SQL语句?
有2个方法:
方法1:
使用showprocesslist,但该方法有个弊端,只能查看正在执行的sql语句,对应历史记录,查看不到,好处是简单便捷。
1.mysql的bin目录下使用 mysqladmin processlist;
2.mysql> show processlist;
如果SUPER权限,可看到全部的线程;否则,只可看到自己发起的线程(当前对应的MySQL帐户运行的线程)。
示例:mysql> show processlist;
+---------+-------------+----------------------+-----------------------+-------------+----------+---------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+---------+-------------+----------------------+-----------------------+-------------+----------+---------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| 7568614 | ethan_app | 192.168.10.69:51420 | ethan_geo_yl | Sleep | 3 | | NULL |
| 7568681 | root | 192.168.10.57:57520 | ethan_opt_yl | Sleep | 5 | | NULL |
| 7569751 | ethan_app | 192.168.10.56:49702 | ethan_geo_yl | Query | 14 | Searching rows for update | update message_info set VAL_STATUS = '1' where TXT_DEVICETOKEN = '5ea335368ea17428a1cf1bd96d9f19aff1 |
| 7569759 | ethan_app | 192.168.10.56:49741 | ethan_geo_yl | Sleep | 30 | | NULL
从上述语句可以看出,info中能显示执行的SQL的类型,但看不到具体的执行SQL。
如何查看具体的SQL,怎么破?
方式2:通过查看information_schema.`PROCESSLIST`
可以用具体的SQL语句进行查看,通过where条件过滤把不相关的信息过滤掉。
具体语句如下:
mysql> select * from information_schema.`PROCESSLIST` where info is not null ORDER BY time desc;
这里有必要介绍下processlist各列的含义和用途:
1、id列:用户登录mysql时,系统分配的"connection_id",可以使用函数connection_id()查看;kill一个语句时会用到,语句为:kill id;MySQL的id相当于Oracle的sid和SERIAL#;
2、user列:显示当前用户。如果不是root,此命令就只显示用户权限范围的sql语句;
3、host列:显示这个语句是从哪个ip的哪个端口上发的,可以用来跟踪出现问题语句的用户;4、db列:显示这个进程目前连接的是哪个数据库;
5、command列:显示当前连接的执行的命令,一般取值为休眠(sleep),查询(query),连接(connect)等;
6、time列:显示这个状态持续的时间,单位是秒;
7、state列:显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个sql语句,已查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成;
8、info列:显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
上述两种方式,刚才也提到过只能查看正在执行的sql语句,对应历史记录,查看不到。
怎么办?
答:开启日志模式
设置开启
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'ON';
设置关闭
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'OFF';
查询具体sql
SELECT * from mysql.general_log ORDER BY event_time DESC
清空表
不允许使用delete删除mysql.general_log,只能用truncate
truncate table mysql.general_log;
但,如果想查看执行时间长的sql,可开启慢日志查询。
首先查询慢日志是否开启:
mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
|slow_query_log | OFF |
+----------------+-------+
1 row in set (0.00 sec)
慢日志查询没有开启。开启如下,找到my.cnf,添加如下内容
# 添加慢查询日志
log_output=file
slow_query_log=on
slow_query_log_file = tmp/mysql-slow.log
log_queries_not_using_indexes=on
long_query_time = 1
重启mysql。
mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | ON |
+----------------+-------+
1 row in set (0.00 sec)
注意:
如果更改日志目录位置,
如更改为/home/msyql/log/mysql-slow.log至少需要将log目录所有者设置为mysql:mysql。重启mysql时,才能自动生成mysql-slow.log文件;否则将无法生成日志文件,mysql用户无权写入数据。
【参考】
http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html
近期热文
你可能也会对以下话题感兴趣。点击链接便可查看。