【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 读写
- 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
- 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
- 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 读取到了事务 B 未提交的数据,这其实就是脏读了
select * from price_test where id = 1;
【结论】:在「读未提交」事务隔离级别下,读写是可以同时进行的,不会阻塞。
5.2 写写
事务 A 和 事务 B 同时对 id 为 1 的记录进行更新,看看是否能够更新成功
- 先用如下命令在事务 A(上边的窗口)执行,将 price 修改为 15,此时事务 A 还未提交。
begin;
update price_test set price = 15 where id = 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);
-
在事务 A 执行如下命令:
select * from price_test where price > 15 for update;
,查询 price > 15 的记录: -
接着,我们在事务 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 读写
- 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
- 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
- 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 未读取到了事务 B 未提交的数据,未产生脏读。
select * from price_test where id = 1;
6.2 写写
测试同时对 id 为 1 的数据进行更新:
- 事务 A 执行如下命令:
begin;
update price_test set price = 15 where id = 1;
- 接着事务 B 执行如下命令:
begin;
update price_test set price = 20 where id = 1;
- 事务 B 阻塞了。查看下锁信息,如下图所示
可以看到,其锁是一个行级别的记录锁,结果和「读未提交」的是一样的
继续看看范围的查询是否会触发间隙锁
- 事务 A 执行:
begin;
select * from price_test where price > 5 for update;
- 事务 B 执行:
begin;
select * from price_test where price > 15 for update;
- 事务 B 会阻塞,查看锁信息如下图所示
6.3 总结
在「读已提交」隔离级别下,只会使用行级别的记录锁,并不会用间隙锁。
6.4 读已提交隔离级别如何解决了【脏读】问题
脏读:是在并发事务中,一个事务可以读取到另一个未提交事务的数据
在“读已提交”隔离级别下,事务只能读取已经提交的数据,而不能读取未提交的数据。这意味着当一个事务正在进行修改时,其他事务无法读取到该事务所做的修改,直到该事务提交
为了实现"读已提交"隔离级别,数据库管理系统通常使用锁机制或多版本并发控制(MVCC)。锁机制可以确保一个事务在修改数据时对其他事务进行阻塞,以防止脏读。而MVCC则通过为每个事务创建不同的数据版本来实现隔离,并且只允许事务读取已提交的数据版本
7. 可重复读
我们设置一下隔离级别为「可重复读」
SET session TRANSACTION ISOLATION LEVEL REPEATABLE READ;
7.1 读写
- 事务 A 执行如下命令,查询出 id 为 1 记录的 price 值,不提交事务
begin;
select * from price_test where id = 1;
- 接着,事务 B 执行如下命令,修改 price 为 20
begin;
update price_test set price = 20 where id = 1;
- 接着,事务 A 再次读取 id 为 1 记录的 price 值。事务 A 未读取到了事务 B 未提交的数据,未产生脏读。
select * from price_test where id = 1;
7.2 写写
同时对 id 为 1 的数据进行更新,看看会发生什么
- 事务 A 执行如下命令:
begin;
update price_test set price = 15 where id = 1;
- 事务 B 执行如下命令
begin;
update price_test set price = 20 where id = 1;
- 事务 B 阻塞了。查看下锁信息,加上一个行级别的记录锁
继续看看范围的查询是否会触发间隙锁?
- 事务 A 执行:
begin;
select * from price_test where price > 5 for update;
- 事务 B 执行:
begin;
select * from price_test where price > 15 for update;
- 事务 B 会阻塞,查看锁信息如下图所示
可以看到,在这里就变成了 Next-Key 锁,就是记录锁和间隙锁结合体
7.3 总结
在「可重复读」隔离级别下,使用了记录锁、间隙锁、Next-Key 锁三种类型的锁
可重复读存在幻读的问题,但实际上在 MySQL 中,因为其使用了间隙锁,所以在「可重复读」隔离级别下,可用加锁解决幻读问题。因此,MySQL 将「可重复读」作为了其默认的隔离级别
8. 总结
对于任何隔离级别,表级别的表锁、元数据锁、意向锁都是会使用的,但对于行级别的锁则会有些许差别
- 在「读未提交」和「读已提交」隔离级别下,都只会使用记录锁,不会用间隙锁,当然也不会有 Next-Key 锁了
- 对于「可重复读」隔离级别来说,会使用记录锁、间隙锁和 Next-Key 锁
相关文章:

【MYSQL】MYSQL 的学习教程(十一)之 MySQL 不同隔离级别,都使用了哪些锁
聊聊不同隔离级别下,都会使用哪些锁? 1. MySQL 锁机制 对于 MySQL 来说,如果只支持串行访问的话,那么其效率会非常低。因此,为了提高数据库的运行效率,MySQL 需要支持并发访问。而在并发访问的情况下&…...

LORA的基本原理
本文将介绍如下内容: 什么是Lora高效微调的基本原理LORA的实现方式LORA为何有效? 一、什么是LoRA LoRA 通常是指低秩分解(Low-Rank Decomposition)算法,是一种低资源微调大模型方法,论文如下: LoRA: Low…...

Vue2x的自定义指令和render函数使用自定义指令
在某些情况下,我们需要对底层DOM进行操作,而内置的指令不能满足需求,就需要自定义指令。一个自定义指令由一个包含类似组件的生命周期的钩子的对象来定义,钩子函数会接收到指令所绑定的元素作为参数。 定义指令 常用两种方式进行…...

Linux学习(2):文件目录指令
Linux学习(2):文件目录指令 1 文件目录指令1.1 pwd 用来显示当前目录的绝对路径的1.2 ls 显示当前目录的信息1.3 cd 切换到指定目录1.4 mkdir 创建目录1.5 rmdir 删除空目录1.6 touch 创建空文件1.7 cp 拷贝文件到指定目录1.8 rm 移除文件或目…...

Dockerfile的ENV
文章目录 环境总结测试测试1测试2测试3测试4测试5测试6 参考 环境 RHEL 9.3Docker Community 24.0.7 总结 如果懒得看测试的详细信息,可以直接看结果: 一条 ENV 指令可以定义多个环境变量。Dockerfile里可以包含多条 ENV 指令。环境变量的值不需要用…...

【普中开发板】基于51单片机的简易密码锁设计( proteus仿真+程序+设计报告+讲解视频)
基于51单片机的简易密码锁设计 1.主要功能:资料下载链接: 实物图:2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单 【普中】基于51单片机的简易密码锁设计 ( proteus仿真程序设计报告讲解视频) 仿真图proteus8.16(有低版本) 程…...
c语言之输出函数用法 putchar
putchar函数 putchar函数是c语言输出函数,但它只能输出单个字符,如果要输出字符串就不合适了。 应用举例 #include<stdio.h> int main() {putchar(a);putchar(4);putchar(\n);return 0: } 从上面代码可以看出,单字符必须用单引号’…...
高精度原边控制电路D3820,CC/CV精度±5%以内,可作为10W以下小功率、低待机功耗的电源替代,可兼容OB2520
高精度原边控制离线式PWM功率开关 特点 1、全电压范围CC/CV精度保持在5%以内 2、用原边控制,无需TL431和光耦 3、欠压锁定(UVLO)及自动重启 4、驱动BJT 5、内置前沿消隐(LEB) 6、逐周期限流模式 7、输出线压降…...

Python库学习(十四):ORM框架-SQLAlchemy
1.介绍 SQLAlchemy 是一个用于 Python 的 SQL 工具和对象关系映射(ORM)库。它允许开发者通过 Python 代码而不是 SQL查询语言来操作数据库。SQLAlchemy 提供了一种灵活且强大的方式来与关系型数据库交互,支持多种数据库后端,如 P…...
信息学奥赛一本通1014:与圆相关的计算
1014:与圆相关的计算 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 167892 通过数: 85008 【题目描述】 给出圆的半径,求圆的直径、周长和面积。输入圆的半径实数r,输出圆的直径、周长、面积,每个数保留小数点后4…...

Vscode——通过SSH连接服务器
1、打开vscode —— 点击左下角 2、选择SSH 3、点击后会自动安装三个插件 4、点击左下角——连接服务器 5、再次点击左下角——连接服务器 6、登录成功后打开终端即可操作 快捷键:ctrl ~ 7、查看编辑服务器文件目录 点击文件——打开文件夹 8、确定后再次输入登录密…...

UE5 通过接口实现角色描边效果
接口不能够被实例化,不能够在内部书写函数的逻辑和设置属性,只能够被继承使用。它能够让不同的类实现有相同的函数,继承接口的类必须实现接口的函数。 并且,我们可以在不同的类里面的函数实现也不同,比如A类描边是红色…...

电脑提示dll丢失怎么办,教你一招将dll修复
使用电脑时,你的电脑是否出现关于dll文件丢失或找不到的问题,出现这种问题又该如何解决呢,dll文件问题会导致软件无法打开,或者会导致系统崩溃。今天就来教大家如何快速解决dll文件修复。 一.如何修复dll修复 方法一:…...
MATLAB mat 文件
1.mat文件格式 MATLAB(Matrix Laboratory)使用 .mat 文件格式来存储和加载数据。MAT 文件是一种二进制文件格式,能够保存 MATLAB 中的各种数据类型,包括矩阵、向量、结构体、元胞数组等。 特定和用途: 二进制格式&a…...

Linux du和df命令
目录 一. df二. du 一. df ⏹用于显示系统级别,磁盘分区上的可用和已用空间的信息 -h:以人类可读的格式显示文件系统大小 ⏹每秒钟监视当前磁盘的使用情况 watch 用于周期性的执行特定的命令-n 1 表示每一秒刷新一次命令执行的结果df -h ./ 表示周期性…...
Adobe Photoshop 快捷键
PS快捷键 图层 选择图层 Ctrl T:可以对图层的大小和位置进行调整 填充图层 MAC: AltBackspace (前景) or CtrlBackspace (背景) WINDOWS: AltDelete (前景) or CtrlDelete (背景) 快速将图层填充为前景色或背景色 平面化图层(盖印图层)…...

缓存代理服务器
1 缓存代理 1.1 缓存代理的概述 web代理的作用 缓存网页对象,减少重复请求 存储一些之前被访问的或且可能将要备再次访问的静态网页资源对象,使用户可以直接从缓存代理服务器获取资源,从而减少上游原始服务器的负载压力,加快整…...
四道面试题
一.网络的七层模型 网络的七层模型,也被称为OSI七层协议模型,是一种用于理解和描述网络通信过程的概念模型。这个模型将网络通信过程划分为七个层次,从低到高分别是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层…...
BRC20 技术分析
文章目录 什么是 BRC20 ?brc20 白皮书。重点基于链上数据解析获取交易详情返回值如何将 16 进制转换为 字符串没有节点,如何获取数据?见证隔离如何解析出 BRC20 数据?最后如何快速搭建节点BRC20 Indexer...

【Unity】Timer计时器属性及使用
可以代替协程完成延时操作 可以不用Update进行计时 GitHub开源计时插件 网址:https://github.com/akbiggs/UnityTimer/tree/master 导入:URL:https://github.com/akbiggs/UnityTimer.git 基本功能: 创建计时器: Time…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...