「Mysql 事务 隔离级别」 读提交和可重复读的区别

本文深入探讨了数据库的四种隔离级别:读未提交、读已提交、可重复读和串行化,以及它们对应的现象——脏读、丢失修改、不可重复读和幻读。重点解析了可重复读如何解决不可重复读问题,以及InnoDB和XtraDB如何利用MVCC和next-key-lock解决幻读。最后,介绍了各个隔离级别的应用场景及其优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前提

首先我们应该先明确 Mysql的四种隔离级别和四种对应的现象

  • 隔离级别:
    读未提交、读已提交、可重复读、串行化
  • 现象:
    脏读、丢失修改、不可重复读、幻读

二、先说结论

读提交和可重复读都是一种隔离级别,可重复读解决了读提交本身未解决的 关于同一事务多次读取同一记录不一致的问题

怎么解决的?

对比记忆:
在读提交中: 事务A第一次读取数据,事务B修改同一数据但并未提交,事务A第二次读取数据,此时事务A读取数据并没有变化,然后将事务B提交,事务A第三次读取数据,才能读到数据的修改。
在可重复读中: 事务A第一次读取数据,事务B修改同一数据但并未提交,事务A第二次读取数据,此时事务A读取到的数据仍是修改之前的结果,然后将事务B提交,事务A第三次读取数据,(区别来了!)此时事务A读取到的数据仍然没有变化。 就是说在事务A提交之前,即使事务B修改并提交了数据,事务A读取的结果也没有任何变化,所以才会可重复读

说白话:
读提交在事务A提交之前,可以读到事务B修改并提交的数据
可重复读隔离级别下,事务A提交之前,无论事务B怎么修改怎么提交,读到的都是一样的数据。除非事务A也提交了,才会读到事务B作出的更改。

三、讨论分析

在明确前提定义之后,我们开始讨论;(具体不明白定义的朋友,我会将定义贴到文末)

首先最低的隔离级别是读未提交 该级别的开销小,并发量高,但是会带来我们所说的脏读现象 ——也就是事务A可以读取到事务B未提交的数据,也就是脏数据。
那么我们为了解决脏读 这一现象,出现了下一隔离级别读已提交 ——只能读到事务B提交之后的数据,在提交之前所做的修改,事务A是读不到的(不可见的)。
所以,在我们只能读到提交的数据之后,便出现了第三种现象,即在事务A开启后多次读取同一数据,在多次读取中间,事务B对数据进行了修改然后提交,提交之后事务A再读,导致事务A结束之前多次读取的数据不同,所谓的不可重复读这个是现象)。
解决不可重复读这一现象,需要用到下一隔离级别 这个隔离级别叫做 可重复读。但是可重复读仍然会有遗留现象,即幻读——当事务A在读取某个范围内记录时,事务B在该范围内插入了新的记录。

最终,解决幻读就用到了串行化这一隔离级别,通过强制事务串行之行,避免幻读问题,他会在读取的每一行数据上加锁🔒,所以会导致大量的超时和锁征用问题。

InnoDB和XtraDB数据引擎用到了MVCC(多版本并发控制协议,读不加锁读写不冲突,可以了解一下通过隐藏列、undolog指针和ReadView实现)。锁方面解决幻读用到了 next-key-lock,相当于间隙锁和记录锁,不但会锁住一个范围,还会锁住记录本身。

四、 隔离级别和现象的定义:

READ UINCOYNITTED (读未提交)(很少用)
在READ UNCONMITTED 级别,事务中的修改,即使没有提交,对其他事务也都是可见
的。事务可以读取未提交的数据,这也被称为胜读 (Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCONNIITTED 不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。

READ COMMITTED (提交读)
大多数数据库系统的默认隔离级别都是 READ COMMITTED (但 MysQL 不是)。READ COMMITTED 满足前面提到的隔高性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级別有时候也叫做不可重复读 (nonrcpcatable read),因为两次执行同样的查询,可能会得到不一样的结果。

REPEATABLE READ(可重复读)
REPEATABLE READ 解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read) 的向题。所谓幻谈,指的是当某个事务在该取某个范国内的记录时,另外一个事务又在该范围内插人了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行 (Phantom Row)。IanoDB 和XtraDB 存储引擎通过多版本并发控制 (MVCC, Multiversion Concurrency Control)解决了幻读的问题。

SERIALIZABLE(可串行化)
SERIALIZABLE 是最商的隔离级别。它通过强制事务串行执往,避免了前面说的幻读的问题。简单来说,SERIALIZABLE 会在读取的每一行数据上都加锁,所以可能导致大量的超时和领争用的问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

脏读
当事务A访问数据,此时事务B对同一数据进行修改,在事务B提交之前事务A仍然可以读取到事务B修改的数据;

丢失修改
当事务A修改数据,事务B在之后修改数据,那么事务A修改的数据结果也将会丢失,也就是最后只能查询到B修改的数据;

不可重复读
事务A读取数据,由于并发事务B对数据进行修改然后提交,导致的事务A再次读取,两次读取的结果不相同的现象。

幻读
事务A读取数据后,并发事务B插入或删除数据,导致后来事务A查询的结果与第一次事务A查询结果不同的现象。和前者的区别是不可重复读注重事务B对原数据的修改,而幻读是注重与事务B对原数据的增加或删除,注重于记录条数增加减少。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值