查询超出变量 long_query_time 指定时间值的为慢查询。但是查询获取锁(包括锁等待)的时间不计入查询时间内。
mysql记录慢查询日志是在查询执行完毕且已经完全释放锁之后才记录的,因此慢查询日志记录的顺序和执行的SQL查询语句顺序可能会不一致(例如语句1先执行,查询速度慢,语句2后执行,但查询速度快,则语句2先记录)。
注意,MySQL 5.1之后就支持微秒级的慢查询超时时长,对于DBA来说,一个查询运行0.5秒和运行0.05秒是非常不同的,前者可能索引使用错误或者走了表扫描,后者可能索引使用正确。
另外,指定的慢查询超时时长表示的是超出这个时间的才算是慢查询,等于这个时间的不会记录。
和慢查询有关的变量:
long_query_time=10 # 指定慢查询超时时长(默认10秒),超出此时长的属于慢查询
log_output={
TABLE|FILE|NONE} # 定义一般查询日志和慢查询日志的输出格式,默认为file
log_slow_queries={
yes|no} # 是否启用慢查询日志,默认不启用
slow_query_log={
1|ON|0|OFF} # 也是是否启用慢查询日志,此变量和log_slow_queries修改一个另一个同时变化
slow_query_log_file=/mydata/data/hostname-slow.log #默认路径为库文件目录下主机名加上-slow.log
log_queries_not_using_indexes=OFF # 查询没有使用索引的时候是否也记入慢查询日志
一、启动和设置慢查询日志
现在启用慢查询日志。
mysql> set @@global.slow_query_log=on;
log_output={TABLE|FILE|NONE} # 定义一般查询日志和慢查询日志的输出格式,不指定时默认为file
二、查看慢查询日志
因为默认超时时长为10秒,所以进行一个10秒的查询。
mysql> select sleep(10);
查看慢查询日志文件。这里看到虽然sleep了10秒,但是最后查询时间超出了847微秒,因此这里也记录了该查询。
[root@VM_2_223_centos mysql]# tail -f /var/lib/mysql/VM_2_223_centos-slow.log
Time Id Command Argument
# Time: 2019-10-16T06:12:36.966416Z
# User@Host: root[root] @ localhost [] Id: 80
# Query_time: 20.000238 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
use db01;
SET timestamp=1571206356;
select sleep(20);
/usr/sbin/mysqld, Version: 5.7.28-log (MySQL Community Server (GPL)). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 2020-12-01T08:54:59.153235Z
# User@Host: skip-grants user[root] @ [218.106.126.130] Id: 23
# Query_time: 10.000395 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
use sys;
SET timestamp=1606812899;
select sleep(10);
随着时间的推移,慢查询日志文件中的记录可能会变得非常多,这对于分析查询来说是非常困难的。好在提供了一个专门归类慢查询日志的工具mysqldumpslow。
[root@xuexi data]# mysqldumpslow --help
-d debug
-v verbose:显示详细信息
-t NUM just show the top n queries:仅显示前n条查询
-a don't abstract all numbers to N and strings to 'S':归类时不要使用N替换数字,S替换字符串
-g PATTERN grep: only consider stmts that include this string:通过grep来筛选select语句。
该工具归类的时候,默认会将同文本但变量值不同的查询语句视为同一类,并使用N代替其中的数值变量,使用S代替其中的字符串变量。可以使用-a来禁用这种替换。如:
Reading mysql slow query log from VM_2_223_centos-slow.log
Count: 1 Time=20.00s (20s) Lock=0.00s (0s) Rows=1.0 (1), root[root]@localhost
select sleep(20)
Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.0 (0), 0users@0hosts
# User@Host: skip-grants user[root] @ [218.106.126.130] Id: 23
# Query_time: 13.000312 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1606813140;
select sleep(13)
Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.0 (0), 0users@0hosts
# User@Host: skip-grants user[root] @ [218.106.126.130] Id: 23
# Query_time: 10.000330 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1606813127;
select sleep(10)
Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.0 (0), 0users@0hosts
# User@Host: skip-grants user[root] @ [218.106.126.130] Id: 23
# Query_time: 10.000395 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
use sys;
SET timestamp=1606812899;
select sleep(10)
慢查询在SQL语句调优的时候非常有用,应该将它启用起来,且应该让慢查询阈值尽量小,例如1秒甚至低于1秒。就像一天执行上千次的1秒语句,和一天执行几次的20秒语句,显然更值得去优化这个1秒的语句。