理解mysql的slow log

本文详细解析了MySQL慢查询日志的各个方面,包括log_output参数的设置,start_time字段的含义,log_queries_not_using_indexes如何影响记录,以及如何配置log_throttle_queries_not_using_indexes限制记录数量。此外,还探讨了min_examined_row_limit参数的作用,以及long_query_time、lock_time在慢查询记录中的体现。最后提到了log_slow_slave_statements参数对从库记录主库慢查询的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PS:所有的前提,慢查询时间设置为3s

1 log_output参数为TABLE时,慢查询记录到mysql.slow_log表里,但这时这个系统表没有任何索引,我们一般可以在start_time列自行加上索引方便检索,类似这样

mysql> show create table mysql.slow_log\G
*************************** 1. row ***************************
       Table: slow_log
Create Table: CREATE TABLE `slow_log` (
  `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_host` mediumtext NOT NULL,
  `query_time` time NOT NULL,
  `lock_time` time NOT NULL,
  `rows_sent` int(11) NOT NULL,
  `rows_examined` int(11) NOT NULL,
  `db` varchar(512) NOT NULL,
  `last_insert_id` int(11) NOT NULL,
  `insert_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `sql_text` mediumtext NOT NULL,
  KEY `start_time` (`start_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Slow log'
1 row in set (0.00 sec)

2 start_time指的是SQL结束时间,而不是开始执行时间。

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2016-06-13 11:34:12 |
+---------------------+
1 row in set (0.00 sec)

mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
|         0 |
+-----------+
1 row in set (19.99 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2016-06-13 11:34:47 |
+---------------------+
1 row in set (0.00 sec)

   start_time: 2016-06-13 11:34:46
     user_host: ucloudbackup[ucloudbackup] @  [10.10.249.91]
    query_time: 00:00:20
     lock_time: 00:00:00
     rows_sent: 1
 rows_examined: 0
            db: test
last_insert_id: 0
     insert_id: 0
     server_id: 168491355
      sql_text: select sleep(20)
10 rows in set (0.00 sec)

3 log_queries_not_using_indexes为1时,会记录任何不使用索引的sql,从而无视long_query_time参数

mysql> set global log_queries_not_using_indexes=1;
Query OK, 0 rows affected (0.00 sec)

虽然是global变量,但不用重开session

mysql> select * from xx limit 1;

+------+------+
| id   | dd   |
+------+------+
|  123 | NULL |
+------+------+
1 row in set (0.00 sec)

  start_time: 2016-06-13 11:38:04
     user_host: ucloudbackup[ucloudbackup] @  [10.10.249.91]
    query_time: 00:00:00
     lock_time: 00:00:00
     rows_sent: 1
 rows_examined: 1
            db: test
last_insert_id: 0
     insert_id: 0
     server_id: 168491355
      sql_text: select * from xx limit 1
12 rows in set (0.00 sec)

4 默认情况下不会记录DDL操作,不管执行时间多长,除非将log_slow_admin_statements参数设置为1,而这个参数只在5.6.11后支持

mysql> alter table xx add column dd varchar(100);
Query OK, 8388608 rows affected (1 min 4.47 sec)
Records: 8388608  Duplicates: 0  Warnings: 0

mysql> select * from mysql.slow_log where sql_text like '%alter%';
Empty set (0.00 sec)

5 在log_queries_not_using_indexes为1的情况下,默认没走索引的sql有多少就记录多少,而设置了log_throttle_queries_not_using_indexes为N后,表示1分钟内该SQL最多记录N条,这个参数在5.6.5后支持

set global log_queries_not_using_indexes=1;

set global log_queries_not_using_indexes=1;

mysql> select * from xx;
Empty set (0.00 sec)

mysql> select * from xx;
Empty set (0.00 sec)

mysql> select * from xx;
Empty set (0.00 sec)

mysql> select * from mysql.slow_log where sql_text like '%xx%';
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+------------------+-----------+
| start_time          | user_host                                    | query_time | lock_time | rows_sent | rows_examined | db   | last_insert_id | insert_id | server_id | sql_text         | thread_id |
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+------------------+-----------+
| 2016-06-13 11:45:50 | ucloudbackup[ucloudbackup] @  [10.10.218.80] | 00:00:00   | 00:00:00  |         0 |             0 | test |              0 |         0 | 168483408 | select * from xx |        29 |
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+------------------+-----------+
1 row in set (0.00 sec)


6 默认情况下有记录就记录,而设置了min_examined_row_limit为N后,表示只有返回条数大于N才记录到慢查询

mysql> set min_examined_row_limit=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select sleep(4.5);
+------------+
| sleep(4.5) |
+------------+
|          0 |
+------------+
1 row in set (4.50 sec)

mysql> select * from mysql.slow_log where sql_text like '%sleep(4.5)%';
Empty set (0.00 sec)

mysql> show variables like '%long%';
+---------------------------------------------------+----------+
| Variable_name                                     | Value    |
+---------------------------------------------------+----------+
| long_query_time                                   | 3.000000 |
| max_long_data_size                                | 16777216 |
| performance_schema_events_waits_history_long_size | 10000    |
+---------------------------------------------------+----------+
3 rows in set (0.00 sec)

mysql> set min_examined_row_limit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select sleep(4.5);
+------------+
| sleep(4.5) |
+------------+
|          0 |
+------------+
1 row in set (4.50 sec)

mysql> select * from mysql.slow_log where sql_text like '%sleep(4.5)%';
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+-------------------+
| start_time          | user_host                                    | query_time | lock_time | rows_sent | rows_examined | db   | last_insert_id | insert_id | server_id | sql_text          |
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+-------------------+
| 2016-06-13 11:27:07 | ucloudbackup[ucloudbackup] @  [10.10.249.91] | 00:00:04   | 00:00:00  |         1 |             0 | test |              0 |         0 | 168491355 | select sleep(4.5) |
+---------------------+----------------------------------------------+------------+-----------+-----------+---------------+------+----------------+-----------+-----------+-------------------+
1 row in set (0.00 sec)

7 只有sql的实际执行时间超过long_query_time,才会记录到慢查询(这里的实际执行时间排除了lock的时间),而当记录到slow_log后,query_time列记录的时间是实际执行时间+lock_time的时间。

case 1 实际执行时间为5s,lock时间为40s,记录到慢查询

session 1 执行

mysql> flush tables with read lock;

Query OK, 0 rows affected (0.00 sec)


session 2执行以下sql,这时sql被锁住

mysql> insert into xx values (sleep(5));


session1断开连接释放全局读锁

session2 经过5s后执行完成

mysql> insert into xx values (sleep(5));
Query OK, 1 row affected (45.27 sec)

这时查看mysql.slow_log

    start_time: 2016-06-13 11:54:15
     user_host: ucloudbackup[ucloudbackup] @  [10.10.218.80]
    query_time: 00:00:45
     lock_time: 00:00:40
     rows_sent: 0
 rows_examined: 0
            db: test
last_insert_id: 0
     insert_id: 0
     server_id: 168483408
      sql_text: insert into xx values (sleep(5))
     thread_id: 34
14 rows in set (0.00 sec)

可以看到query_time为45s,locktime为40s,query_time是40+5,包括了lock时间和实际执行时间


case 2 实际执行时间为1s,locktime为5s,不记录慢查询

session 1执行flush tables with read lock;

session 2 执行mysql> insert into xx values (sleep(1));

断开session1释放全局读锁

session2过1s后执行完成,总耗时为6s

mysql> insert into xx values (sleep(1));
Query OK, 1 row affected (6.02 sec)

查看慢查询,无session2的记录

mysql> select * from mysql.slow_log where sql_text like '%sleep(1)%';
Empty set (0.00 sec)

8 默认slave不会记录主库传过来的慢查询,除非开启log_slow_slave_statements为1(官方文档是这么说的),但是我在主从上都打开了这个参数,发现从库还是没有记录,这tmd是bug吧(5.6.11支持这个参数,我用的是5.6.20)





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值