当前位置: 首页 > 科技观察

图文结合,带你了解MySQL日志(SlowQueryLog)之SlowQueryLog

时间:2023-03-15 09:02:57 科技观察

什么是SlowQueryLogMySQL的慢查询日志是用来记录MySQL中响应时间超过阈值的语句,具体指运行时间超过long_query_time值的SQL会记录在慢查询日志中。long_query_time的默认值是10,也就是说运行超过10秒(不包括10秒)的语句就被认为超过了我们的最大容忍时间值。它的主要作用是帮助我们发现那些执行时间较长的SQL查询,并有针对性地对其进行优化,从而提高系统的整体效率。当我们的数据库服务器阻塞运行缓慢时,查看慢查询日志,找出那些慢查询,对解决问题很有帮助。例如,如果一个平方|执行超过5秒,我们认为它是慢SQL。我们希望收集5秒以上的SQL,结合explain进行综合分析。默认情况下,MySQL数据库是不开启慢查询日志的,需要我们手动设置这个参数。如果非调优需要,一般不建议开启该参数,因为开启慢查询日志会在一定程度上对性能产生一定的影响。慢查询日志支持将日志记录写入文件。如何打开慢查询日志Openslow_query_logmysql>showvariableslike'%slow_query_log%';+-------------------------------+--------------------------------+|变量名|值|+----------------------------------+------------------------------+|慢查询日志|关闭||slow_query_log_always_write_time|10.000000||慢查询日志文件|/var/lib/mysql/KAiTO-slow.log||--------------------------+------------------------------+4rowsinset(0.00sec)#openslowquerymysql>setglobalslow_query_log='ON';QueryOK,0rowsaffected(0.12sec)然后我们检查慢查询查询日志是否开启,慢查询日志文件位置:mysql>showvariableslike'%slow_query_log%';+------------------------------------+--------------------------------+|变量名|价值|+--------------------------------+-------------------------------+|慢查询日志|开||slow_query_log_always_write_time|10.000000||慢查询日志文件|/var/lib/mysql/KAiTO-slow.log|||+--------------------------------+-------------------------------+4rowsinset(0.00sec)可以看到此时开启了慢查询分析,文件保存在/var/lib/mysql/KAiTO-slow.log文件修改long_query_timethreshold下面我们来看慢查询的时间阈值设置,使用如下命令:mysql>showvariableslike'%long_query_time%';+-----------------+----------+|变量名|价值|+----------------+------------+|long_query_time|10.000000|+----------------+------------+1rowinset(0.00sec)表示SQL语句超过10秒它将是记录在慢查询日志中,那么如何修改这个阈值呢?mysql>设置全局long_query_time=1;mysql>showglobalvariableslike'%long-query_time%';或者修改my.cnf文件,在[mysqld]下添加或修改参数long_query_time、slow_query_log和slow_query_log_file,然后重启MySQL服务器。[mysqld]slow_query_log=ON#开启慢查询日志开关slow_query_log_file=/var/lib/mysql/my-slow.log#慢查询日志目录及文件名信息long_query_time=3#设置慢查询阈值为3秒,SQL超过这个设定值的会记录在慢查询日志中log_output=FILE#一般有两种形式,一种是输出到文件FILE,另一种是写入数据表table,会保存到slow_logmysql库的表如果表中没有指定存储路径,则慢查询日志默认存储在mysql数据库的data文件夹中。如果未指定文件名,则默认文件名为hostname-slow.log。补充min_examined_row_limit除了上述变量外,还有一个控制慢查询日志的系统变量:min_examined_row_limit。此变量表示查询扫描的最小记录数。该变量与查询执行时间共同构成了判断查询是否为慢查询的条件。如果查询扫描的记录数大于或等于该变量的值,且查询执行时间超过long_query_time的值,则该查询将记录在慢查询日志中;否则不会记录在慢查询日志中。mysql>showvariableslike'min%';+------------------------+--------+|变量名|值|+----------------------+--------+|min_examined_row_limit|0|+------------------------+--------+1rowinset(0.01sec)您也可以修改该值min_examined_row_limit通过根据您的需要修改my.cnf文件。MySQL除了记录普通的慢查询外,还提供了两个参数让我们记录不使用索引的查询。它们是:log-queries-not-using-indexes和log_throttle_queries_not_using_indexeslog-queries-not-using-indexes系统变量log-queries-not-using-indexes的作用是将不使用索引的查询也记录在慢查询日志。log_throttle_queries_not_using_indexes可以设置为log_throttle_queries_not_using_indexes来限制每分钟写入慢日志的SQL语句的数量,而不是建立索引。该参数默认为0,表示不启用,即不控制写入SQL语句的条数。在生产环境中,如果不使用索引,这样的SQL语句会被频繁的记录到slowlog中,导致slowlog文件的大小不断增加,我们可以通过调整这个参数来配置。log_slow_extra如果启用了log_slow_extra系统变量(自MySQL8.0.14起可用),服务器会将几个额外的字段写入日志。如果要记录bytes_received和bytes_sent这两个字段,需要开启perconaslowlogGreatSQL是从PerconaServer衍生出来的分支版本。除了PerconaServer既有的稳定、可靠、高效、管理更方便等优势外,还进一步完善了MGR。(MySQL组复制)性能和可靠性,以及许多错误修复。这就是为什么在使用GreatSQL查看慢查询日志时,会有Query_time、Lock_time等信息。这就是为什么我们的GreatSQL起源于PerconaServer的原因,使得查询内容更加丰富,更多的数据让我们能够更好的排除错误。我们通过一个简单的案例来展示一下:我们先打开慢查询日志,设置时间阈值大于1秒来记录:#打开慢查询日志mysql>setglobalslow_query_log='ON';QueryOK,0rowsaffected(0.00sec)#Recordmysql>setgloballong_query_time=1;QueryOK,0rowsaffected(0.01sec)mysql>showvariableslike'%long_query_time%';+-----------------+----------+|变量名|值|+----------------+---------+|long_query_time|1.000000|+----------------+------------+1rowinset(0.00sec)#查看已记录的慢查询次数mysql>显示全局状态,如'%Slow_queries%';+----------------+------+|变量名|价值|+----------------+--------+|慢查询|3|+----------------+--------+1rowinset(0.01sec)写一个超过1秒的SQL语句mysql>SELECT*FROM`student`WHEREid>1000AND`name`='Yunxi';+--------+--------+--------+------+----------+|9999715|707|云溪|863|71|.........省略|9999999|418|云溪|793|734|+--------+--------+--------+------+--------+166949行集合(3.94秒)mysql>显示全局状态,如'%Slow_queries%';+----------------+------+|变量名|值|+----------------+------+|慢查询|4|+--------------+------+1rowinset(0.00sec)可以看到这条SQL已经被记录,接下来我们去看看慢查查询日志:#时间:2022-12-14T15:01:34.892085Z#用户@主机:root[root]@localhost[]Id:8#查询时间:3.985637锁定时间:0.000138发送行:165346已检查行:9900000线程编号::0杀死:0bytes_received:0bytes_sent:4848540read_first:0read_last:0read_keyke:1read_nexk:9900000:9900000开始:2022-12-14T15:01:30.906448Z结束:2022-12-14T15:01:34.892085Z模式:慢Rows_affected:0#Tmp_tables:0Tmp_disk_tables:0Tmp_table_sizes:0#InnoDB_trx_id:0#Full_scan:NoFull_join:没有Tmp_table:没有Tmp_table_on_disk:没有#Filesort:没有Filesort_on_disk:没有Merge_passes:0#InnoDB_IO_r_ops:27606InnoDB_IO_r_bytes:452296704InnoDB_IO_r_wait:0.220474#InnoDB_rec_lock_wait:0.000000InnoDB_queue_wait:0.000000#InnoDB_pages_distinct:8191useslow;SETtimestamp=1671030090;SELECT*FROM`student`WHEREid>100000AND`name`='Yunxi';可以看到慢查询日志记录的非常详细。从上面的日志中,可以看到几个信息:1.这条SQL耗时3.985637秒。2、返回结果有165346行,共需要扫描990万行数据。如果扫描的行数很多,但是返回的行数很少,说明SQL效率很低,索引可能不合适。3、Read_*等几个指标表示这条SQL读取记录的方式,是顺序读、随机读等。4、Sort_*等几个指标表示这条SQL是否产生了排序,以及排序的代价。如果有,成本高,就需要想办法优化。5、tmp等几个指标表示SQL是否生成临时表及其开销。如果有,成本高,就需要想办法优化。6、full_scan/Full_join表示是否产生了全表扫描或全表JOIN。如果是,而且SQL耗时长,就需要想办法优化了。7、InnoDB_IO_*等几个指标表示InnoDB在逻辑上读取相关数据。8.InnoDB_rec_lock_wait表示是否有行锁在等待。9.InnoDB_queue_wait表示是否有队列在等待。10、InnoDB_pages_distinct表示SQL总共读取了多少InnoDBpages,这是一个很重要的指标。GreatSQL可以替代MySQL或PerconaServer用于在线生产环境。完全免费并与MySQL或PerconaServer兼容。综上所述,如果你在生产环境中使用过PerconaServer,你也可以放心使用GreatSQL。详见:(https://greatsql.cn/doc/#!&v=47_6_0)详细了解GreatSQL查看慢查询条数查看当前系统有多少条慢查询记录SHOWGLOBALSTATUSLIKE'%Slow_queries%';慢查询日志分析工具在生产环境中,如果要手动分析日志,查找并分析SQL,显然是一项费力的工作。MySQL提供了日志分析工具mysqldumpslow,也可以使用其他工具pt-query-digest。它可以从日志、进程列表和tcpdump分析MySQL的状态。日志包括slowlog、generallog、binlog。您还可以将分析结果输出到文件,或将文件写入表。分析过程是先对查询语句的条件进行参数化,然后对参数化后的查询进行分组统计,并计算出每条查询的执行时间、频率、比例等,然后利用分析结果来识别问题并优化它们。关闭慢查询日志笔者建议除了调优外,不要开启MySQL服务器停止慢查询日志功能:方法1[mysqld]slow_query_log=OFF方法2SETGLOBALslow_query_log=off;删除慢查询日志mysql>showvariableslike'%slow_query_log%';+----------------------------------+----------------------------------+|变量名|价值|+--------------------------------+-------------------------------+|慢查询日志|开||slow_query_log_always_write_time|10.000000||慢查询日志文件|/var/lib/mysql/zhyno1-slow.log||慢查询日志使用全局控制||+--------------------------------+-------------------------------+4rowsinset(0.00sec)通过上面的查询可以看到慢查询日志的目录,手动删除慢查询在此目录中查询日志文件。或者使用命令mysqladmin删除,mysqladmin命令语法如下:mysqladmin-uroot-pflush-logs执行该命令后,命令行会提示输入密码。输入正确的密码后,将执行删除操作。新的慢查询日志会直接覆盖旧的查询日志,不需要手动删除。请注意,使用mysqladminflush-logs命令删除并重建慢速查询日志。使用时需要注意的是,一旦执行该命令,慢查询日志将只存在于新的日志文件中。如果需要旧的查询日志,必须提前备份。参考文章《MySQL是怎样运行的--从根儿上理解MySQL》—孩子4919(https://juejin.cn/book/6844733769996304392)