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

MySQL事物隔离级别详解

目录

事物隔离级别总结

实际情况演示

脏读(未提交)

避免脏读(读已提交)

不可重复读

可重复读

幻读


事物隔离级别总结

SQL标准定义了四种事物隔离级别,用来平衡事物的隔离性(Isolation)和并发性能。级别越高,数据一致性越好,但并发性可能越低,这四个级别是:

  • READ-UNCOMMITTED(读取未提交) :最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。这种级别在实际应用中很少使用,因为它对数据一致性的保证太弱。
  • READ-COMMITTED(读取已提交) :允许读取并发事务已经提交的数据,可以阻止脏读但是幻读或不可重复读仍有可能发生。这是大多数数据库(如 Oracle, SQL Server)的默认隔离级别。
  • REPEATABLE-READ(可重复读)对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改可以阻止脏读和不可重复读,但幻读仍有可能发生。MySQL InnoDB 存储引擎的默认隔离级别正是 REPEATABLE READ。并且,InnoDB 在此级别下通过 MVCC(多版本并发控制) 和 Next-Key Locks(间隙锁+行锁) 机制,在很大程度上解决了幻读问题。
  • SERIALIZABLE(可串行化)最高的隔离级别,完全服从 ACID 的隔离级别所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读

 默认级别查询:

MySQL InnoDB存储引擎的默认隔离级别是REPEATABLE READ。可以通过一下命令查看:

mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+

 InnoDB 的 REPEATABLE READ 对幻读的处理:

标准的SQL隔离级别定义里,重复读是无法防止幻读的。但InnoDB的实现通过一下机制很大程度上避免了幻读:

  • 快照读:普通的SELECT语句,通过MVCC机制实现。事物启动时创建一个数据快照,后续的快照读都读取这个版本的数据,从而避免了看到其他事务新插入到幻读(幻读)或修改的行(不可重复读)。
  • 当前读: 像SELECT...FOR UPDATE ,SELECT ..LOCK IN SHARE MODE ,INSERT,UPDATE,DELETE这些操作。InnoDB使用Next-Key来锁定扫描到索引记录及其间的范围(间隙),防止其他事务在这个范围内插入新的记录,从而避免幻读。Next-Key Lock是行锁(Record Lock)和间隙锁(Gap Lock)的组合。

值得注意的是,虽然通常认为隔离级别越高,并发性越差,但InnoDB存储引擎通过MVCC机制优化了可重复读级别。对于常见的只读或读多写少的场景,其性能与读已提交相比可能没有显著差异。不过,在写密集型且并发冲突较高的的场景下,RR的间隙锁的机制可能比RC带来更多的锁等待。

此外,在某些特定场景下,如需要严格一致性分布式事务(XA trransactions),InnoDB可能要求或推荐使用串行化隔离级别来确保原句数据的一致性。

《MySQL 技术内幕:InnoDB 存储引擎(第 2 版)》7.7 章这样写到:

InnoDB存储引擎提供了对XA事物的支持,并通过XA事务来支持分布式事务的实现。分布式事务指的是允许有多个事务资源(transactions resource)参与到一个全局的事务中。事务资源通常是关系型数据库系统,但也可以是其他类型的资源。全局事务要求在其中的所有参与的事务要么提交,要么都回滚,这对于事务原有ACID要求又有了提高。另外,在使用分布式事务时,InnoDB存储引擎的事务隔离级别必须设置为串行化。

实际情况演示

下面会使用2个命令行MySQL,模拟多线程(多事务)对同一份的数据的脏读问题。

MySQL命令行的默认设置中事务都是自动提交的,即执行SQL语句就会马上执行COMMIT操作。如果要显式地开启一个事务需要使用命令:START TRANSACTION

我们可以通过下面的命令来设置隔离级别。

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

 我们再看一下我们在下面实际操作中使用到一些并发控制语句:

  • STRAT TRANSACTION | BEGIN:显式地开启一个事务
  • COMMIT:提交事务,使得对数据库做的修改成为永久性。
  • ROOLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。

脏读(未提交)

避免脏读(读已提交)

不可重复读

还是刚才上面的读已提交的图,虽然避免了读未提交,但是出现了,一个事务还没有结束,就发生了不可重复读问题。

可重复读

幻读

演示幻读出现的情况

SQL脚本1在第一次查询工资为500的记录当时只有一条,SQL脚本2插入了一条工资为500的记录,提交之后,SQL1脚本在同一个事务中再次出现读查询发现了两条工资为500的记录这种就是幻读。

解决幻读的方法

解决幻读的方法有很多,但是它们核心的思想就是一个事务在操作某张表数据的时候,另外一个事务不允许新增或者是删除这张表中的数据了。解决幻读的方式主要有一下几种:

  • 将事务隔离级别调整为串行化
  • 在可重复读的事务级别下,给事务操作的这张表添加表锁。
  • 在可重复读的事务级别下,给事务操作的这张表添加Next-Key Lock(Record Lock +Gap Lock)。
http://www.lqws.cn/news/537859.html

相关文章:

  • 笔记04:层叠的定义及添加
  • 链表基本功(相交链表)
  • Ubuntu通过防火墙管控Docker容器
  • Go语言与云原生:Kubernetes Operator开发全流程
  • Selenium+Pytest自动化测试框架实战
  • 第十二章:温度传感器拓展模块
  • 《汇编语言:基于X86处理器》第5章 过程(1)
  • LeetCode 2311.小于等于 K 的最长二进制子序列:贪心(先选0再选1)-好像还是比灵神写的清晰些
  • Python打卡:Day36
  • 永磁无刷电机旋转原理
  • 数据结构进阶 第六章 树与二叉树
  • 15.三数之和
  • 教程 | 一键批量下载 Dify「Markdown 转 Docx」生成的 Word 文件(附源码)
  • GraphQL注入 -- GPN CTF 2025 Real Christmas
  • Spring Boot高并发 锁的使用方法
  • 与 AI 聊天更顺畅:cat_code.py
  • [深度学习][python]yolov13+bytetrack+pyqt5实现目标追踪
  • 数据结构进阶 - 第九章 排序
  • Docker安装Mysql、配置文件挂载、修改Mysql编码
  • C2远控篇CC++SC转换格式UUID标识MAC物理IPV4地址减少熵值
  • 什么是谓词下推?
  • leetcode:50. Pow(x, n)(python3解法,数学相关算法题)
  • 苍穹外卖day3--公共字段填充+新增菜品
  • 桌面小屏幕实战课程:DesktopScreen 11 SPI 水墨屏
  • 超声波清洗机相对于传统清洗方法有哪些优势?
  • 博客系统测试报告
  • 互联网大厂Java求职面试:RAG系统架构设计与实战
  • 通达信 股道主力资金 幅图分析系统
  • 攻防世界-MISC-4-2
  • vue3 定时刷新