【MySQL】MySQL Slow Log

一、背景

一般情况下,线上环境的MySQL实例都会开启slow log来收集MySQL的慢日志,用来分析业务应用中的慢SQL,达到优化SQL的目的。

收集慢SQL,有几个参数肯定是需要设置的:

slow_query_log=on
这个参数代表开启慢日志的收集。如果要关闭,设置为off

long_query_time=xxx
其中,xxx是一个数字,单位是秒,一般线上环境会根据业务的情况来设置,1~10s都有可能,当然,也有可能设置为0,代表收集全量的业务日志。
一旦业务的SQL执行时间超过这个阈值,MySQL会递增global status中的slow_queries全局变量,然后再把慢日志写入到slow query log中。

log_queries_not_using_indexes=on:
这个参数的字面意思很好理解,代表将所有没有使用索引的慢查询都记录下来。
但实际情况是,即使一个查询用到了索引,但是这个索引并没有过滤掉任何数据,而是返回了表里面所有的数据,这个查询也会被记录到表里面。

slow_query_log_file=/path/to/dir:
这个参数很好理解,就是慢日志的保存路径。

二、 场景分析

  1. 首先,我们开启这两个参数,代表收集所有的慢日志
mysql> set global slow_query_log=on;
Query OK, 0 rows affected (0.00 sec)

mysql> set global long_query_time= 0;
Query OK, 0 rows affected (0.00 sec)

  1. 然后我们在MySQL中随便执行几条命令
    注意,真的是随便执行。
mysql> delete database test;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'database test' at line 1
mysql> exit
Bye

mysql> testtesttestttttttttttttttttttt--------ttt;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'testtesttestttttttttttttttttttt--------ttt' at line 1
mysql>
mysql> exit
Bye

这两条可能根本就不是能够正常执行的命令。

  1. 查看MySQL的慢日志
$ tail  -f  /path/to/mysql_slow.log

mysqld, Version: 5.7.24 (MySQL Community Server (GPL)). started with:
Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock
Time                 Id Command    Argument
# Time: 2022-11-09T08:54:58.240129Z
# User@Host: root[root] @  [172.17.0.1]  Id:  4343
# Query_time: 0.002451  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0
SET timestamp=1667984098;
set global slow_query_log=on;
# Time: 2022-11-09T08:55:01.149621Z
# User@Host: root[root] @  [172.17.0.1]  Id:  4343
# Query_time: 0.002791  Lock_time: 0.000289 Rows_sent: 5  Rows_examined: 1026
SET timestamp=1667984107;
delete database test;
# Time: 2022-11-09T08:55:09.597576Z
# User@Host: root[root] @  [172.17.0.1]  Id:  4343
# Query_time: 0.000019  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0
SET timestamp=1667984303;
testtesttestttttttttttttttttttt--------ttt;
# Time: 2022-11-09T08:58:25.771920Z
# User@Host: root[root] @ localhost []  Id:  4346
# Query_time: 0.000019  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0
SET timestamp=1667984305;
# administrator command: Quit;

这个结果,多少有点离谱。这种"SQL"根本无法执行,即使记录到慢日志中,也没有任何意义。
如果我们用pt-query-digest这种工具去解析慢日志,在前端展示慢SQL结果的时候,确实看着不那么优雅美观。

如何避免这个问题?

出现这种情况,都是SQL本身在解析器阶段词法解析或者语法解析的时候,就出现错误了,解析的过程非常快。

那么我们其实可以给long_query_time设置一个更加合理的值来杜绝这种现象。例如0.01秒,设置为0.01秒意味着只有执行时间大于10ms的SQL才会被收集到,大概率可以过滤掉这种SQL,但是如果你想收集全量日志,有些业务SQL可能也就漏掉了。

所以这个值设置多少最好呢?其实还是看你业务关注的慢日志阈值。

这篇文章主要告诉大家,设置为0,就会出现这种看起来比较离谱的错误SQL出现在你的慢日志里面。

三、参考

MySQL官方工具 + 开源工具
图文: https://www.modb.pro/db/77114
视频:https://www.modb.pro/course/play/97?lsId=4647
PPT:https://www.modb.pro/doc/38657

你可能感兴趣的:(【MySQL】MySQL Slow Log)