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

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

在这里插入图片描述

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 锁

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core中实现个人资料上传图片功能

当用户需要在ASP.NET Core中实现修改个人资料的功能时,其中一个常见的需求就是允许上传个人头像图片。下面将详细介绍如何在ASP.NET Core中实现修改个人资料上传图片的功能。 步骤一:控制器中添加一个HttpPost方法 首先,我们在控制器中添加…

Linux时间同步和时间设置

时间分为: 1、hwclock:用于查看硬件时间 hwclock -r(--show:读取硬件时钟并打印结果) :查看硬件时间 hwclock -s :系统时间向硬件时间同步 hwclock -w :硬件时间向系统时间同步 …

Dash+Plotly | Web应用开发(1)

本文为https://github.com/CNFeffery/DataScienceStudyNotes的学习笔记,部分源码来源于此仓库。 本期内容主要为基础概念、web布局方法和交互回调。 文章目录 Dash的主要模块Highlightlayoutcallback 惰性交互阻止初次回调忽略回调匹配错误控制部分回调输出不更新获…

企业数据库安全管理规范

1.目的 为规范数据库系统安全使用活动,降低因使用不当而带来的安全风险,保障数据库系统及相关应用系统的安全,特制定本数据库安全管理规范。 2.适用范围 本规范中所定义的数据管理内容,特指存放在信息系统数据库中的数据。 本…

C语言基础知识(6):UDP网络编程

UDP 是不具有可靠性的数据报协议。细微的处理它会交给上层的应用去完成。在 UDP 的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。因此,应用有时会根据自己的需要进行重发处理。 1.UDP协议的主要特点: &#xf…

day07 四数相加Ⅱ 赎金信 三数之和 四数之和

题目1:454 四数相加Ⅱ 题目链接:454 四数相加Ⅱ 题意 4个整数数组nums1, nums2, nums3, nums4的长度均为n,有多少个元组(i,j,k,l)使得 nums[…

分布式锁3: zk实现分布式锁3 使用临时顺序节点+watch监听实现阻塞锁

一 zk实现分布式锁 1.1 使用临时顺序节点 的问题 接上一篇文章,每个请求要想正常的执行完成,最终都是要创建节点,如果能够避免争抢必然可以提高性能。这里借助于zk的临时序列化节点,实现分布式锁 1. 主要修改了构造方法和lock方…

【鸿蒙4.0】安装DevEcoStudio

1.下载安装包 HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者华为鸿蒙DevEco Studio是面向全场景的一站式集成开发环境,,在鸿蒙官网下载或升级操作系统开发工具DevEco Studio最新版本,SDK配置和下载,2.1支持Mac、Windows操作系统。…

静态网页设计——环保网(HTML+CSS+JavaScript)(dw、sublime Text、webstorm、HBuilder X)

前言 声明:该文章只是做技术分享,若侵权请联系我删除。!! 感谢大佬的视频: https://www.bilibili.com/video/BV1BC4y1v7ZY/?vd_source5f425e0074a7f92921f53ab87712357b 使用技术:HTMLCSSJS(…

鸟类分类、鸟类声音相关深度学习数据集大合集

最近收集了一大波和鸟类相关的图片、声音数据集,包含:鸟类分类、鸟类声音识别、鸟类和无人机分类、鸟类状态、鸟类行为等相关数据集。现在分享给大家!! 1、英国20大园林鸟类的图像数据集 20英国花园鸟类数据集提供了20个类别的3…

我用 midjourney 创作的那些好看的图片

下面这些是个人的midjourney v5的关键词,各种类型都有 抽象画 One piece of original artwork from 1998 , in the style of confucian ideology, pop art-inspired collages, recycled material murals, meticulous military scenes, close-up intensity, grocer…

Android Canvas图层saveLayer剪切clipRect原图对应Rect区域,Kotlin(1)

Android Canvas图层saveLayer剪切clipRect原图对应Rect区域,Kotlin(1) 上面一个ImageView,下面一个ImageView,两个ImageView同等大小。当手指在上面的ImageView滑动时候,在下面ImageView里面显示对应区域“…

如何使用UUP从windows更新服务器下载windows10原版镜像

UUP是指Windows 10中的一种更新技术,全称为Unified Update Platform。UUP的目标是提供更快、更高效的更新体验,它通过增量更新的方式来更新操作系统,只下载和安装实际变化的部分,而不是整个更新包。这样可以节省带宽和时间&#x…

案例102:基于微信小程序的旅游社交管理系统设计与实现

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…

HAL——SPI

学习目标 掌握SPI配置方式掌握SPI读写操作 学习内容 需求 SPI配置 打开SPI1,选中全双工模式。观察下方自动生成的引脚,是否和自己开发板引脚对应。 修改引脚,来动右侧芯片引脚视图,找到开发板对应引脚,进行修改。

【Python机器学习】线性模型——线性回归

线性回归,又叫普通最小二乘法,是回归问题最简单也是最经典的线性方法。线性回归寻找参数w和b,使得对训练集的预测值与真实的回归目标值y之间的均方误差最小。 均方误差是预测值与真实值之差的平方和除以样本差。线性回归没有参数&#xff0c…

设计模式设计原则——依赖倒置原则(DIP)

DIP:Dependence Inversion Principle 原始定义:High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions。 官…

62.网游逆向分析与插件开发-游戏增加自动化助手接口-游戏公告类的C++还原

内容来源于:易道云信息技术研究院VIP课 上一个内容:游戏红字公告功能的逆向分析-CSDN博客 码云地址(master分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:0888e34878d9e7dd0acd08ef…

Android Studio 最新版本首次下载和安装以及汉化教程【+第二次安装使用教程】

🌟博主领域:嵌入式领域&人工智能&软件开发 前言:本教程详解首次安装和下载最新版本的Android Studio ,以及汉化教程。另外详解当第二次下载使用时解决遇到的问题。 目录 1.Android Studio 下载 2.Android Studio 首次…

机器人相关知识

机器人学(Robotics) 一些基础概念 位姿 位姿位置姿态 位姿的表示 刚体 刚性物体是一组粒子的集合,其中任意两个粒子之间的距离保持固定,不受物体运动或施加在物体上的力的影响。 “完全不可变形”的物体就是刚体。 刚体位置 刚性连杆 …