MySQL慢日志体系建设

概述

为啥我的数据库慢的和蜗牛一样?

天呢,我的应用好多查询报超时了,什么情况?

好烦,数据库QPS总是上不来,根本扛不住,怎么办呀?

DBA刚刚又找过来了,说我的SQL查询把数据库打挂了,怎么又是我?

或者这些都是万恶的慢SQL造成的。

说到这里,您会认为我应该介绍下SQL该怎么优化的,让您失望了,接下来我将介绍58同城MySQL慢日志是怎么收集统计的;作为DBA,我想在第一时间让您知道:是的,就是您的锅!

MySQL 慢日志介绍

默认情况下,慢查询日志是关闭的,可以通过参数slow_query_log[={0|1}]指定,设置为 1 就是启用慢日志的功能了,参数long_query_time控制着超过多少秒的查询会被记录下来,通过参数log_queries_not_using_indexes也可以将没有使用索引的查询也记录下来,而参数log_output控制着将慢日志保存在文件还是表中。官方文档慢查询日志

下面的设置来自于线上配置

慢日志收集已经打开
(root@(none))>show global variables like 'slow_query_log';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | ON    |
+----------------+-------+
1 row in set (0.00 sec)
慢日志被写入到文件中
(root@(none))>show global variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | FILE  |
+---------------+-------+
1 row in set (0.00 sec)
只要超过0.1s的查询会被记录到慢日志文件中
(root@(none))>show global variables like 'long_query_time';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 0.100000 |
+-----------------+----------+
1 row in set (0.00 sec)
慢日志的文件名为slow.log,如果没有指定绝对路径,默认路径为DATADIR
(root@(none))>show global variables like 'slow_query_log_file';
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| slow_query_log_file | slow.log |
+---------------------+----------+
1 row in set (0.01 sec)

收集慢日志

怎么收集慢日志呢,要么使用第三方开源工具,要么自己开发组件。

开源工具较为流行有pt-query-digest,mysqldumpslow, mysqlsla, myprofi, mysql-explain-slow-log, mysqllogfilter等,其中pt-query-digest较为流行,这些工具配合自动化脚本,适合按照一定的时间间隔收集归档慢日志,并生成慢日志报表,若实现实时展示慢sql则较为困难,因此我们采用了自己开发的组件,组件主要实现:

  • 具有pt-query-digest的分析统计归档慢日志的功能,

  • 具备实时展示慢sql的能力

我们使用的MySQL版本包括percona MySQL的5.5和5.6,以及MySQL社区版5.7和8.0,虽然来自于两家公司,版本跨度较大,但是慢日志格式差异不明显,例如每条慢sql都包括以下内容:
在这里插入图片描述
如果采用特定标识符切割,产生一条条完整的慢日志block(例如上图,就是一条block);然后按照一定的规则将其中有用的信息抽取出来,再将sql语句指纹化,即对where变量做“?”替换生成唯一校验值,就完成慢日志的初步处理。

为了能准实时性查看慢日志详情,我们需要实时解析慢sql,需要解决以下问题:

  • 如果用python实现,使用生成器也能完成对单个文件的快速处理,但是python的效率确实让人怀疑;
  • 为了控制慢日志文件大小,每天要对慢日志文件进行切割,那么怎么发现新的慢日志文件呢?
  • 如果解析工具中间出现故障,重启后会不会重复消费呢?

filebeat是用go开发的轻量级的文件处理工具,filebeat可以按照“# User@Host”切割慢日志文件为block到下游;且能按照一定规则发现新产生的慢日志文件,并能实时记录慢日志解析的位置。因此我们最终解析流程见下图:

在这里插入图片描述
组件说明:

  • Kafka作为中间消息队列,起到削峰填谷的效果;

  • 消费Kafka组件:为自研组件,主要目的是抽取block有用信息,例如:用户、来源ip、库、时间戳、sql语句等,并将sql语句指纹化;

  • Elasticsearch:ES可以作为强大的搜索引擎,可以对sql语句按照不同的维度进行分桶统计分析;

生成慢sql报表和实时统计

Fileabeat按照“# User@Host”将慢日志文件切割为block,消费Kafka组件再抽取每个block中有用的信息,并最终作为独立的term存储到ES当中,下图是慢日志mapping详情:

"mappings" : {
      "_doc" : {
        "properties" : {
          "@timestamp" : {
            "type" : "date",
            "format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
          },
          "checksum" : {
            "type" : "keyword"
          },
          "host" : {
            "type" : "keyword",
            "ignore_above" : 256
          },
          "ip" : {
            "type" : "keyword",
            "ignore_above" : 256
          },
          "lock_time" : {
            "type" : "float"
          },
          "port" : {
            "type" : "long"
          },
          "query_time" : {
            "type" : "float"
          },
          "rows_examined" : {
            "type" : "long"
          },
          "rows_sent" : {
            "type" : "long"
          },
          "schema" : {
            "type" : "keyword",
            "ignore_above" : 256
          },
          "sql" : {
            "type" : "text"
          },
          "sql_fingerprint" : {
            "type" : "text"
          },
          "status" : {
            "type" : "long"
          },
          "user" : {
            "type" : "keyword",
            "ignore_above" : 256
          }
        }
      }
    }

下图为解析的单条慢sql详情:

在这里插入图片描述
字段说明:

  • Time:为慢日志文件的时间戳,转化为ES的data格式
  • user:为应用用户,即发起请求的用户
  • ip:为应用ip,即发起请求的来源机器
  • port:该MySQL实例的端口
  • lock_time: 加锁时间
  • query_time: 查询时间,这个时间可不包括锁等待的时间哦
  • rows_examined:慢sql扫描的行数,本实例展示扫描了10000行
  • Rows_sent:发送到客户端的行数,本示例展示发送了10000行
  • schema:库名,查询的库名,实际大部分慢日志文件是不带有名的,我们只能通过其他方式解决
  • sql:原始sql语句
  • sql_fingerprint:sql指纹后生成的sql语句,这个主要用于生成checksum
  • checksum:指纹化相同的sql会生成一样的校验值,这个是分桶统计的依据,非常非常的重要

基础数据已经准备妥当,是时候展示我们的成果了。
在这里插入图片描述

目前我们通过ES检索分析衍生出两个产品:

  • 慢sql报表
  • 实时慢sql

慢sql报表

慢sql报表功能在58一直都存在,而且前人做的真的不错;但是使用的是pt-query-digest工具,在改造的过程发现优化空间不大,并最终弃用了。

报表是按照天生成的,并且是T+1的,实时性要求不高,所以可以按照不同维度做很多功能。例如:每个集群慢sql数量趋势图、每天慢sql详情及生成优化建议、每日新增慢sql等,个人负责集群慢sql整体趋势、邮件提醒等,按照不同业务线等级统计慢sql个数、部门之间的对比等。报表功能做的很多,下图只是简单展示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oZlszdA-1648459157800)(/Users/liuhansheng/Library/Application Support/typora-user-images/image-20220328161424383.png)]
您负责的业务或许很多,关心的数据库也很多,我们在CDB工作台为您提供了慢SQL总量趋势,当然了您也可以对慢SQL严重的库进行优化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M714K8N6-1648459157801)(/Users/liuhansheng/Library/Application Support/typora-user-images/image-20220328161517084.png)]

  • 单个集群我们为您提供了一年的慢SQL变化趋势;当然,您也可以重点关注某一天的慢SQL详情
  • 或许您只关心具体的某一条sql,例如执行次数,执行时间等,您也可以根据具体情况并结合优化建议进行优化

实时慢sql

实时慢sql充分发挥了ES实时检索分析能力,下图为实时汇总统计,重点部分已经用数字进行了标记

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WnkMlEfD-1648459157801)(/Users/liuhansheng/Library/Application Support/typora-user-images/image-20220328161739607.png)]

  • 您可以按照数据库域名、来源IP、库名、用户名或者SQL编号进行快速检索,我们不仅展示正确的,更给你最需要的;
  • 您也可以按照不同的时间间隔进行筛选,例如最近15min、最近一周等;或者任意时间间隔,例如:23:21:21-23:22:45,秒级也是支持的哦
  • 条形图为您展示了在您选择的时间范围内慢SQL条数的变化情况,那高高立起的小柱,可能就是一次严重的慢sql堆积,赶快点击小柱看看吧
  • 分析统计表为您展示详细的内容,这个表是通过来源IP和SQL编号分组,并按照执行次数从高到底排序
  • 我们也为您提供了复制该条SQL的功能,后期我们会把生成的SQL优化建议也会放在这里,敬请期待

有时间您可能就想知道在某个时间点具体发生了什么慢查询,即SQL流水,实时慢SQL也提供了这方面的功能,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DZKTCRKN-1648459157801)(/Users/liuhansheng/Library/Application Support/typora-user-images/image-20220328162430033.png)]

结语:

为了缩减开发时间,我们也使用了部分开愿工具,例如生成sql指纹的sql-calculator和生成sql优化建议的soar等。

另外还有个小问题,由于慢日志文件很多sql没有库名,我们采用了层级上推的方式,查找库名的流程为:单条block-多条block-单个慢日志文件-多个慢日志文件-多个实例满日志文件-手工补录。一般通过多个慢日志文件就能找到库名了,还没有到手工补录的阶段,一旦某个慢sql指纹语与库名绑定,这个映射关系将会固化,下次就不用这么麻烦的查找了。

慢日志体系建设还有很多可以做,例如实时生成sql优化建议、实时解读执行计划,并配合报警将慢sql实时推送相关负责同学等。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值