【MYSQL】MYSQL 的学习教程(十一)之 MySQL 不同隔离级别,都使用了哪些锁

news2024/11/16 15:40:08

聊聊不同隔离级别下,都会使用哪些锁?

在这里插入图片描述

1. MySQL 锁机制

对于 MySQL 来说,如果只支持串行访问的话,那么其效率会非常低。因此,为了提高数据库的运行效率,MySQL 需要支持并发访问。而在并发访问的情况下,会发生各种各样的问题,例如:脏读、不可重复读、幻读等问题。为了解决这些问题,就出现了事务隔离级别

本质上,事务隔离级别就是为了解决并发访问下的数据一致性问题的。不同的事务隔离级别,解决了不同程度的数据一致性

我们所说的全局锁、表锁、行级锁等等,其实都是事务隔离级别的具体实现。而 MVCC、意向锁,则是一些局部的性能优化

2. 事务隔离级别

MySQL 数据库有四大隔离级别:

  • 读未提交(脏读):可以读取到其他事务还没提交的数据。 未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读
  • 读已提交(不可重复读):该隔离级别的事务能读取到已经提交事务的数据。 因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读
  • 可重复读(MySQL 的默认事务隔离级别:幻读):同一事务范围内读取到的数据是一致的。 但也会有新的问题,比如:此级别的事务正在执行时,另一个事务成功的插入了某条数据,两次查询结果记录条数不一样
  • 串行化:所有事务串行执行。 不用去竞争,一个个去执行,但是效率也是最低的
    • 当事务读取数据时,会获取共享锁,以确保数据的一致性。如果有其他事务已经持有排他锁,则读取操作需要等待排他锁释放
    • 当事务修改数据时,会获取排他锁,以防止其他事务读取或修改相同的数据。如果有其他事务已经持有共享锁或排他锁,则修改操作需要等待相关锁释放

3. MySQL 锁类型

在 MySQL 中有全局锁、表级锁、行级锁三种类型,其中比较关键的是表级锁、行级锁

MySQL 锁类型:

  • 全局锁
  • 表级锁
    • 表锁:在 Innodb 存储存储引擎中,表锁也用得比较少
    • 元数据锁:基本上都是数据库自行操作
    • 意向锁
  • 行级锁
    • 记录锁:某个索引记录的锁
    • 间隙锁:两个索引记录之间的空隙锁
    • 临键锁:记录锁 + 间隙锁
    • 自增锁

在 Innodb 存储引擎中,我们可以通过下面的命令来查询锁的情况:

# 开启锁的日志
set global innodb_status_output_locks=on; 
# 查看innodb引擎的信息(包含锁的信息)
show engine innodb status\G;

查询结果一般如下图所示:

在这里插入图片描述

上面几种不同类型的锁,其各自的关键字为:

  • 表级的意向排它锁(IX):lock mode IX。
  • 行级的插入意向锁(LOCK_INSERT_INTENTION): lock_mode X locks gap before rec insert intention
  • 行级的记录锁(LOCK_REC_NOT_GAP): lock_mode X locks rec but not gap
  • 行级的间隙锁(LOCK_GAP): lock_mode X locks gap before rec
  • 行级的 Next-key 锁(LOCK_ORNIDARY): lock_mode X

通过上面的命令,我们就可以知道不同的事务隔离级别使用了哪些锁了

4. 准备数据测试

CREATE TABLE `2022`.`price_test` (
  `id` BIGINT(64) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) not null,
  `price` INTEGER(4) NULL,
  PRIMARY KEY (`id`));

INSERT INTO price_test(name,price) values('apple', 10);

四种隔离级别:

  • READ UNCOMMITTED:读未提交
  • READ COMMITTED:读已提交
  • REPEATABLE READ:可重复读
  • SERLIALIZABLE:序列化

5. 读未提交

打开两个命令行窗口,并且都修改事务隔离级别为「读未提交」

// 设置隔离级别
SET session TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
// 查看隔离级别
select @@transaction_isolation;

5.1 读写

  1. 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
  1. 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
  1. 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 读取到了事务 B 未提交的数据,这其实就是脏读
select * from price_test where id = 1;

在这里插入图片描述

【结论】:在「读未提交」事务隔离级别下,读写是可以同时进行的,不会阻塞。

5.2 写写

事务 A 和 事务 B 同时对 id 为 1 的记录进行更新,看看是否能够更新成功

  1. 先用如下命令在事务 A(上边的窗口)执行,将 price 修改为 15,此时事务 A 还未提交。
begin;
update price_test set price = 15 where id = 1;
  1. 如下命令在事务 B(下边的窗口)执行,将 price 修改为 20,从图中可以看到,事务 B 阻塞卡住了
begin;
update price_test set price = 20 where id = 1;

【结论】:在「读未提交」事务隔离级别下,写写不可以同时进行的,会阻塞

在这里插入图片描述

通过查看锁信息可以看到,其是加上一个行级别的记录锁,如下图所示:

在这里插入图片描述

如果指定了非索引的列作为查询条件,是否会触发间隙锁呢?

插入一条数据:

INSERT INTO `2022`.`price_test` (`id`, `name`, `price`) VALUES (2, 'orange', 30);
  1. 在事务 A 执行如下命令:select * from price_test where price > 15 for update;,查询 price > 15 的记录:

  2. 接着,我们在事务 B 执行如下命令:select * from price_test where price > 5 for update;,查询 price > 5 的记录。从如下结果可以看到,事务 B 阻塞住了:

在这里插入图片描述
3. 事务 A 查看锁的情况,如下图所示:

在这里插入图片描述

从上图可以看出,MySQL 只是加上了一个记录锁,并没有加间隙锁

5.3 总结

在「读未提交」隔离级别下,读写操作可以同时进行,但写写操作无法同时进行。与此同时,该隔离级别下只会使用行级别的记录锁,并不会用间隙锁

6. 读已提交

设置一下隔离级别为「读已提交」

SET session TRANSACTION ISOLATION LEVEL READ COMMITTED;

6.1 读写

  1. 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
  1. 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
  1. 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 未读取到了事务 B 未提交的数据,未产生脏读
select * from price_test where id = 1;

在这里插入图片描述

6.2 写写

测试同时对 id 为 1 的数据进行更新:

  1. 事务 A 执行如下命令:
begin;
update price_test set price = 15 where id = 1;
  1. 接着事务 B 执行如下命令:
begin;
update price_test set price = 20 where id = 1;
  1. 事务 B 阻塞了。查看下锁信息,如下图所示

在这里插入图片描述

可以看到,其锁是一个行级别的记录锁,结果和「读未提交」的是一样的

继续看看范围的查询是否会触发间隙锁

  1. 事务 A 执行:
begin;
select * from price_test where price > 5 for update;
  1. 事务 B 执行:
begin;
select * from price_test where price > 15 for update;
  1. 事务 B 会阻塞,查看锁信息如下图所示

在这里插入图片描述

6.3 总结

在「读已提交」隔离级别下,只会使用行级别的记录锁,并不会用间隙锁。

6.4 读已提交隔离级别如何解决了【脏读】问题

脏读:是在并发事务中,一个事务可以读取到另一个未提交事务的数据

在“读已提交”隔离级别下,事务只能读取已经提交的数据,而不能读取未提交的数据。这意味着当一个事务正在进行修改时,其他事务无法读取到该事务所做的修改,直到该事务提交

为了实现"读已提交"隔离级别,数据库管理系统通常使用锁机制或多版本并发控制(MVCC)。锁机制可以确保一个事务在修改数据时对其他事务进行阻塞,以防止脏读。而MVCC则通过为每个事务创建不同的数据版本来实现隔离,并且只允许事务读取已提交的数据版本

7. 可重复读

我们设置一下隔离级别为「可重复读」

SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;

7.1 读写

  1. 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
  1. 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
  1. 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 未读取到了事务 B 未提交的数据,未产生脏读
select * from price_test where id = 1;

7.2 写写

同时对 id 为 1 的数据进行更新,看看会发生什么

  1. 事务 A 执行如下命令:
begin;
update price_test set price = 15 where id = 1;
  1. 事务 B 执行如下命令
begin;
update price_test set price = 20 where id = 1;
  1. 事务 B 阻塞了。查看下锁信息,加上一个行级别的记录锁

在这里插入图片描述

继续看看范围的查询是否会触发间隙锁?

  1. 事务 A 执行:
begin;
select * from price_test where price > 5 for update;
  1. 事务 B 执行:
begin;
select * from price_test where price > 15 for update;
  1. 事务 B 会阻塞,查看锁信息如下图所示

在这里插入图片描述

可以看到,在这里就变成了 Next-Key 锁,就是记录锁和间隙锁结合体

7.3 总结

在「可重复读」隔离级别下,使用了记录锁、间隙锁、Next-Key 锁三种类型的锁

可重复读存在幻读的问题,但实际上在 MySQL 中,因为其使用了间隙锁,所以在「可重复读」隔离级别下,可用加锁解决幻读问题。因此,MySQL 将「可重复读」作为了其默认的隔离级别

8. 总结

对于任何隔离级别,表级别的表锁、元数据锁、意向锁都是会使用的,但对于行级别的锁则会有些许差别

  • 在「读未提交」和「读已提交」隔离级别下,都只会使用记录锁,不会用间隙锁,当然也不会有 Next-Key 锁了
  • 对于「可重复读」隔离级别来说,会使用记录锁、间隙锁和 Next-Key 锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LLM的概念理解能力】Concept Understanding In Large Language Models: An Empirical Study

大语言模型中的概念理解:一个实证研究 摘要 大语言模型(LLMs)已经在广泛的任务中证明了其卓越的理解能力和表达能力,并在现实世界的应用中显示出卓越的能力。因此,研究它们在学术界和工业界的值得信赖的性能的潜力和…

buuctf[极客大挑战 2019]BabySQL--联合注入、双写过滤

目录 1、测试万能密码: 2、判断字段个数 3、尝试联合注入 4、尝试双写过滤 5、继续尝试列数 6、查询数据库和版本信息 7、查询表名 8、没有找到和ctf相关的内容,查找其他的数据库 9、查看ctf数据库中的表 10、查询Flag表中的字段名 11、查询表…

C++学习笔记——对象的指针

目录 一、对象的指针 二、减少对象的复制开销 三、应用案例 游戏引擎 图像处理库 数据库管理系统 航空航天软件 金融交易系统 四、代码的案例应用 一、对象的指针 是一种常用的技术,用于处理对象的动态分配和管理。使用对象的指针可以实现以下几个方面的功…

Python GIL 一文全知道!

GIL 作为 Python 开发者心中永远的痛,在最近即将到来的更新中,终于要彻底解决了,整个 Python 社群都沸腾了 什么是GIL? GIL是英文学名global interpreter lock的缩写,中文翻译成全局解释器锁。GIL需要解决的是线程竞…

遥感影像-语义分割数据集:云数据集详细介绍及训练样本处理流程

原始数据集详情 简介:该云数据集包括150张RGB三通道的高分辨率图像,在全球不同区域的分辨率从0.5米到15米不等。这些图像采集自谷歌Earth的五种主要土地覆盖类型,即水、植被、湿地、城市、冰雪和贫瘠土地。 KeyValue卫星类型谷歌Earth覆盖区…

太惨了,又一个程序员被渣的开年大瓜

今天闲暇之余浏览了一下mm,忽然看见一条瓜:某东pdf瓜,一份19页的PDF文件,题为《婚房变赠予,京东渣女出轨连环套设计冤大头程序员》,点进去看了一下,简直炸裂了三观,男同志们一定要保…

EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测

EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测 目录 EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.【E…

【LLM 论文阅读】NEFTU N E: LLM微调的免费午餐

指令微调的局限性 指令微调对于训练llm的能力至关重要,而模型的有用性在很大程度上取决于我们从小指令数据集中获得最大信息的能力。在本文中,我们提出在微调正向传递的过程中,在训练数据的嵌入向量中添加随机噪声,论文实验显示这…

彭博评选2024年50家企业,比亚迪、联发科上榜 | 百能云芯

彭博资讯于9日发布2024年全球50家值得关注的企业名单,该名单由彭博分析师团队从金融到食品等领域追踪了约2,000家企业中挑选出的,根据「观点聚焦」清单,选出50家值得关注的公司,重点考虑了其独特观点、领导层变化、资产出售或并购…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷①

2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷1 目录 需要竞赛软件包环境以及备赛资源可私信博主!!! 2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷1 模块一 …

Flask 菜品管理

common/libs/Helper.py getDictFilterField() 方法 用于在web/templates/food/index.html中展示菜品分类 如何能够通过food里面的cat_id获取分类信息呢?只能通过for循环,这样会很麻烦,所以定义了这个方法。 这个方法可以的查询返回结果…

【数据库系统概论】期末复习1

试述数据、数据库、数据库系统、数据库管理系统的概念。试述文件系统与数据库系统的区别和联系。试述数据库系统的特点。数据库管理系统的主要功能有哪些?试述数据库系统三级模式结构,这种结构的优点是什么?什么叫数据与程序的物理独立性&…

玩转QrCode

生成二维码,跳转指定 url 导入模块 npm install --save qrcode.vue1.7.0 引入模块 import QrcodeVue from qrcode.vue编写页面 button 触发 <template><el-button type"primary" click"showQRCode"><svg-icon icon-class"code&quo…

如何在IEC61850的ICD文件中添加新的DO节点

写在前面 恭喜“梅山剑客”粉丝突破1K&#xff0c;为了纪念这一伟大的时刻&#xff0c;今日发表此文&#xff0c; 纪念这神圣的时间节点&#xff0c;愿各位 青春永驻&#xff0c;笔耕不息。 本文参考链接&#xff1a; 1、61850开发知识总结与分享 2、IEC61850建模说明 1 简介…

ELF文件格式解析二

使用objdump命令查看elf文件 objdump -x 查看elf文件所有头部的信息 所有的elf文件。 程序头部&#xff08;Program Header&#xff09;中&#xff0c;都以 PT_PHDR和PT_INTERP先开始。这两个段必须在所有可加载段项目的前面。 从上图中的INTERP段中&#xff0c;可以看到改段…

QT第三天

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面如果账号和密码不匹配&#xff0…

内存淘金术:Redis 内存满了怎么办?

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 内存淘金术&#xff1a;Redis 内存满了怎么办&#xff1f; 前言LRU&#xff08;Least Recently Used&#xff09;算法LFU&#xff08;Least Frequently Used&#xff09;算法定期淘汰策略内存淘汰事件…

最新出炉!知乎最牛最全JMeter+Ant+Jenkins接口自动化测试框架(Windows)

一:简介 大致思路&#xff1a;Jmeter可以做接口测试&#xff0c;也能做压力测试&#xff0c;而且是开源软件&#xff1b;Ant是基于Java的构建工具&#xff0c;完成脚本执行并收集结果生成报告&#xff0c;可以跨平台&#xff0c;Jenkins是持续集成工具。将这三者结合起来可以搭…

JNPF低代码是什么,怎么样?

低代码开发平台已经是程序员日常标配效率工具了&#xff0c;曾经我们拿到开发需求后&#xff0c;要先配 Vue & React 等框架环境、再选需要引入的第三方组件库&#xff0c;最后穿针引线&#xff0c;调试搭建起需要的后台工具。这其中无数深坑等着我们去趟&#xff0c;直到低…

【C++进阶05】AVL树的介绍及模拟实现

一、AVL树的概念 二叉搜索树的缺点 二叉搜索树虽可以缩短查找效率 但如果数据有序或接近有序 二叉搜索树将退化为单支树 查找元素相当于在顺序表中搜索元素&#xff0c;效率低下 AVL树便是解决此问题 向二叉搜索树中插入新结点 并保证每个结点的左右子树 高度之差的绝对值不超…