• MySQL到底有没有解决幻读问题?这篇文章彻底给你解答


    MySQL InnoDB引擎在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题?

    网上众说纷纭,有的说解决了,有的说没解决,甚至有些大v的意见都无法达成统一。

    今天就深入剖析一下,彻底解决这个幻读的问题。

    解决幻读问题之前,先普及几个知识点。

    1. 并发事务产生的问题

    先创建一张用户表,用作数据验证:

    CREATE TABLE `user` (
      `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(100) DEFAULT NULL COMMENT '姓名',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB COMMENT='用户表';
    

    并发事务会产生下面三个问题:

    脏读

    定义: 一个事务读到其他事务未提交的数据。

    image

    从上面的示例图中,可以看出,在事务2修改完数据,没有提交的情况。事务1已经读到事务2最新修改的数据,这种情况就属于脏读。

    不可重复读

    定义: 一个事务读取到其他事务修改过的数据。

    image

    从上面的示例图中,可以看出,在事务2修改完数据,并提交事务后。事务1第二次查询已经读到事务2最新修改的数据,这种情况就属于不可重复读。

    幻读

    定义: 一个事务读取到其他事务最新插入的数据。

    image

    从上面的示例图中,可以看出,在事务2插入完数据,并提交事务后。事务1第二次查询已经读到事务2最新插入的数据,这种情况就属于幻读。

    2. 快照读和当前读

    再普及一下快照读和当前读。

    快照读: 读取数据的历史版本,不对数据加锁。

    例如:select

    当前读: 读取数据的最新版本,并对数据进行加锁。

    例如:insert、update、delete、select for update、select lock in share mode。

    3. 再谈幻读问题

    MySQL在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题?

    只能说是部分解决了幻读问题。

    首先,在快照读的情况下,是通过MVCC(复用读视图)解决了幻读问题。

    想详细了解MVCC和读视图,可以翻一下上篇文章。

    先手动设置一下MySQL的隔离级别为可重复读

    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    

    image

    执行测试用例,验证一下:

    image

    从上面的示例图中,可以看出,事务1的两次查询,得到的结果一致,并没有查到事务2最新插入的数据。

    原因是,在可重复读隔离级别下,第一次快照读的时候,生成了一个读视图。第二次快照读的时候,复用了第一次生成的读视图,所以两次查询得到的结果一致。

    所以,在快照读的情况下,可重复读隔离级别是解决了幻读的问题。

    再测试一下,在当前读的情况下,可重复读隔离级别是否解决幻读问题:

    image

    从上面的示例图中,可以看出,事务1的两次查询,得到的结果不一致。在事务2插入数据,并提交事务后。事务1的第二次执行当前读(加了for update)的时候,读到了事务2最新插入的数据。

    原因是,在可重复读隔离级别下,每次执行当前读会生成一个新的读视图,所以能读到其他事务最新插入的数据。

    所以,在当前读的情况下,可重复读隔离级别是没有解决了幻读的问题。

    在执行上面的测试用例的时候,我忽然想到一个问题,既然select for update的当前读,出现了幻读问题,是不是其他的当前读也会复现幻读问题,比如insert。

    再执行测试用例,验证一下:

    image

    跟预想的一样,在insert当前读的情况下,也出现了幻读的问题(主键冲突)。

    那有没有什么办法?在可重复读隔离级别下,执行当前读的时候,也能解决幻读的问题?

    当然有的,唯一的办法就是加锁

    image

    事务1在执行第一次查询的时候,就对数据进行加锁(使用for update),防止其他事务修改数据,这样也就彻底解决了幻读问题。

    你觉得有什么好办法吗?

    image

  • 相关阅读:
    vscode快捷生成html标签
    关于HarmonyOS元服务的主题演讲与合作签约
    IPSec&GRE
    Java 变量之变量数据类型
    ALPHA开发板网络方案说明
    Qt listWidget 详细分析
    每日4道算法题——第004天
    Android开发使用SoundPool播放音乐
    从中间表取数更新TW付款单数据(不含表体)
    希尔排序(Shell Sort)
  • 原文地址:https://www.cnblogs.com/yidengjiagou/p/16688967.html