MySQL慢查询监控
MySQL提供了慢查询日志来记录执行时间超过long_query_time设置的查询,可用于查找执行时间过长的查询,方便优化工作。
试验环境
操作系统:CentOS Linux release 7.3.1611 (Core)
数据库系统: mysql 8.0.15
相关参数
- slow_query_log:0表示禁用日志,1表示启用日志
- slow_query_log_file:指定日志文件的保存路径和名称
- long_query_time:指定多少秒返回查询为慢查询,可精确到微秒
- log_slow_admin_statements:表示记录administrative语句,如alter table,analyze table等
- log_queries_not_using_indexes:表示记录所有未使用索引的查询
- log_throttle_queries_not_using_indexes:指定每分钟记录到日志的未使用索引查询的数量,超过此数量的只记录语句数量和花费总时间
- log_slow_slave_statements:表示记录从裤上的慢查询
- min_examined_row_limit:表示查询的行数少于此数的查询不会记录到日志
- log_timestamps:表示慢日志的时间戳的时区
- log_output:表示日志的输出格式,可以是TABLE, FILE, and NONE,默认为FILE
慢日志判定
服务器按以下顺序使用控制参数来确定是否将查询写入慢查询日志:
- 检查查询是否为管理语句,如果是则必须启用 log_slow_admin_statements 。
- 查询时常需要超过 long_query_time的配置,或者启用了 log_queries_not_using_indexes ,并且查询未使用索引。
- 如设定了min_examined_row_limit,则查询必须至少检查过指定数量的行数。
- 如设置了log_throttle_queries_not_using_indexes,则未使用索引查询数量必须小于其设定值。
另外:
默认情况下,复制从属服务器不会将复制查询写入慢速查询日志。要更改此设置,需要启用 log_slow_slave_statements 系统变量。
慢查询日志启用实验
查看原始状态:
慢查询日志默认为关闭状态:
mysql> show variables like 'slow_query%';
+---------------------+-----------------------------------+
| Variable_name | Value |
+---------------------+-----------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/localhost-slow.log |
+---------------------+-----------------------------------+
2 rows in set (0.01 sec)
long_query_time默认为10秒:
mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)
1.使用全局变量设置
设置开启慢查询:
mysql> set global slow_query_log='ON';
Query OK, 0 rows affected (0.01 sec)
设置超过1秒就记录日志
mysql> set global long_query_time=1;
Query OK, 0 rows affected (0.00 sec)
2.使用配置文件设置
修改my.cnf文件,加入相关配置:
[root@localhost ~]# vim /etc/my.cnf
slow_query_log = ON
slow_query_log_file = /var/lib/mysql/localhost-slow.log
long_query_time = 1
然后重启mysqld服务:
[root@localhost ~]# systemctl restart mysqld
查询慢查询日志
首先向慢查询日志写入数据,我设定的long_query_time是1秒,所以用sleep函数即可:
mysql> select sleep(2);
mysql> select sleep(3);
mysql> select sleep(4);
查看生成的慢查询日志:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
/usr/sbin/mysqld, Version: 8.0.15 (MySQL Community Server - GPL). started with:
Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 2019-02-26T18:08:33.711341Z
# User@Host: root[root] @ localhost [] Id: 8
# Query_time: 2.000805 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1551204511;
select sleep(2);
# Time: 2019-02-26T20:27:53.737128Z
# User@Host: root[root] @ localhost [] Id: 9
# Query_time: 3.000576 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1551212870;
select sleep(3);
# Time: 2019-02-26T20:27:59.466613Z
# User@Host: root[root] @ localhost [] Id: 9
# Query_time: 4.000169 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0
SET timestamp=1551212875;
select sleep(4);
关键参数如下:
- Query_time:语句执行时间
- Lock_time:锁等待时间
- Rows_sent:发送到客户端的行数
- Rows_examined:优化器检查的行数
这么观察日志格式有点混乱,下面说一下慢日志查询工具:
1.mysqldumpslow
mysqldumpslow是mysql自带的慢日志查询工具:
[root@localhost ~]# mysqldumpslow /var/lib/mysql/localhost-slow.log
Reading mysql slow query log from /var/lib/mysql/localhost-slow.log
Count: 3 Time=3.00s (9s) Lock=0.00s (0s) Rows=1.0 (3), root[root]@localhost
select sleep(N)
他只会输出统计后的结果,但不方便阅读分析。
-query-digest
pt-query-digest是percona-toolkit的一个工具,需要手动安装:
下载地址:percona-toolkit-3.0.13-1.el7.x86_64.rpm
yum install perl-CPAN perl-Time-HiRes perl-DBI perl-DBD-MySQL perl-IO-Socket-SSL
yum install https://www.percona.com/downloads/percona-toolkit/3.0.13/binary/redhat/7/x86_64/percona-toolkit-3.0.13-1.el7.x86_64.rpm
使用pt-query-digest命令查看慢日志:
[root@localhost ~]# pt-query-digest /var/lib/mysql/localhost-slow.log
290ms user time, 10ms system time, 25.64M rss, 219.75M vsz
Current date: Wed Feb 27 05:11:53 2019
Hostname: localhost.localdomain
Files: /var/lib/mysql/localhost-slow.log
Overall: 3 total, 1 unique, 0.00 QPS, 0.00x concurrency ________________
Time range: 2019-02-26T18:08:33 to 2019-02-26T20:27:59
Attribute total min max avg 95% stddev median
============ ======= ======= ======= ======= ======= ======= =======
Exec time 9s 2s 4s 3s 4s 786ms 3s
Lock time 0 0 0 0 0 0 0
Rows sent 3 1 1 1 1 0 1
Rows examine 0 0 0 0 0 0 0
Query size 45 15 15 15 15 0 15
总统计表中:
- Overall total 总共有多少条查询
- unique 查询数量,即对查询条件进行参数化以后,总共有多少不同查询
- QPS 每秒查询次数
- concurrency 近似并发数
- Time range 查询执行的时间范围
- total 总计
- min 最小
- max 最大
- avg 平均
- 95% 把所有值从小到大排列,位置位于95%的那个数,一般最具有参考价值
- stddev 标准差
- median 中位数
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================================== ============= ===== ====== ===== =====
# 1 0x59A74D08D407B5EDF9A57DD5A41825CA 9.0015 100.0% 3 3.0005 0.21 SELECT
事件信息表中:
- Rank 本次查询分析中的查询序号
- Query ID 查询的号
- Response time 总的响应时间,以及该查询在本次分析中总共占用的时间百分比
- Calls 查询执行次数
- R/Call 平均每次执行的响应时间
- V/M 响应时间变化的平均比值
- Item 查询语句的起始内容
# Query 1: 0.00 QPS, 0.00x concurrency, ID 0x59A74D08D407B5EDF9A57DD5A41825CA at byte 764
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.21
# Time range: 2019-02-26T18:08:33 to 2019-02-26T20:27:59
- Query 查询的序号
- QPS 每秒的查询次数
- ID 查询ID,查询在数据库中的校验码的十六进制值
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 100 3
# Exec time 100 9s 2s 4s 3s 4s 786ms 3s
# Lock time 0 0 0 0 0 0 0 0
# Rows sent 100 3 1 1 1 1 0 1
# Rows examine 0 0 0 0 0 0 0 0
# Query size 100 45 15 15 15 15 0 15
- Exec time 执行时间
- Lock time 锁等待时间
- Rows sent 行提交数
- Rows examine 行分析优化数
- Query size 查询语句大小
# String:
# Hosts localhost
# Users root
- Hosts host
- Users 用户
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s ################################################################
# 10s+
查询时间分布图,通过长短区间占比直观展示查询耗时分布
# EXPLAIN /*!50100 PARTITIONS*/
select sleep(4)\G
相关涉及表信息