MySQL 1093错误 及EXPLAIN分析

UPDATE `user` set age=50 WHERE id IN (SELECT id FROM `user` WHERE age =20);

DELETE FROM `user`  WHERE id =(SELECT id FROM `user` WHERE age =20);



UPDATE `user` set age=50 WHERE id IN (SELECT id FROM `user` WHERE age =20)
> 1093 - You can't specify target table 'user' for update in FROM clause
> 时间: 0s


DELETE FROM `user`  WHERE id =(SELECT id FROM `user` WHERE age =20)
> 1093 - You can't specify target table 'user' for update in FROM clause
> 时间: 0s

在进行更新和删除操作的时候,条件语句里面有子查询语句,此时会报1093错误!

MySQL在进行读取数据的时候 会加读锁(共享锁),其他请求可以再次加上读锁,但是不能加写锁,(如果在读的过程中,又有其他线程进行了更新操作,就会导致当前线程读取到的数据不是最新的数据,这就是不可重复读现象)。因此不支持对数据更新的同时进行查询操作,加了读锁 就不允许加写锁。

此时可以通过再建立一个子查询语句 建立临时表来绕过此问题。

UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20);

UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20)
> Affected rows: 1
> 时间: 0.013s

此条语句之中 先执行的from 后面的子查询,建立的临时表 temp,所以可以进行更新查询操作,此时的temp表为临时表加了锁也无所谓

DELETE FROM `user`  WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2);


DELETE FROM `user`  WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2)
> Affected rows: 1
> 时间: 0.009s

这样改造 均操作成功!

查看执行计划:

EXPLAIN UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20);

EXPLAIN DELETE FROM `user`  WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2);

1.最先执行的为 为派生  DERIVED

   SIMPLE :查询语句为简单查询、

   PRIMARY :查询包含子查询的时候,对应的最外层的查询类型

   UNION : union之后出现的select语句对应的查询类型、

   SUBQUERY :子查询

   DEPENDENT SUBQUERY : 取决于外面的查询   目前第一步从user表中查询;

2.然后执行的类型为PRIMARY包含有子查询,从派生表里面查询数据 ;

3.目前表是没有分区的 所以partitions为空

4.type 代表的是当前通过什么样的方式对数据库表进行访问

    system : 该表只有一行,相当于系统表,数据量很小,查询速度很快,system是const类型的特例

   const : 说明在进行数据查询的时候,命中了primary key或唯一索引,此类数据查询非常快

   eq_ref : 在数据查询过程中,如果SQL语句中在表链接情况下可以基于聚簇索引或者null值的唯一索引进行数据扫描,那么此时type对应的值就是eq_ref

   ref : 如果命中的索引是二级索引不是唯一索引,type是ref,如果是多字段的联合索引,根据最左匹配原则,从联合索引的最左侧开始连续多个列的字段进行等值比较也是ref类型。

  ref_or_null : 类似于ref ,区别在于会额外搜索包含NULL值的行

  unique_subquery : 在where条件中的关于in的子查询集合

  index_subquery : 用于非唯一索引,可以返回重复值

  range : 使用索引进行行数据检索,只对指定范围内的行数据检索。就是针对的一个有索引的字段,在指定的范围中检索数据 如果where 语句中使用 between、and 、< 、> 、<=、 in 等条件都是range

  index : 与ALL都是读全表,区别在于index是遍历索引树读取,而ALL是从硬盘中读取

  ALL : 遍历全表进行数据匹配,此时的数据查询性能最差

5.possible_keys

表示哪些索引可以按MySQL的优化器进行选择,也就是索引候选者有哪些。

6. key 

 possible_keys中实际选择的索引

7. key_len

 索引的长度,和实际的字段属性以及是否为null都有关系

8.ref (条件的引用方式)

如果使用字段进行常量等值查询时ref 此处为const ;当查询条件中使用了表达式或者函数ref 为 func ;其他的显示 null;

9.rows

执行查询的时候必须检查的行数,行数越少,效率越高!!

10. filtered

是一个百分比的值,表里符合条件的记录数百分比。满足条件的记录数量的比例

11.extra

其他列不显示的额外信息在此列进行展示。

  Using index :数据库使用了覆盖索引,查询的列被索引覆盖,使用到覆盖索引会比较快

  Using where : 查询时未找到可用的索引,进而通过where条件过滤获取所需数据,并不是所有的带where语句的查询都会显示这个。

  Using temporary : 查询后结果需要用临时表来存储,一般在排序或者分组查询时用到

  Using filesort : 此类型表示无法利用索引完成指定的排序操作,也就是order by的字段实际没有索引,因此此类SQL是需要进行优化的。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laughing_Xie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值