本文由  网易云发布。

MySQL慢日志(slow log)是MySQL DBA及其他开发、运维人员需经常关注的一类信息。使用慢日志可找出执行时间较长或未走索引等SQL语句,为进行系统调优提供依据。本文结合线上案例分析如何正确设置MySQL慢日志参数和使用慢日志功能,并介绍网易云RDS对MySQL慢日志功能增强。

MySQL参数组功能

网易云RDS实例提供了参数组管理功能,可通过参数管理界面查看绝大部分常用的MySQL系统参数,用户可以了解当前运行值和建议值,如下所示:

用户还可通过参数管理页面对所列的参数进行修改,点击“修改参数”按钮在线设置,点击“保存修改”即可一键完成MySQL主从节点的参数修改,如下图:

查看参数管理界面不难发现,与慢查询相关的参数较多,这些参数是如何起作用的呢,相互关系又是如何,满足什么条件的SQL语句才会记录到慢日志中?只有了解了这些才能更好地利用慢日志进行系统调优和问题定位。我们以一个线上案例为依托来介绍如何正确配置慢日志参数:用户报告他们使用的多个RDS 5.7版本实例慢日志异常,明明执行了一分多钟的SQL语句,却没有记录到慢日志中。还提供了用于复现的SQL语句。

慢日志参数正确配置姿势

首先,我们需确认该实例是否开启了慢日志功能,默认情况下,MySQL慢日志功能是关闭的。慢日志开关参数为slow_query_log,可在mysqld启动命令行或配置文件中显式指定,若指定slow_query_log=1或不指定值,则表示开启慢日志,赋值为0表示关闭。用户可以在运行时动态开启和关闭。网易云RDS实例默认开启慢日志功能,我们确认了该用户未关闭实例的慢日志开关。

接下来,需确认慢日志记录位置,MySQL使用log_output参数指定以文件(FILE)还是表(TABLE)的方式来保存慢日志,需要强调的是,仅指定log_output而将slow_query_log置为0并不会记录慢日志,也就是说slow_query_log才是慢日志的开关。若使用文件形式记录慢日志,则可通过slow_query_log_file指定文件名,如果用户没有显式指定slow_query_log_file,则MySQL将其初始化为host_name-slow.log,host_name即为运行mysqld的主机名,慢日志文件默认位于MySQL数据目录。网易云RDS实例不允许用户修改日志文件路径,但可以配置log_output参数,通过查询,确认该实例以文件方式记录慢日志,查看日志文件确认没有用户所述的SQL语句。

由于用户提供了复现语句,我们执行了其SQL语句,确实1分多钟才返回,通过explain命令发现其未走索引,扫描了较多的记录数,再次查看慢日志仍没有记录该SQL语句。MySQL会记录满足执行时间超过long_query_time秒,扫描记录数超过min_examined_row_limit行的SQL语句。long_query_time参数最小值和默认值分别为1和10s,该参数可以精确到微秒(ms)。如果选择将慢日志记录到文件中,那么所记录的时间精确到微秒,如果记录到慢日志表(mysql.slow_log)中,那么仅精确到秒,微秒部分被忽略。网易云RDS实例允许用户设置这两个参数值,那么是不是用户调整了上述两个阈值,导致无法满足记录条件呢,进一步查询发现也不是问题原因所在。

我们注意到MySQL还有个名为log_queries_not_using_indexes的参数用于控制是否记录未走索引的SQL查询,代码如下:

重点关注箭头所指内容,如果查询未走索引或者索引无效,且相关参数开启,那么warn_no_index设置为true,若同时满足扫描记录数超过阈值,也会像慢查询一样被记录,那么是不是该参数未开呢?结果仍是否定的。

问题原因之所在

由于数据库实例中可能有较多不走索引的SQL语句,若开启log_queries_not_using_indexes,则存在日志文件或表容量增长过快的风险,此时可通过设置log_throttle_queries_not_using_indexes来限制每分钟写入慢日志中的不走索引的SQL语句个数,该参数默认为0,表示不开启,也就是说不对写入SQL语句条数进行控制。启用后,系统会在第一条不走索引的查询执行后开启一个60s的窗口,在该窗口内,仅记录最多log_throttle_queries_not_using_indexes条SQL语句。超出部分将被抑制,在时间窗结束时,会打印该窗口内被抑制的慢查询条数以及这些慢查询一共花费的时间。下一个统计时间窗并不是马上创建,而是在下一条不走索引的查询执行后开启。对应到该线上问题,log_throttle_queries_not_using_indexes被设置为10,在日志文件中看到周期性打印了如下内容:

确实符合上面描述的现象,用户的慢日志应该是被抑制了,汇总到了359里面去。我们尝试将log_throttle_queries_not_using_indexes设置为0,再执行对应的SQL语句,果然在日志文件中记录了相应的SQL语句。这个线上问题似乎已经定位到了,就是系统产生的不走索引的慢日志太多,而设置的log_throttle_queries_not_using_indexes太小,导致无法正常记录用户未走索引的慢日志。但还有一个疑惑点没有解决,那就是log_throttle_queries_not_using_indexes为0时,每分钟并没有打印超过10条慢日志,更没有throttle提示的359条这么多,那么设置为10的时候用户提供的那条SQL语句应该被记录到慢日志中才对啊,为何没有记录,原因何在?其实,仔细看下MySQL记录不走索引的日志的代码逻辑可以找到答案:

上图是记录慢日志的主逻辑,是否记录日志由函数log_slow_applicable控制,该函数先前已分析了一部分,我们进一步看该函数的其他相关内容,见下图红框:

suppress_logging是个决定性的变量,只有它为false,该SQL语句才可能被记录。其结果就跟log_throttle_queries_not_using_indexes相关,我们进一步看下log_throttle_qni.log相关实现,如下图:

eligible即为warn_no_index,inc_log_count()函数在1分钟内不走索引的语句总数超过log_throttle_queries_not_using_indexes时返回值为true,只有warn_no_index和inc_log_count()返回值都为true,suppress_current才为true,而suppress_current即为suppress_logging。

通过对上述2个截图内容进行分析,可以解答之前的疑惑点:log_throttle_queries_not_using_indexes统计的是所有不走索引的语句,其中有些语句因为不满足扫描记录数的约束而不会记录到慢日志中,这就是为什么该值为10的时候,慢日志文件中并没有10条记录。因为这10条中有8条SQL语句由于扫描记录数太少并没有被记录。

这也解惑了上图中359这个数字,它这个时间窗内不走索引的SQL语句总数。所以,log_throttle_queries_not_using_indexes是个很关键的参数,设置不当会无法正常记录不走索引的慢查询,导致慢日志功能部分失效。

InnoSQL慢日志功能增强

还有部分RDS实例用户问我们,为什么我的SQL语句执行时间没有超过所设置的long_query_time,而且走了索引,但还是被记录到慢日志中,是不是出Bug了?其实这不是Bug,而是因为网易云RDS使用的InnoSQL(网易维护的MySQL开源分支)版本对慢日志做了优化,除了考察SQL语句的执行时间外,还关注该查询所需的磁盘页面(Disk Page)数,因为所需的页面数目过多,也可能会对系统负载造成较大影响。为了能够量化统计,我们收集了SQL查询所需读取的总页面数和这些页面中实际进行IO的次数,分别记录为logical_reads和physical_reads,前者包括命中InnoDB Buffer Pool和未命中需要进行IO的页面请求。通过引入slow_query_type和long_query_io两个参数为用户提供该功能。前者可设置为0/1/2/3。1表示启用基于执行时间来记录慢日志,2表示基于搜索总页面数来记录慢日志,3是1和2的合集。所以在InnoSQL中,SQL查询只需满足执行时间够长或所需总页面数够多即可记录到慢日志中。代码实现片段如下:

页面数阈值通过long_query_io参数来衡量,用户可动态设置,如果总页面数m_logical_reads超过了该值,即使执行时间未超标,也会被记录。相应的,RDS实例慢日志表结构和慢日志文件输出内容也增加了新的字段。

上图即为InnoSQL版的slow_log表结构,其中,logical_reads和physical_reads为InnoSQL增加字段。同样的,慢日志文件的输出内容也增加了两个字段,如下所示:

除了以上详细描述的内容外,MySQL慢日志模块还有如下几个特性值得关注:

  1. 进行慢日志统计及慢日志中所记录的时间并不包括该SQL语句开始执行前获取锁所需等待的时间;
  2. MySQL在SQL语句执行完且所持有的锁均已释放后才将其写入慢日志中,所以慢日志中的SQL语句记录顺序并不能准确反映这些SQL语句的实际执行顺序;
  3. 每条慢日志都包含一个时间戳,若写入文件中,log_timestamps 参数用于将慢日志时间戳转化为指定时区的时间。但该参数对于mysql.slow_log表中的慢日志不起作用;
  4. 可通过设置log_slow_slave_statements来开启MySQL从库的慢日志功能;ALTER TABLE, ANALYZE TABLE, CHECK TABLE, CREATE INDEX, DROP INDEX, OPTIMIZE TABLE, and REPAIR TABLE等表管理操作也能够被记录到慢日志中,可通过log_slow_admin_statements选项开启。

了解 网易云 :
网易云官网:https://www.163yun.com/
新用户大礼包:https://www.163yun.com/gift
网易云社区:https://sq.163yun.com/

MySQL慢日志功能分析及优化增强的更多相关文章

  1. 查看mysql慢日志,进行优化

    MySQL 慢查询的相关参数解释:slow_query_log :是否开启慢查询日志,1表示开启,0表示关闭. slow_query_log    :是否开启慢查询日志,1表示开启,0表示关闭. lo ...

  2. MySQL慢日志线上问题分析及功能优化

    本文来源于数据库内核专栏. MySQL慢日志(slow log)是MySQL DBA及其他开发.运维人员需经常关注的一类信息.使用慢日志可找出执行时间较长或未走索引等SQL语句,为进行系统调优提供依据 ...

  3. MySQL binlog日志优化

    mysql中日志类型有慢查询日志,二进制日志,错误日志,默认情况下,系统只打开错误日志,因为开启日志会产生较大的IO性能消耗.   一般情况下,生成系统中很少打开二进制日志(bin log),bin ...

  4. MySQL慢日志优化

    慢日志的性能问题 造成 I/O 和 CPU 资源消耗:慢日志通常会扫描大量非目的的数据,自然就会造成 I/O 和 CPU 的资源消耗,影响到其他业务的正常使用,有可能因为单个慢 SQL 就能拖慢整个数 ...

  5. mysql笔记03 查询性能优化

    查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...

  6. Mysql Binlog日志详解

    一.Mysql Binlog格式介绍       Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...

  7. MySQL慢日志查询全解析:从参数、配置到分析工具【转】

    转自: MySQL慢日志查询全解析:从参数.配置到分析工具 - MySQL - DBAplus社群——围绕数据库.大数据.PaaS云,运维圈最专注围绕“数据”的学习交流和专业社群http://dbap ...

  8. ELK 构建 MySQL 慢日志收集平台详解

    ELK 介绍 ELK 最早是 Elasticsearch(以下简称ES).Logstash.Kibana 三款开源软件的简称,三款软件后来被同一公司收购,并加入了Xpark.Beats等组件,改名为E ...

  9. 关于MySQL慢日志,你想知道的都在这

    关于MySQL慢日志,你想知道的都在这 https://mp.weixin.qq.com/s/Ifbq0Dk13SO3WVghqWVUbA 作者介绍邹鹏,现任职于腾讯云数据库团队,负责腾讯云数据库My ...

随机推荐

  1. java基础笔记(4)----数组

    介绍: 数组是一种数据类型,是引用类型,是一块连续的内存空间,用于存储和管理相同类型的多个数据. 定义:-- > 数组的声明方式 先声明,在开辟内存空间--> int [] a; a=ne ...

  2. Alpha冲刺No.5

    一.站立式会议 在助教帮助下,优先解决404的问题,将demo移植到自己项目上. 进一步制作界面. 将已做好的内容,移植到手机做部分测试,能够在同一路由子网内登录数据库. 二.实际项目进展 已经解决了 ...

  3. 201621123040《Java程序设计》第八周学习总结

    1.本周学习总结 2.书面作业 2.1ArrayList代码分析 2.1.1解释ArrayList的contains源代码 ArrayList.contain()方法通过调用indexOf()来判断元 ...

  4. vue中一个dom元素可以绑定多个事件?

    其实这个问题有多个解决方法的  这里提出两点 第一种 第二种 现在dom上绑定一个 然后在你的methods中直接调用 如果要传参数  这时候千万别忘记 原创 如需转载注明出处 谢谢

  5. Python内置函数(58)——input

    英文文档: input([prompt]) If the prompt argument is present, it is written to standard output without a ...

  6. Mego开发文档 - 复杂保存操作

    复杂保存操作 Mego框架还提供了更强大的数据更新API,以简化开发工作,同时也保证的性能. 指定属性添加数据 本列中指定插入一个数据对象,并且只会插入三列数据,最后两个属性是以表达式的形式插入. u ...

  7. Dojo API中文 Dojo内容模块概览,初学者

    官网:http://dojotoolkit.org/reference-guide/1.10/dojo/index.html#dojo-dojo的翻译 dojo 内容: dojo dojo/dojo ...

  8. confluence搭建详情

    Confluence安装&破解&汉化 编辑时间: 2017年7月7日18:01:13 1.介绍 Atlassian Confluence(简称Confluence)是一个专业的wiki ...

  9. sts中maven

    建立一个maven web的工程 网上有很多关于maven的下载,配置等,我这里就不多说了. 下面介绍主要介绍关于在sts中建立一个maven时最开始出现的错误问题. 创建maven工程 file-& ...

  10. Java面向对象之封装 入门实例(一)

    一.基础概念 (一)面向对象的三大特征:      1.封装         2.继承          3.多态 (二)封装:隐藏实现细节,对外提供公共的访问方式(接口). 封装的体现之一:将属性都 ...