update语句未使用索引的后果

update语句未使用索引的后果

网上有一种说法:mysql的update语句不使用索引,会锁表;使用索引,会锁行。这种说法是非常不准确的。今天来简单分析一下。

本文使用的mysql版本为8.0.32,innodb存储引擎。

例1

本例中的表结构如下:

sql 复制代码
CREATE TABLE `t7` (
  `id` int NOT NULL AUTO_INCREMENT,
  `a` int DEFAULT NULL,
  `b` int DEFAULT NULL,
  `c` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `b` (`b`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

当前数据库中的记录为:

在事务中更新记录:

sql 复制代码
begin;
update t7 set c=11 where a=2 and c=4;

下面,我们来针对这个事务涉及到的锁进行分析。

update语句是否涉及表级锁

首先,update语句执行过程中会涉及到表级锁吗? 答案是会,update语句在执行过程中,会涉及到两种表级锁: 元数据锁和表级意向锁。

MDL锁/元数据锁

MDL锁的主要作用是保证表元数据的一致性。

MySQL server会持有元数据锁,直到事务结束。如果另一个会话尝试对相关表进行DDL操作或者LOCK TABLE,将会阻塞。

关于MDL的详细介绍,可以查看官方文档:元数据锁

我们可以通过查询performance_schema.metadata_locks表来查看元数据锁信息:

sql 复制代码
select * from performance_schema.metadata_locks\G;

查询结果:

表级意向锁

表级意向锁(IS,IX),是为了在以后加表级别的S锁和X锁时可以快速判断表中记录是否被上锁而提出的。 IS与IS、IX与IX、IS与IX之间,相互兼容。 可以通过查询performance_schema.data_locks来获取表及意向锁信息。

sql 复制代码
select * from performance_schema.data_locks\G;

查询结果:

需要注意的是,无论是MDL锁,还是表级意向锁,都不会影响update语句的执行,也就是说,update语句不会因为这两种锁而阻塞。

update语句没有使用到索引究竟会发生什么

update语句如果没有使用到索引,会进行全表扫描,会对表中/聚簇索引的每一行记录进行加锁,这会耗费较长时间。如果用show engine innodb status查看,你可能会发现语句长时间处于searching rows for update状态。 更严重的是,这会带来严重的并发问题。

  • 如果是用RC级别,如果被读取的记录不满足where条件,对应的记录锁会被立即释放。
  • 如果是用RR级别,即使被读取的记录不满足where条件,对应的记录锁也会不会释放,直到事务结束。同时,这个事务也会持有gap锁,阻塞其他事务对这个范围的插入操作。

如果是用RR级别,并发能力会大大降低。这也是很多公司都不会使用默认的RR级别,而改为使用RC级别的原因。

使用到了索引,就一定没问题吗

即使用到了索引,如果索引区分度不高,并发时依然有可能造成较多的锁等待。 此外,如果使用到了索引合并(index merge),还可能会增加死锁的概率。

所以,对于update语句,一定要尽量使用索引,而且要保证索引区分度较高,最好是保证where条件中的每一列都在索引中。

注:此文原载于本人个人网站链接地址

参考资料:

  1. MySQL官方手册-元数据锁

本文由mdnice多平台发布

相关推荐
爱上语文19 分钟前
Redis基础(5):Redis的Java客户端
java·开发语言·数据库·redis·后端
陈敬雷-充电了么-CEO兼CTO1 小时前
推荐算法系统系列>推荐数据仓库集市的ETL数据处理
大数据·数据库·数据仓库·数据挖掘·数据分析·etl·推荐算法
MeshddY1 小时前
(超详细)数据库项目初体验:使用C语言连接数据库完成短地址服务(本地运行版)
c语言·数据库·单片机
wuxinyan1231 小时前
Java面试题033:一文深入了解MySQL(5)
java·数据库·mysql·面试
萧曵 丶2 小时前
Spring @TransactionalEventListener
java·数据库·spring·事务·transactional·异步
胡斌附体2 小时前
mobaxterm终端sqlplus乱码问题解决
数据库·乱码·sqlplus·字符集设置
moon66sun2 小时前
开源项目XYZ.ESB:数据库到数据库(DB->DB)集成
数据库·esb
TDengine (老段)2 小时前
使用 StatsD 向 TDengine 写入
java·大数据·数据库·时序数据库·iot·tdengine·涛思数据
DarkAthena2 小时前
【GaussDB】深度解析:创建存储过程卡死且无法Kill会话的疑难排查
数据库·gaussdb
Gauss松鼠会2 小时前
GaussDB权限管理:从RBAC到精细化控制的企业级安全实践
大数据·数据库·安全·database·gaussdb