news 2026/10/27 1:13:48

MySQL Innodb 引擎中预防 Update 操作上升为表锁

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL Innodb 引擎中预防 Update 操作上升为表锁

一、MySQL 如何预防 Update 上升为表锁

在MySQL中,进行任何数据的修改操作都会进行一定的锁操作,而锁的不同直接导致性能的差异。例如MyISAM引擎,更新时采用表锁,并发性较差。而Innodb引擎支持事务,更新时采用行锁,锁的粒度更细,所以并发性较高。

由于表锁的粒度过大,即使只有部分行被修改,也会阻塞其他事务对整个表的写操作,限制了系统的吞吐量和响应速度。对于在Innodb引擎中,虽然采用了粒度更细的行锁,但也不是所有的数据修改操作都是仅锁住相关的行,有时很可能不注意就导致了表锁。

下面通过一个实验进行深入:

例如有如下表结构:

CREATETABLE`user`(`id`intNOTNULLAUTO_INCREMENT,`name`varchar(255)DEFAULTNULL,`age`intDEFAULTNULL,`sex`varchar(255)DEFAULTNULL,PRIMARYKEY(`id`),KEY`idx_user_name_age`(`name`,`age`),KEY`name`(`name`,`age`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_0900_ai_ci;

写入一些测试数据:

INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(1,'小明',18,'男');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(2,'小红',19,'女');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(3,'小蓝',16,'女');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(4,'小王',17,'男');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(5,'张三',18,'男');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(6,'李四',19,'男');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(7,'王五',20,'男');INSERTINTO`test`.`user`(`id`,`name`,`age`,`sex`)VALUES(8,'赵六',21,'男');

下面尝试在事务中修改姓名为张三的年龄为20岁,注意这里先不要着急提交事务:

BEGIN;UPDATEuserSETage=20WHEREname='张三';

下面查看下前正在发生的数据锁情况:

SELECT*FROMperformance_schema.data_locksWHEREOBJECT_NAME="user"

从这里可以看出,锁住了表里所有的数据,已经上升为了表锁,但是上面仅更新了姓名为张三的数据,怎么会锁住那么多数据呢?

这是因为name字段没有索引,要找到姓名为张三的数据,就要进行全表扫描,但是update的时候要保证数据的一致性,所以此时相关的数据就是全部的表数据,因此也就相当于表锁了。

那怎么降低锁的粒度呢,既然是因为name字段没有索引,那给name增加索引,再次进行上面实验呢。

增加索引:

ALTERTABLEuserADDINDEXindex_name(name);

再次尝试修改但不提交事务:

BEGIN;UPDATEuserSETage=20WHEREname='张三';

查看下前正在发生的数据锁情况:

SELECT*FROMperformance_schema.data_locksWHEREOBJECT_NAME="user"


可以看出此时并没有锁住全部的数据,但是锁住的'张三', 5和'李四', 6是什么呢?

这其实是索引信息,如果修改操作涉及到了非主键索引,MySql会首先锁住非主键索引,再锁定具体数据的主键索引。至于会锁住李四就是MySQL中Next-Key和GAP间隙锁的原因了,当准备更新张三时,以防止在这个范围内插入新的记录,所以将临近的李四也进行上锁。

从上面结果看增加了索引后已经解决了表锁的问题,但还是会锁住多余的内容,下面直接尝试根据主键进行修改:

BEGIN;UPDATEuserSETage=20WHEREid=5;


再次查看下前正在发生的数据锁情况:

SELECT*FROMperformance_schema.data_locksWHEREOBJECT_NAME="user"

此时就仅锁住相关的数据了。

二、总结

从上面的实验过程来看,MySQL中的修改操作很有可能导致表锁,因此最好在更新语句中使用主键列或其他索引列进行筛选。另外索引最好设置在不经常变更的字段上比较好,不然容易造成冲突死锁的情况。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 1:13:45

基于 YOLO V8 Fine-Tuning 训练自定义的目标检测模型

一、YOLO V8 YOLO V8 是由 2023 年 ultralytics 公司开源的发布,是结合了前几代 YOLO 的融合改进版。YOLO V8 支持全方位的视觉 AI 任务,包括检测、分割、姿态估计、跟踪和分类。并且在速度和准确性方面具有无与伦比的性能。能够应用在各种对速度和精度…

作者头像 李华
网站建设 2026/10/27 1:13:45

Verilog基础:在testbench中使用阻塞赋值和非阻塞赋值的区别

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 本文详细阐述了在一个testbench中,应该如何使用阻塞赋值与非阻塞赋值。首先说结论,建议在testbench中,对时钟信号(…

作者头像 李华
网站建设 2026/10/27 1:13:27

英伟达显卡系列与架构、代表产品

NVIDIA的产品线和GPU架构发展历史都非常丰富。无论是面向普通消费者的游戏显卡,还是面向专业图形、科学计算与AI训练的高性能加速卡,都在不同阶段形成了非常清晰的定位。整体来看,NVIDIA的发展主线并不是简单地“做更快的显卡”,而…

作者头像 李华
网站建设 2026/10/27 1:12:44

Verilog基础:表达式中的整数常量(integer)

相关文章 Verilog基础专栏https://blog.csdn.net/weixin_45791458/category_12263729.html ​ 整数常量可以由十进制、十六进制、八进制或二进制格式指定,有两种表现形式。 第一种表现形式 第一种表现形式是一个简单的十进制数,应指定为0到9的数…

作者头像 李华
网站建设 2026/10/27 1:10:08

电容两端电压不能突变:原理、应用与工程实战完整笔记

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/27 1:07:13

TIA Context:让AI真正理解PLC程序的工业语义中枢

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华