zoukankan      html  css  js  c++  java
  • 【MySQL】聊一聊MySQL的幻读

    问题:

    1. 什么是幻读?
    2. MySQL解决幻读了么?

    幻读场景

    场景一

    场景一

    现象:事务A明明查出来没有数据ID为3的数据,但是插入的时候却报了主键冲突的问题,出现幻读的场景

    场景二

    场景二

    事务A在更新name为cc的数据之前明明查出来只有一条匹配的,但是更新结果却对两条数据产生了影响,出现了幻读的场景。

    当前读和快照读

    如果只看上面的两种场景的话其实我们可以下结论说MySQL在RR级别下没有解决幻读的问题,但是网上关于幻读的讨论一大堆,而且官方也没有给出一个明确的定性,到底是什么原因呢?这时候就要引出MySQL的当前读与快照读

    快照读

    在RR级别下,通过MVCC机制,可以让数据变得可重复读,而MVCC实现原理就是在开启事务后的第一次select操作的同时创建一份快照,接下来再执行select操作就是从快照中读取的。

    注意:

    1. 第一次select的时候才会创建快照,你可以测试在开启事务A之后,先不执行select操作,这时候让事务B插入一条数据,接着事务A再执行select的话会查出来事务B插入的数据。
    2. 快照读针对的是select操作,从上面可以看到我们在事务A的最后一步select的话读取到的是快照中的数据,但是update,delete,insert读取到的却不是

    快照读虽然解决了可重复读,但是他可能让读出来的数据不是最新的数据,而是历史数据

    当前读

    MySQL对于update、insert、delete使用的都是当前读的模式,再执行这几个操作的时候读取到的都是当前最新的数据。别的事务提交的数据也可以查到,甚至别的数据未提交的数据也可以查到,你可以测试下在事务A插入一个id为10的数据但是不提交,这时候如果事务B同样插入一个数据为10的数据的话就会阻塞,你可以认为加了一个排他锁,你也可以站在另外一个角度认为他查询到了其他的事务操作的数据。

    MySQL三种行锁

    1. Record Lock:对单个行记录进行加锁
    2. Gap Lock:间隙锁,对一个区间范围加锁,但不包含数据本身,所以叫做间隙,而GAP锁提出的原因就是为了解决幻读问题
    3. Next-Key Lock:他是第一种和第二种的合体,这样就可以在锁住范围的同时锁住本身,对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

    结论

    再了解了上面的问题以后我们再来看看为什么有的人认为MySQL在RR级别下解决了幻读,有的认为没有解决。

    我认为这是对幻读的定位、认知不同。

    在认为解决的人看来。幻读不能把快照读和当前读混起来操作,这是两种使用方式。幻读应该是在快照读或当前读本身的场景下,两次读取结果一致,而MySQL在快照读的情况下通过MVCC已经解决了,在当前读的情况MySQL通过next-key来解决了。

    在认为没有解决的人看来。幻读应该不关心快照读还是当前读,只要第二次读(这个读比较广泛)读出了第一次读没有的数据就叫幻读,在这种定义下,我们可以从上面的两种场景看出,MySQL没有解决。

    参考

    幻读场景

    当前读和快照读

    Innodb 中 RR 隔离级别能否防止幻读

    美团

  • 相关阅读:
    条款04:确定对象在使用前已经被初始化
    条款06:若不想使用编译器自动生成的函数,就应该明确拒绝
    计算机操作系统之死锁的原因和必要条件
    条款10:令operator=返回一个reference to *this
    条款02:尽量以const,enum,inline代替#define
    条款11:在operator=处理自我赋值
    计算机操作系统之进程与线程
    堆排序
    NodeJS For Windows
    我常用的linux命令
  • 原文地址:https://www.cnblogs.com/colin-xun/p/13746292.html
Copyright © 2011-2022 走看看