MySQL-事务隔离级别:READ UNCOMMITTED(未提交读)、READ COMMITTED(已提交读)、REPEATABLE READ(可重复读)、SERIALIZABLE(可串行化)

MySQL-事务隔离级别:READ UNCOMMITTED(未提交读)、READ COMMITTED(已提交读)、REPEATABLE READ(可重复读)、SERIALIZABLE(可串行化)

码农世界 2024-06-12 后端 90 次浏览 0个评论

MySQL-事务隔离级别:READ UNCOMMITTED(未提交读)、READ COMMITTED(已提交读)、REPEATABLE READ(可重复读)、SERIALIZABLE(可串行化)以及Next-Key Lock算法

      • 一、事务隔离级别
      • 二、Next-Key Lock算法

        一、事务隔离级别

        事务隔离级别是数据库系统为了确保并发访问数据时的一致性和完整性而引入的机制。不同的隔离级别定义了事务之间如何查看彼此的数据修改,以及如何防止不同事务之间的读写冲突。在MySQL中,有以下四种标准的事务隔离级别:

        1、READ UNCOMMITTED(未提交读)

        • 这是最低级别的隔离,一个事务可以读取到另一个事务尚未提交的数据变更。
        • 在这种模式下,可能会发生脏读(Dirty Read)、不可重复读(Non-Repeatable Read)和幻读(Phantom Read)现象。
        • 由于其对一致性的弱保障,实践中不建议使用。

          2、READ COMMITTED(已提交读)

          • 在这个级别上,一个事务只能看到其他事务已经提交的数据更改。
          • 可以避免脏读问题,但不能阻止不可重复读和幻读的发生。
          • MySQL的InnoDB存储引擎支持READ COMMITTED隔离级别,并且可以通过配置设置为默认隔离级别。

            3、REPEATABLE READ(可重复读)

            • MySQL InnoDB存储引擎的默认事务隔离级别就是REPEATABLE READ。
            • 在同一个事务内的多次相同查询始终会返回相同的结果,即使其他事务在此期间对数据进行了修改并提交。
            • InnoDB通过Next-Key Lock锁算法实现此隔离级别,该算法结合了行锁(Record Locks)和间隙锁(Gap Locks),从而防止了幻读的发生,但理论上仍然允许不可重复读(但在实际实现中,InnoDB的MVCC多版本并发控制机制可以保证在同一事务内读取结果一致性)。

              4、SERIALIZABLE(可串行化)

              • 这是最高的隔离级别,它强制事务按顺序执行,好像它们是唯一运行在系统中的事务一样。
              • 它提供了最严格的事务隔离,完全避免了脏读、不可重复读和幻读的问题。
              • 为了达到这一目标,数据库可能需要进行更多的锁定操作,这将显著降低并发性能。

                在MySQL中,要查询InnoDB存储引擎当前的事务隔离级别,可以使用以下SQL命令:

                对于MySQL 8.0及更高版本:

                SELECT @@transaction_isolation;
                

                对于MySQL 5.x版本:

                SELECT @@tx_isolation;
                

                执行上述任一命令后,返回结果可能是以下四种之一:

                • READ UNCOMMITTED
                • READ COMMITTED
                • REPEATABLE READ (这是InnoDB存储引擎的默认隔离级别)
                • SERIALIZABLE

                  如果返回的是REPEATABLE READ,则表明当前系统中的InnoDB存储引擎设置的默认事务隔离级别为可重复读。

                  案例说明:

                  • 考虑两个并发事务A和B,在READ COMMITTED级别下,假设事务A首先读取某行记录,然后事务B更新了该记录并提交。此时事务A再次读取同一行记录,将会看到事务B提交后的结果,即发生了不可重复读。

                  • 而在REPEATABLE READ级别下,同样的场景,事务A在第一次读取后,事务B虽然更新并提交了记录,但由于InnoDB使用了Next-Key Lock,它不仅锁定了被读取的记录,还锁定了记录前后的间隙,所以事务B无法更新,或者必须等待事务A结束才能更新,从而保证了事务A在整个事务期间看到的是最初读取时的状态,避免了不可重复读。

                  • 如果事务B插入了一条新的记录,那么事务A就可能出现幻读(即在事务A内第二次执行相同的查询时看到了事务B插入的新行)。

                  • 不过在InnoDB的REPEATABLE READ级别下,Next-Key Lock也会锁定相应间隙,从而有效防止了幻读情况的发生。

                    隔离级别脏读不可重复读幻读
                    RU
                    RC不会
                    RR不会不会
                    可串行化不会不会不会

                    这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 REPEATABLE-READ可重读 事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server) 是不同的。

                    所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLEREAD可重读 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE可串

                    行化隔离级别。因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容) ,但是你要知道的是InnoDB 存储引擎默认使用REPEAaTABLE-READ(可重读) 并不会有任何性能损失。

                    InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE可串行化 隔离级别。

                    二、Next-Key Lock算法

                    ​ InnoDB存储引擎在MySQL数据库中负责处理事务和行级锁定。Next-Key Lock是InnoDB为实现REPEATABLE READ隔离级别而采用的一种锁定机制,它结合了Record Lock(记录锁)和Gap Lock(间隙锁),旨在解决幻读问题。

                    Record Lock(记录锁)

                    记录锁锁定的是索引记录本身。如果一个事务要修改或删除一条特定的记录,那么该事务会获取对该记录的排他锁(X锁)。其他事务不能同时修改或删除该记录,但可以获取该记录的共享锁(S锁)进行读取操作。

                    Gap Lock(间隙锁)

                    间隙锁锁定的是两个相邻索引记录之间的“间隙”。当事务在一个范围内进行查询并意图更新或删除数据时,不仅锁定目标记录,还会对目标记录所在索引区间内的间隙进行锁定,防止其他事务在这个间隙内插入新的记录,从而避免了幻读的发生。

                    Next-Key Lock

                    • Next-Key Lock实际上是对Record Lock和Gap Lock的结合体。它不仅锁定了实际的数据记录,还锁定了这个记录前后的间隙。
                    • 当执行范围查询时,InnoDB会对查询条件涉及的所有索引记录及其前后间隙都施加Next-Key Lock。
                    • 例如,在索引列上有值1、3、5、8的情况下,如果一个事务对(2, 6)范围进行查询,则会锁定记录(3)以及间隙(-∞, 1)、(1, 3)、(3, 5)和(5, ∞),确保在此期间不会有任何新记录插入到这些间隙内。

                      通过使用Next-Key Lock,InnoDB可以在REPEATABLE READ隔离级别下有效地保证同一个事务内多次执行相同范围查询的结果一致性,即不会出现幻读现象。需要注意的是,对于唯一索引(如主键索引)上的等值查询,Next-Key Lock会降级为Record Lock,这是因为在一个唯一的索引上,理论上不存在间隙,因此没有必要锁定间隙。

                      MySQL-事务隔离级别:READ UNCOMMITTED(未提交读)、READ COMMITTED(已提交读)、REPEATABLE READ(可重复读)、SERIALIZABLE可串行化到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧

转载请注明来自码农世界,本文标题:《MySQL-事务隔离级别:READ UNCOMMITTED(未提交读)、READ COMMITTED(已提交读)、REPEATABLE READ(可重复读)、SERIALIZABLE(可串行化)》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,90人围观)参与讨论

还没有评论,来说两句吧...

Top