暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL子查询的一个Bug,大家注意一下

92

今天,马六学上弄了一个活动,鼓励大家分享自己最硬核的数据库经验(可以是坑、技巧或冷知识)。

活动地址:

https://www.maliustudy.com/post_detail/262

小程序可点击跳转

其中,有一位朋友留言。

看这条SQL,第一感觉是,如果course没有id这个字段,执行之后,应该要提示字段不存在才合理。

但实际返回了数据。

我也是很好奇,然后做了一个实验。

创建测试表:

    CREATE TABLE `t1_0807` (
      `id` int NOT NULL AUTO_INCREMENT,
      `a` int DEFAULT NULL,
      b varchar(10),
      PRIMARY KEY (`id`),
      KEY `idx_a` (`a`)
    ) ENGINE=InnoDB;


    CREATE TABLE `t2_0807` (
      `id` int NOT NULL AUTO_INCREMENT,
      `c` int DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;

    写入测试数据:

      insert into t1_0807(a,b) values (1,'one'),(2,'two'),(3,NULL);
      insert into t2_0807(c) values (1),(2),(3);

      查询:

        select * from t1_0807 where b in (select b from t2_0807);

        果然,复现了,t2_0807没有b字段,也返回了数据,MySQL版本是8.0.25。


        估计是优化器改写的时候出的问题。

        我们先查看执行计划:

          explain select * from t1_0807 where b in (select b from t2_0807);

          查看warnings,就能看到优化器是怎么改写SQL的。

            show warnings;

            原来是SQL被优化器改写成了:

              select#1 */ select `martin`.`t1_0807`.`id` AS `id`,`martin`.`t1_0807`.`a` AS `a`,`martin`.`t1_0807`.`b` AS `b` from `martin`.`t1_0807` semi join (`martin`.`t2_0807`) where (`martin`.`t1_0807`.`b` = `martin`.`t1_0807`.`b`

              大家在使用子查询的时候得小心了哈,一个好的习惯就是在更新或者删除前,先查询一下,看是不是符合预期。

              像这位同学的留言,应该就是研发没先执行查询,直接更新导致全表数据被错误更新了。


              近期文章

              怎样构建自己的数据库运维平台?

              这些Xtrabackup的问题你遇到过吗?

              一周41个技术问题,来自社群的强烈推背感

              从小镇做题家到大厂DBA,他是怎样学习的?

              通过低代码平台go-admin开发MySQL元数据管理系统

              文章转载自MySQL数据库联盟,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论