定位执行慢的 SQL:慢查询日志

目录

一、开启慢查询日志参数

1.1 开启 slow_query_log

1.2 修改 long_query_time 阈值

二、查看慢查询数目

三、案例演示

3.1 建表

3.2 设置参数 log_bin_trust_function_creators

3.3 创建函数

3.4 创建存储过程

3.5 调用存储过程

四、测试及分析

4.1 测试

4.2 分析

五、慢查询日志分析工具:mysqldumpslow

5.1 查看mysqldumpslow的帮助信息

5.2 示例

六、关闭慢查询日志

6.1 永久性方式

6.2 临时性方式

七、删除慢查询日志


实验条件:在本机上安装了虚拟机,安装了 centos7 和 mysql8

一、开启慢查询日志参数

1.1 开启 slow_query_log

默认情况下,慢查询日志是关闭的。可以使用如下命令打开(注意设置变量值的时候需要使用 global):

mysql> set global slow_query_log='ON';
然后我们再来查看下慢查询日志是否开启,以及慢查询日志文件的位置:
你能看到这时慢查询分析已经开启,同时文件保存在 /var/lib/mysql/atguigu05 - slow.log 文件中。

1.2 修改 long_query_time 阈值

接下来我们来看下慢查询的时间阈值设置,使用如下命令:
mysql> show variables like '%long_query_time%';

这里如果我们想把时间缩短,比如设置为 1 秒,需要做两方面设置:
  • 全局设置(设置global的方式对当前sessionlong_query_time失效
mysql> set global long_query_time = 1;

  • 会话级设置
mysql> set long_query_time=1;

二、查看慢查询数目

查询当前系统中有多少条慢查询记录
mysql> SHOW GLOBAL STATUS LIKE '%Slow_queries%';

当前系统中没有慢查询。

三、案例演示

3.1 建表

CREATE TABLE `student` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`stuno` INT NOT NULL ,
`name` VARCHAR(20) DEFAULT NULL,
`age` INT(3) DEFAULT NULL,
`classId` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

3.2 设置参数 log_bin_trust_function_creators

创建函数,假如报错:

This function has none of DETERMINISTIC......

命令开启:允许创建函数设置

set global log_bin_trust_function_creators=1; # 不加global只是当前窗口有效。

3.3 创建函数

产生随机字符串:

DELIMITER //
CREATE FUNCTION rand_string(n INT)
RETURNS VARCHAR(255) #该函数会返回一个字符串
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END //
DELIMITER ;

#测试
SELECT rand_string(10);

产生随机数值:

DELIMITER //
CREATE FUNCTION rand_num (from_num INT ,to_num INT) RETURNS INT(11)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(from_num +RAND()*(to_num - from_num+1)) ;
RETURN i;
END //
DELIMITER ;

#测试:
SELECT rand_num(10,100);

3.4 创建存储过程

DELIMITER //
CREATE PROCEDURE insert_stu1( START INT , max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0; #设置手动提交事务
REPEAT #循环
SET i = i + 1; #赋值
INSERT INTO student (stuno, NAME ,age ,classId ) VALUES
((START+i),rand_string(6),rand_num(10,100),rand_num(10,1000));
UNTIL i = max_num
END REPEAT;
COMMIT; #提交事务
END //
DELIMITER ;

3.5 调用存储过程

#调用刚刚写好的函数, 4000000条记录,从100001号开始
CALL insert_stu1(100001,4000000);

四、测试及分析

4.1 测试

mysql> SELECT * FROM student WHERE stuno = 3455655;
+---------+---------+--------+------+---------+
| id      | stuno   | name   | age  | classId |
+---------+---------+--------+------+---------+
| 3355654 | 3455655 | rdrxnY |   13 |     302 |
+---------+---------+--------+------+---------+
1 row in set (2.31 sec)

mysql> SELECT * FROM student WHERE name = 'rdrxnY';
+---------+---------+--------+------+---------+
| id      | stuno   | name   | age  | classId |
+---------+---------+--------+------+---------+
|   81629 |  181630 | rDRxNy |   19 |      80 |
|  190737 |  290738 | rDRxNy |   17 |     966 |
| 1507970 | 1607971 | RDrXNY |   62 |     949 |
| 1842741 | 1942742 | rDRxNy |   13 |     808 |
| 1858203 | 1958204 | RdRXny |   62 |     483 |
| 2405348 | 2505349 | rdrxnY |   15 |     399 |
| 2430609 | 2530610 | RdRXny |   58 |     274 |
| 2806416 | 2906417 | RdRXny |   57 |     235 |
| 3126683 | 3226684 | rDRxNy |   15 |     876 |
| 3355654 | 3455655 | rdrxnY |   13 |     302 |
| 3559533 | 3659534 | RDrXNY |   61 |     933 |
| 3612590 | 3712591 | rDRxNy |   13 |     788 |
+---------+---------+--------+------+---------+
12 rows in set (2.00 sec)
从上面的结果可以看出来,查询学生编号为 “3455655” 的学生信息花费时间为 2.31 秒。查询学生姓名为 “rdrxnY”的学生信息花费时间为2.00 秒。已经达到了秒的数量级,说明目前查询效率是比较低的。

4.2 分析

查询慢查询的数量:
mysql> show status like 'slow_queries';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries  | 2     |
+---------------+-------+
1 row in set (0.02 sec)

五、慢查询日志分析工具:mysqldumpslow

在生产环境中,如果要手工分析日志,查找、分析 SQL ,显然是个体力活, MySQL 提供了日志分析工具 mysqldumpslow

5.1 查看mysqldumpslow的帮助信息

[root@atguigu05  ~]# mysqldumpslow --help
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]

Parse and summarize the MySQL slow query log. Options are

  --verbose    verbose
  --debug      debug
  --help       write this text to standard output

  -v           verbose
  -d           debug
  -s ORDER     what to sort by (al, at, ar, c, l, r, t), 'at' is default
                al: average lock time
                ar: average rows sent
                at: average query time
                 c: count
                 l: lock time
                 r: rows sent
                 t: query time  
  -r           reverse the sort order (largest last instead of first)
  -t NUM       just show the top n queries
  -a           don't abstract all numbers to N and strings to 'S'
  -n NUM       abstract numbers with at least n digits within names
  -g PATTERN   grep: only consider stmts that include this string
  -h HOSTNAME  hostname of db server for *-slow.log filename (can be wildcard),
               default is '*', i.e. match all
  -i NAME      name of server instance (if using mysql.se
mysqldumpslow 命令的具体参数如下:
  • -a: 不将数字抽象成N,字符串抽象成S
  • -s: 是表示按照何种方式排序:
    • c: 访问次数
    • l: 锁定时间
    • r: 返回记录
    • t: 查询时间
    • al:平均锁定时间
    • ar:平均返回记录数
    • at:平均查询时间 (默认方式)
    • ac:平均查询次数
  • -t: 即为返回前面多少条的数据;
  • -g: 后边搭配一个正则匹配模式,大小写不敏感的;

5.2 示例

举例:我们想要按照查询时间排序,查看前五条 SQL 语句,这样写即可:
[root@atguigu05  ~]# mysqldumpslow -s t -t 5 /var/lib/mysql/atguigu05?-slow.log

Reading mysql slow query log from /var/lib/mysql/atguigu05      -slow.log
Count: 1  Time=1059.37s (1059s)  Lock=0.00s (0s)  Rows=0.0 (0), root[root]@[192.168.44.1]
  /* ApplicationName=DBeaver N.N.N - SQLEditor <Script-N.sql> */ CALL insert_stu1(N,N)

Count: 1  Time=2.31s (2s)  Lock=0.00s (0s)  Rows=1.0 (1), root[root]@localhost
  SELECT * FROM student WHERE stuno = N

Count: 1  Time=2.00s (1s)  Lock=0.00s (0s)  Rows=12.0 (12), root[root]@localhost
  SELECT * FROM student WHERE name = 'S'

Count: 1  Time=1.11s (1s)  Lock=0.14s (0s)  Rows=1.0 (1), root[root]@[192.168.44.1]
  /* ApplicationName=DBeaver N.N.N - SQLEditor <Script-N.sql> */ SELECT COUNT(N) from student s 
  LIMIT N, N

Died at /usr/bin/mysqldumpslow line 162, <> chunk 4.

六、关闭慢查询日志

MySQL 服务器停止慢查询日志功能有两种方法:

6.1 永久性方式

[mysqld]
slow_query_log=OFF
或者,把 slow_query_log 一项注释掉 或 删除
[mysqld]
#slow_query_log =OFF
重启 MySQL 服务,执行如下语句查询慢日志功能。
SHOW VARIABLES LIKE '%slow%'; #查询慢查询日志所在目录
SHOW VARIABLES LIKE '%long_query_time%'; #查询超时时长

6.2 临时性方式

停止 MySQL 慢查询日志功能,具体 SQL 语句如下:
SET GLOBAL slow_query_log=off;
使用 SHOW 语句查询慢查询日志功能信息,具体 SQL 语句如下:
SHOW VARIABLES LIKE '%slow%';
#以及
SHOW VARIABLES LIKE '%long_query_time%';

重启MySQL服务,慢查询的时间阈值重置为系统默认值(10秒):

七、删除慢查询日志

慢查询日志的目录默认为MySQL的数据目录,在该目录下手动删除慢查询日子文件即可。

使用命令 mysqladmin flushlogs 来重新生成查询日志文件,具体命令如下:

mysqladmin -uroot -p flush-logs slow

提示:慢查询日志都是用 mysqladmin flushlogs 命令来删除重建的。一旦执行了此命令,慢查询日志都只存在新的日志文件中,如果需要旧的查询日志,旧必须事先备份。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值