MySQL通过Explain查看select语句的执行计划结果触发写操作

背景

  某某同学执行了一下Explain结果结果发现数据库有了一条写入操作,恭喜这位同学你的锅到货了,你签收一下;

 

  对! 你没有听错,在一种场景下就算是Explain也会引发数据的写操作,就这是外层查询访问任意表,内层查询调用function

  在function有写入动作的情况下会发生写入。

 

硬生生的套上一个场景

  假设我们有一个Person表,每访问一次Person表都记录一次在什么时候,访问了哪一行,表结构设计如下

create table if not exists person(
    id int not null auto_increment primary key,
    name varchar(16)
);

create table if not exists person_opration_log(
    id int not null auto_increment primary key,
    pid int not null,
    access_datetime datetime
);

delimiter //
create function fun_person_log(pid int) returns int
    begin
        insert into person_opration_log(pid,access_datetime) values(pid,now());
        return pid;
    end //

delimiter ;

 

  正常的数据访问SQL如下,但是它并不写日志

mysql> select
    ->     id,
    ->     name 
    -> from person 
    -> where id = 1;
+----+--------+
| id | name   |
+----+--------+
|  1 | 项羽   |
+----+--------+
1 row in set (0.00 sec)

 

  如果我们要写日志可以分两步走,先访问再计一笔日志

mysql> select
    ->     id,
    ->     name 
    -> from person 
    -> where id = 1;
+----+--------+
| id | name   |
+----+--------+
|  1 | 项羽   |
+----+--------+
1 row in set (0.00 sec)

mysql> 
mysql> select fun_person_log(1);
+-------------------+
| fun_person_log(1) |
+-------------------+
|                 1 |
+-------------------+
1 row in set (0.05 sec)

mysql> 
mysql> select * from person_opration_log ;
+----+-----+---------------------+
| id | pid | access_datetime     |
+----+-----+---------------------+
|  1 |   1 | 2018-10-06 17:12:31 |
+----+-----+---------------------+
1 row in set (0.00 sec)

 

牛人想出的新点子把两步合成一步

  牛人的新点子

mysql> select 
    ->     fun_person_log(100) as id , 
    ->     name
    -> from person
    -> where id = (select fun_person_log(100));
Empty set (0.04 sec)

mysql> 
mysql> select * from person_opration_log;
+----+-----+---------------------+
| id | pid | access_datetime     |
+----+-----+---------------------+
|  1 |   1 | 2018-10-06 17:12:31 |
|  2 | 100 | 2018-10-06 17:15:29 |
+----+-----+--------------------

  牛人的新点子刚好入坑,我们可以explain一下

mysql> explain select 
    ->     fun_person_log(250) as id , 
    ->     name
    -> from person
    -> where id = (select fun_person_log(250));
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                          |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
|  1 | PRIMARY     | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | no matching row in const table |
|  2 | SUBQUERY    | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used                 |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
2 rows in set, 1 warning (0.08 sec)

mysql> 
mysql> select * from person_opration_log;
+----+-----+---------------------+
| id | pid | access_datetime     |
+----+-----+---------------------+
|  1 |   1 | 2018-10-06 17:12:31 |
|  2 | 100 | 2018-10-06 17:15:29 |
|  3 | 250 | 2018-10-06 17:17:23 |
+----+-----+---------------------+
3 rows in set (0.00 sec)

  看吧! explain引发了写入操作!

 

参考连接

 

Derived Tables

 

学习交流

 -----------------------------http://www.sqlpy.com-------------------------------------------------

 -----------------------------http://www.sqlpy.com-------------------------------------------------

  

 

posted on 2018-10-06 17:21  蒋乐兴的技术随笔  阅读(451)  评论(0编辑  收藏  举报

导航