The Slow Query Log: https://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html
Selecting General Query and Slow Query Log Output Destinations: https://dev.mysql.com/doc/refman/5.7/en/log-destinations.html
MySQL慢查询日志总结: http://www.cnblogs.com/kerrycode/p/5593204.html
MYSQL开启慢查询日志实施: http://www.cnblogs.com/wangtao_20/archive/2013/09/06/3304645.html
引言:
慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值long_query_time的SQL语句,SQL执行时间超过long_query_timeL,则将记录到慢查询日志中。long_query_time的默认值为10,意思是执行时间10s以上的语句,将会被记录慢查询日志中。long_query_time精确到毫秒,即可配置1.005,这种形式的阀值。默认情况下,Mysql数据库并不启动慢查询日志,需要我们手动来设置这个参数或通过配置文件(my.cnf),当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。就启动慢查询日志的方法而言,建议用手动来设置,不建议用配置文件,手动设置的话,不用重启就能起效,而配置文件方式需要重启,同时我们一般会在开发环境中,来调优,到正式就不用了,所以我们用手动设置方法。慢查询日志支持将日志记录写入文件(FILE),也支持将日志记录写入数据库表(TABLE)。
今天我们就来看手动方式启动慢查询日志功能:
查看慢查询日志是否开启
mysql> show variables like '%slow_query%';
-> ;
+---------------------------+---------------------------------+
| Variable_name | Value |
+---------------------------+---------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /mysqldata/Donald_Draper-slow.log |
+---------------------------+---------------------------------+
2 rows in set
slow_query_log控制慢查询日志,slow_query_log_file为慢查询日志文件,一般为hostname-slow.log,主要这个文件mysql必须有权限读写。
开启慢查询日志功能
mysql> set global slow_query_log = 1;
Query OK, 0 rows affected
mysql> show variables like '%slow_query%';
+---------------------+---------------------------------+
| Variable_name | Value |
+---------------------+---------------------------------+
| slow_query_log | ON |
| slow_query_log_file | /mysqldata/Donald_Draper-slow.log |
+---------------------+---------------------------------+
2 rows in set
已开启
再来查看慢查询响应时间阀值long_query_time
mysql> show variables like '%query_time%';
+------------------------------+---------------------------------+
| Variable_name | Value |
+------------------------------+---------------------------------+
| long_query_time | 10.000000 |
+------------------------------+---------------------------------+
1 rows in set
long_query_time的默认值为10,意思是执行时间10s以上的语句,将会被记录慢查询日志中。
long_query_time精确到毫秒,即可配置1.005,这种形式的阀值。
修改慢查询响应时间阀值long_query_time为1秒
mysql> set global long_query_time = 1;
Query OK, 0 rows affected
mysql> show variables like '%query_time%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set
查看修改后响应时间阀值long_query_time,
注意:这个时候不能在用上面的命令show variables like '%query_time%',这个命令执行后还是原来的值,这个可能是mysql使用的缓存,我们用show global variables like '%query_time%'命令来查看
mysql> show global variables like '%query_time%';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set
mysql>
来看慢查询日志默认输出的格式:
mysql> show variables like '%log_output%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | FILE |
+---------------+-------+
1 row in set
mysql>
log_output有两种方式,一种为FILE,及记录中日志中,一种为TABLE,将慢日志记录在
mysql.slow_log表中。
先来看第一种方式:
执行查询,查看慢查询日志文件:
Donald_Draper:~ #tail -f Donald_Draper-slow.log
# Time: 170518 14:29:14
# User@Host: donald[123456] @ [192.168.31.153] Id: 16
# Query_time: 0.009314 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
use test;
SET timestamp=1495088954;
# administrator command: Init DB;
# Time: 170518 14:29:15
# User@Host: donald[123456] @ [192.168.31.153] Id: 16
# Query_time: 0.665908 Lock_time: 0.000156 Rows_sent: 69 Rows_examined: 69
SET timestamp=1495088955;
SHOW FULL TABLES WHERE Table_type != 'VIEW';
# Time: 170518 14:29:28
# User@Host: donald[123456] @ [192.168.31.153] Id: 17
# Query_time: 0.033067 Lock_time: 0.000183 Rows_sent: 1 Rows_examined: 1
SET timestamp=1495088968;
SHOW TABLE STATUS LIKE 'message_info';
# User@Host: donald[123456] @ [192.168.31.153] Id: 17
# Query_time: 0.048564 Lock_time: 0.000116 Rows_sent: 1000 Rows_examined: 1000
SET timestamp=1495088968;
SELECT * FROM `message_info` LIMIT 0, 1000;
# Time: 170518 14:32:28
# User@Host: donald[123456] @ [192.168.31.153] Id: 10
# Query_time: 106.102272 Lock_time: 0.000191 Rows_sent: 1 Rows_examined: 8494928
SET timestamp=1495089148;
select count(*) from message_info;
我们取一条来看
# Time: 170518 14:32:28 发生时间
# User@Host: donald[123456] @ [192.168.31.153] Id: 10 访问信息
# 查询时间 锁住时间
# Query_time: 106.102272 Lock_time: 0.000191 Rows_sent: 1 Rows_examined: 8494928
SET timestamp=1495089148;
#执行慢查询语句
select count(*) from message_info;
再来看第二种慢日志输出方式-TABLE:
修改慢日志输出方式log_output为TABLE
mysql> set global log_output = 'TABLE';
Query OK, 0 rows affected
mysql> show variables like '%log_output%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | TABLE |
+---------------+-------+
1 row in set
mysql>
查询慢日志表
mysql> select * from mysql.slow_log;
+---------------------+-----------------------------------+------------+-----------+-----------+---------------+------------------+----------------+-----------+-----------+------------------------------------------+-----------+
| start_time | user_host | query_time | lock_time | rows_sent | rows_examined | db | last_insert_id | insert_id | server_id | sql_text | thread_id |
+---------------------+-----------------------------------+------------+-----------+-----------+---------------+------------------+----------------+-----------+-----------+------------------------------------------+-----------+
| 2017-05-18 14:42:01 | donald[123456] @ [192.168.31.153] | 00:00:00 | 00:00:00 | 12 | 12 | mysql | 0 | 0 | 1 | SHOW COLUMNS FROM `mysql`.`slow_log` | 19 |
| 2017-05-18 14:42:30 | donald[123456] @ [192.168.31.153] | 00:00:37 | 00:00:00 | 1 | 1260746 | test | 0 | 0 | 1 | select count(*) from company_info | 10 |
| 2017-05-18 14:42:45 | donald[123456] @ [192.168.31.153] | 00:00:00 | 00:00:00 | 2 | 2 | mysql | 0 | 0 | 1 | SELECT * FROM `slow_log` LIMIT 0, 1000 | 19 |
+---------------------+-----------------------------------+------------+-----------+-----------+---------------+------------------+----------------+-----------+-----------+------------------------------------------+-----------+
3 rows in set
mysql>
我们也可以配置log_queries参数来设置将没有使用索引的语句记录在
慢日志中
查看log_queries_not_using_indexes
mysql> show variables like '%log_queries%';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | OFF |
+-------------------------------+-------+
1 row in set
开启记录没有使用索引的语句功能
mysql> set global log_queries_not_using_indexes = 1;
Query OK, 0 rows affected
mysql> show variables like '%log_queries%';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | ON |
+-------------------------------+-------+
1 row in set
在开启记录没有使用索引的语句功能情况下,我们可以通过log_throttle_queries_not_using_indexes
控制每秒中允许记录没有使用索引的语句数量,默认为0,即不限制,如果不限制的情况,太多这样的日志产生将会影响mysql的性能。
mysql> show variables like '%log_throttle%';
+----------------------------------------+-------+
| Variable_name | Value |
+----------------------------------------+-------+
| log_throttle_queries_not_using_indexes | 0 |
+----------------------------------------+-------+
1 row in set
直接通过慢日志文件和慢日志表的方式还不能清晰便捷的分析慢查询语句的具体慢的原因,我们可以通过MySQL提供的慢日志分析工具mysqldumpslow来分析慢日志文件。
Donald_Draper:~ # mysqldumpslow --help
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
Parse and summarize the MySQL slow query log. Options are
--verbose verbose
--debug debug
--help write this text to standard output
-v verbose
-d debug
-s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default,默认为平均查询时间
al: average lock time 平均锁住时间
ar: average rows sent 平均返回记录数
at: average query time 平均查询时间
c: count 访问次数
l: lock time 锁住时间
r: rows sent 返回的记录数
t: query time 查询时间
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries 只显示最前面n个慢查询
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
实例:查询语句的排序方式为,平均查询时间,平均锁住时间,查询时间,锁住时间
Donald_Draper:~ # mysqldumpslow -s at al t l c -t 6 /mysqldata/Donald_Draper-slow.log
Reading mysql slow query log from al t l c /mysqldata/Donald_Draper-slow.log
Count: 1 Time=173.86s (173s) Lock=0.00s (0s) Rows=1.0 (1), donald[123456]@[192.168.31.153]
select count(*) from message_info
Count: 1 Time=106.10s (106s) Lock=0.00s (0s) Rows=1.0 (1), donald[123456]@[192.168.31.153]
select count(*) from company_info
Count: 1 Time=0.67s (0s) Lock=0.00s (0s) Rows=69.0 (69), donald[123456]@[192.168.31.153]
SHOW FULL TABLES WHERE Table_type != 'S'
Count: 1 Time=0.05s (0s) Lock=0.00s (0s) Rows=1000.0 (1000), donald[123456]@[192.168.31.153]
SELECT * FROM `company_info` LIMIT N, N
Count: 1 Time=0.03s (0s) Lock=0.00s (0s) Rows=1.0 (1), donald[123456]@[192.168.31.153]
SHOW TABLE STATUS LIKE 'S'
Count: 1 Time=0.01s (0s) Lock=0.00s (0s) Rows=0.0 (0), donald[123456]@[192.168.31.153]
当输出结果的比较多时,我们可以使用管线,结合more或grep,查找需要的信息:
Donald_Draper:~ # mysqldumpslow -s at al t l c -t 6 /mysqldata/Donald_Draper-slow.log | more/grep
或者用流导向,将排序后的结果导入文件在查看:
Donald_Draper:~ # mysqldumpslow -s at al t l c -t 6 /mysqldata/Donald_Draper-slow.log > mysql-slow-log-sort.txt
本篇文章中我们手动设置的所有变量的作用域可为全局和会话,并且可以动态生效。我们设置的都是全局的,由于这些都是手动设置,动态生效,数据库重启时,将会失效,如果不想失效可以写在配置文件中。
[mysqld]
slow_query_log = 1
slow_query_log_file = /mysqldata/Donald_Draper-slow.log
long_query_time = 1
log_output=FILE
log-queries-not-using-indexes = 1
log_throttle_queries_not_using_indexes = 10