当前位置: 首页 > news >正文

【MySQL】——事务的隔离性

目录

一、前言

二、隔离级别

1、查看与设置隔离性

2、读未提交 【Read Uncommitted】

3、读提交【Read Committed】

4、 可重复读【Repeatable Read】

5、串行化 【Serializable】

三、总结


一、前言

在上篇事务一文中,我们提到了事务的四个属性 原子性、持久性、隔离性、一致性。原子性和持久性我们已经在上篇文章中见识到了,但是隔离性和一致性又该怎么理解呢?

我们首先来看事务的隔离性,数据库中为了保证事务执行过程中尽量不受干扰,就有了一个重要的特征:隔离性

同时,数据库中允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

二、隔离级别

首先我们先了解一下MySQL数据库中定义了四种标准的隔离级别:

  1. 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,我们上篇文章为了做实验方便观察现象,用的就是这个隔离性。
  2. 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
  3. 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
  4. 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)

隔离级别如何实现:隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的。常见有,表锁,行锁,读锁,写锁,间隙锁(GAP),Next-Key锁(GAP+行锁)等。不过,我们先了解就行。

1、查看与设置隔离性

设置当前会话 or 全局隔离级别语法

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ
COMMITTED | REPEATABLE READ | SERIALIZABLE}

如我们所想,设置当前会话隔离性,另起一个会话并不会影响新会话的隔离性。若设置全局隔离性,当另起一个新会话时,该会话的隔离性会被影响。

2、读未提交 【Read Uncommitted】

此时客户端A B都在事务中,都没有提交,可以看到在客户端隔离性为读未提交的状态下,客户端A在一个事务中对表中数据更新但是还没提交的情况下,客户端B在事务中也会看到表的更新。 

上面的现象就称为脏读即一个事务在执行中,读到另一个执行中事务的更新(或其他操作),但是未commit的数据。

该隔离性几乎没有枷锁,虽然效率高,但是问题太多了,所以严重不建议采纳。

3、读提交【Read Committed】

 可以看到客户端B是在客户端A的事务提交之后才在它的事务中看到客户端A对表的修改的,而在客户端A没有提交的情况下,客户端B是看不到的,无论自己是否提交。

所以这就造成了在同一个事务内(客户端B事务),同样的读取,在不同的时间段(是在整个事务还在运行的时间段)读取到了不同的值,这种现象就称为 不可重复读

4、 可重复读【Repeatable Read】

可以看到只有在客户端AB同时提交事务之后,客户端B才能看到客户端A在事务中对于表中数据的更新。也就是说客户端B在自己的事务中无论读多少次,读到的內容都是一样的,这也就是为什么该隔离性被称为 可重复读

这里如果将客户端A对表的更新操作变为插入操作,那么在客户端B的事务中还会有可重复读的情况吗?

我们要知道一般的数据库在可重复读的情况的时候,无法屏蔽其他事务insert的数据,因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题。会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读(phantom read)

但是MySQL在可重复读的情况下并没有出现幻读的问题,解决的方式是用Next-Key锁(GAP+行锁),这里稍作了解。

5、串行化 【Serializable】

此时客户端AB都在事务中,可以看到双方读取內容很正常,不会串行化,但是客户端A更新内容时, 会卡顿

当我们提交客户端B的事务后,客户端A的更新就可以继续,只不过由于事务等待的时间超过了MySQL的锁等待超时限制,所以出现了报错。

在RR隔离性下,除了update操作, insertdelete之间是会有加锁现象的,但是select和这些操作是不冲突的,这就是通过读写锁+MVCC完成的隔离性。

RR对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用

三、总结

  • 其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个衡点。
  • 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样
  • 说明: mysql 默认的隔离级别是可重复读,一般情况下不要修改
  • 上面的例子可以看出,事务也有长短事务这样的概念。事务间互相影响,指的是事务在并行执行的时候,即都没有commit的时候,影响会比较大

接下来谈谈一致性

  • 成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
  • 其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑做支撑,也就是,一致性,是由用户决定的。
  • 事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务

感谢阅读!

http://www.dtcms.com/a/122364.html

相关文章:

  • Dubbo的简单介绍
  • 数据分析-Excel-学习笔记Day1
  • LeetCode Hot100 刷题笔记(2)—— 子串、普通数组、矩阵
  • Ubuntu22.04——YOLOv8模型训练到RK3588设备部署和推理
  • 实现抗隐私泄漏的AI人工智能推理
  • Linux进程控制:fork、exit与waitpid的江湖恩怨
  • C# 根据指定路径、文件格式、创建日期清理文件夹内文件,包括子目录
  • 从Transformer到世界模型:AGI核心架构演进
  • 微信小程序 -- 原生封装table
  • UV安装与使用
  • asp.net core 项目发布到 IIS 服务器
  • 场外期权只适合上涨行情吗?
  • CSS语言的游戏AI
  • ResNet改进(18):添加 CPCA通道先验卷积注意力机制
  • 从个人博客到电商中台:EdgeOne Pages的MCP Server弹性架构×DeepSeek多场景模板实战解析
  • 1.VTK 使用CMakeLists
  • Linux 编程中的 I/O 复用
  • Element UI 设置 el-table-column 宽度 width 为百分比无效
  • React九案例中
  • 敏捷迭代实战经验分享
  • leetcode_数组 189. 轮转数组
  • Odrive0.5.1-FOC电机控制 arm_cos_f32.cpp arm_sin_f32.cpp代码实现(一)
  • 中科岩创基坑自动化监测解决方案
  • 【11】数据结构之基于线性表的查找算法
  • 【消息队列kafka_中间件】一、快速入门分布式消息队列
  • Android 中Intent 相关问题
  • STM32CubeMX-H7-12-IIC读写MPU6050模块(中)-MPU6050模块详解以及软件IIC驱动
  • Node.js是js语言在服务器编译运行的环境,什么是IP和域名
  • Python包管理工具uv简单使用
  • nginx或tengine服务器,配置HTTPS下使用WebSocket的线上环境实践!