
在MySQL数据库中,慢SL慢慢查想了解数据库运行情况的探秘重要指标之一是慢SQL。而并非如某些人所说的为志里所有运行慢的SQL都会被记录在慢SQL日志(或日志表)里,抑或是却没没有慢SQL就代表没有运行慢的SQL。本文将总结一些比较常见的记录运行比较慢但不会被记录在慢SQL日志里的情况。另外,询日慢SQL的慢SL慢慢查计算方式在MySQL8.0新版本中有变化,因此,探秘将通过对比MySQL5.7(MySQL5.7.38)与MySQL8.0(MySQL8.0.33)进行总结。为志里 1. 准备工作部署了两套环境,却没分别是记录MySQL5.7(MySQL5.7.38)版本及MySQL8.0(MySQL8.0.33)版本。另外为了后续进行慢SQL测试,询日此时先创建一张测试表并清空慢SQL日志表。慢SL慢慢查 (1)创建测试表及数据 创建测试表及测试数据,探秘便于后续测试。为志里本次通过创建一张1000W记录的表进行测试。 然后再添加个字段。 复制mysql> call sp_createNum(10000000); Query OK, 1611392 rows affected (38.70 sec) mysql> select count(*) from testdb.nums; +----------+ | count(*) | +----------+ | 10000000 | +----------+ 1 row in set (3.70 sec) mysql> alter table testdb.nums add c1 varchar(20); Query OK, 0 rows affected (17.83 sec) Records: 0 Duplicates: 0 Warnings: 01.2.3.4.5.6.7.8.9.10.11.12. (2)清空慢SQL日志表 测试前先清空慢SQL日志表mysql.slow_log,清空方法如下: 复制mysql> select count(*) from mysql.slow_log; +----------+ | count(*) | +----------+ | 2 | +----------+ 1 row in set (0.00 sec) # 需先关闭慢SQL监控开关 mysql> set global slow_query_log=0; Query OK, 0 rows affected (0.00 sec) # truncate 方式清空慢SQL日志表 mysql> truncate table mysql.slow_log; Query OK, 0 rows affected (0.00 sec) mysql> select count(*) from mysql.slow_log; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec) # 清理完毕后开启慢SQL监控 mysql> set global slow_query_log=1; Query OK, 0 rows affected (0.00 sec)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23. 2. 未开启慢SQL监控查看MySQL是否开启MySQL的方法如下: 复制mysql> SHOW GLOBAL VARIABLES LIKE slow_query_log; +----------------+-------+ | Variable_name | Value | +----------------+-------+ | slow_query_log | ON | +----------------+-------+ 1 row in set (0.00 sec)1.2.3.4.5.6.7. 其中value值为ON (或1),则代表开启了慢SQL监控。MySQL各个版本查看的服务器托管方法均一样。 
另外和慢SQL相关的其他主要参数如下: slow_query_log: 这个参数用于启用或禁用慢SQL监控。设置为1表示启用,0表示禁用。默认值为0(禁用)。log_output:日志存储方式(不仅仅是慢SQL日志),默认值为FILE。当log_output=FILE表示将日志存入文件;当log_output=TABLE表示将日志存入数据库中的mysql.slow_log表里;当log_output=FILE,TABLE表示既存储到日志文件又存储到mysql.slow_log表里。slow_query_log_file: 慢SQL日志文件的路径和文件名(5.5等低版本参数为log_slow_queries)。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log。long_query_time: 用于定义慢SQL的阈值时间,单位为秒。执行时间超过该阈值的SQL语句将被记录到慢SQL日志中。默认值为10秒。log_queries_not_using_indexes:如果设置为1,则将未使用索引的查询也记录到慢查询日志中。默认值为0(禁用)。log_slow_admin_statements: 如果设置为1,则会记录部分管理命令(例如ALTER TABLE)到慢SQL日志中。默认值为0(禁用),本文后续也会继续演示介绍。log_slow_extra: 如果设置为1,则除了慢SQL日志的标准输出之外,还将在日志中包括额外的源码下载信息,如用户、主机、客户端命令等。默认值为0(禁用)。log_slow_slave_statements: 如果设置为1,则将从服务器执行的慢SQL记录到主服务器的慢SQL日志中。默认值为0(禁用)。min_examined_row_limit: 仅在查询的行数超过指定值时,才记录到慢SQL日志中。默认值为0,表示不限制。 3. SQL运行时间小于慢SQL监控阈值时间第一部分已经介绍了和慢SQL相关的参数中的long_query_time,即慢SQL阈值。所以,当SQL运行时间小于该阈值时,对于的SQL将不会记录在慢SQL日志中。查看和修改慢SQL监控阈值的方法如下: 复制# 查看慢SQL阈值 mysql> SHOW GLOBAL VARIABLES LIKE long_query_time; +-----------------+----------+ | Variable_name | Value | +-----------------+----------+ | long_query_time | 0.500000 | +-----------------+----------+ 1 row in set (0.00 sec) # 设置慢SQL阈值 mysql> set global long_query_time=0.6; Query OK, 0 rows affected (0.00 sec) # 设置完成后可以查看全局的阈值 mysql> SHOW GLOBAL VARIABLES LIKE long_query_time; +-----------------+----------+ | Variable_name | Value | +-----------------+----------+ | long_query_time | 0.600000 | +-----------------+----------+ 1 row in set (0.01 sec) # 但是当前会话的慢SQL阈值是没变的,这个同其他包含全局和会话级的参数类似 mysql> SHOW VARIABLES LIKE long_query_time; +-----------------+----------+ | Variable_name | Value | +-----------------+----------+ | long_query_time | 0.500000 | +-----------------+----------+ 1 row in set (0.00 sec)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27. 
注:对于不同的数据库需按照实际情况设置慢SQL监控的亿华云阈值,例如TP业务的实例且配置相对较好时,建议阈值设置的较低;如果是AP类型业务,则适当放宽慢SQL的阈值。 4. 锁等待或事务等待的SQL开启2个事务,然后模拟锁等待情况。 (1)MySQL5.7 中测试 首先测试MySQL5.7版本的情况: 事务1 事务2 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2024-03-24 20:40:47 | +---------------------+ 1 row in set (0.00 sec) mysql> update testdb.nums set c1=id where id<=5; Query OK, 5 rows affected (7.85 sec) Rows matched: 5 Changed: 5 Warnings: 0 mysql> select now(); +---------------------+ | now() | +---------------------+ | 2024-03-24 20:41:07 | +---------------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2024-03-24 20:41:20 | +---------------------+ 1 row in set (0.00 sec) mysql> update testdb.nums set c1=id where id<3; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select now(); +---------------------+ | now() | +---------------------+ | 2024-03-24 20:42:55 | +---------------------+ 1 row in set (0.00 sec) mysql> select * from mysql.slow_log\G |