MySQL高级篇——聊聊MySQL的慢查询日志

Posted 张起灵-小哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL高级篇——聊聊MySQL的慢查询日志相关的知识,希望对你有一定的参考价值。

文章目录:

1.数据库服务器的优化步骤

2.查看系统性能参数

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

4.查看 SQL 执行成本:SHOW PROFILE


1.数据库服务器的优化步骤

当我们遇到数据库调优问题的时候,该如何思考呢?这里把思考的流程整理成下面这张图。 整个流程划分成了 观察( Show status 行动( Action 两个部分。字母 S 的部分代表观察(会使 用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。


2.查看系统性能参数

mysql 中,可以使用 SHOW STATUS 语句查询一些 MySQL 数据库服务器的 性能参数 执行频率 SHOW STATUS 语句语法如下:
SHOW [GLOBAL|SESSION] STATUS LIKE '参数';
一些常用的性能参数如下: • Connections :连接 MySQL 服务器的次数。 • Uptime MySQL 服务器的上 线时间。 • Slow_queries :慢查询的次数。 • Innodb_rows_read Select 查询返回的行数 Innodb_rows_inserted :执行 INSERT 操作插入的行数 • Innodb_rows_updated :执行 UPDATE 操作更新的 行数 • Innodb_rows_deleted :执行 DELETE 操作删除的行数 • Com_select :查询操作的次数。 Com_insert :插入操作的次数。对于批量插入的 INSERT 操作,只累加一次。 • Com_update :更新操作 的次数。 • Com_delete :删除操作的次数。

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

开启slow_query_log

然后我们再来查看下慢查询日志是否开启,以及慢查询日志文件的位置:

你能看到这时慢查询分析已经开启,同时文件保存在 /var/lib/mysql/atguigu02 - slow.log 文件 中。

修改 long_query_time 阈值 接下来我们来看下慢查询的时间阈值设置,使用如下命令: 这里如果我们想把时间缩短,比如设置为 0.5

查看慢查询数目

下面,我们做一个简单的案例演示:首先会有一些建表语句、存储过程、存储函数。 (向表中添加了四百万条数据,时间会有点长。。。)

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;

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 ;

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 ;

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 ;

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

SELECT COUNT(*) FROM student;

表和数据都准备就绪之后,下面我们来测试。

这两条sql的执行时间都超过了我们自定义的long_query_time阈值,所以我们就可以查看慢查询数目

慢查询日志分析工具:mysqldumpslow

在生产环境中,如果要手工分析日志,查找、分析 SQL ,显然是个体力活, MySQL 提供了日志分析工具 mysqldumpslow 查看 mysqldumpslow 的帮助信息
mysqldumpslow --help
mysqldumpslow 命令的具体参数如下: -a: 不将数字抽象成 N ,字符串抽象成 S -s: 是表示按照何种方式排序: c: 访问次数 l: 锁定时间 r: 返回记录 t: 查询时间 al: 平均锁定时间 ar: 平均返回记录数 at: 平均查询时间 (默认方式) ac: 平均查询次数 -t: 即为返回前面多少条的数据; -g: 后边搭配一个正则匹配模式,大小写不敏感的; 对刚才的案例进行分析:(这里可以看到慢查询日志已经记录下了刚刚我们执行的两次超过0.5s的sql)
#得到返回记录集最多的10个SQL 
mysqldumpslow -s r -t 10 /var/lib/mysql/localhost-slow.log 

#得到访问次数最多的10个SQL 
mysqldumpslow -s c -t 10 /var/lib/mysql/localhost-slow.log 

#得到按照时间排序的前10条里面含有左连接的查询语句 
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/localhost-slow.log 

#另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况 
mysqldumpslow -s r -t 10 /var/lib/mysql/localhost-slow.log | more

因为我们如何不调优了话,最好还是不要开启慢查询日志,因为开启之后也会影响一定的性能。

所以下面来说一下 关闭慢查询日志。

方式一:永久性关闭,或者,把slow_query_log一项注释掉 或 删除。  操作之后记得重启mysql服务

[mysqld] 
slow_query_log=OFF 

[mysqld] 
#slow_query_log =OFF

方式二:临时性关闭。这里先对slow_query_log参数做一个修改。然后重启mysql服务,long_query_time这个参数就会重置为最初的10s。

删除慢查询日志


4.查看 SQL 执行成本:SHOW PROFILE

下面我们执行两条sql。

然后,我们再次通过show profiles命令查看。

 

以上是关于MySQL高级篇——聊聊MySQL的慢查询日志的主要内容,如果未能解决你的问题,请参考以下文章

「MySQL高级篇」MySQL日志事务原理 -- undologredologbinlog两阶段提交

MySQL高级篇 - 性能优化

mysql案例系列 ~ 奇怪的慢日志问题

MySQL高级 之 查询日志分析

MySQL 的慢查询日志

学会读懂 MySql 的慢查询日志