• [MySQL]事务的MVCC原理与幻读


    首先要了解MVCC,MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照

    我们每行数实际上隐藏了两列,创建版本号,过期(删除)版本号,每开始一个新的事务,版本号都会自动递增

    拿user表举例子,假设我们插入两条数据,他们实际上应该长这样 , 创建版本号是递增的。

    idnamecreate_versiondelete_version
    1 张三 1  
    2 李四 2  

    这时候假设小明去执行查询,此时也是会默认开启一个事务 当前版本就是 current_version=3

    select * from user where id<=3;

    同时,小红在这时候开启事务去修改id=1的记录,小红事务版本是 current_version=4

    update user set name='张三三' where id=1;

    小红执行成功后的结果是这样的

    idnamecreate_versiondelete_version
    1 张三 1  
    2 李四 2  
    1 张三三 4  

    同时 , 还有小黑在删除id=2的数据,小黑的版本是 current_version=5,小黑执行后结果是这样的。

    idnamecreate_versiondelete_version
    1 张三 1  
    2 李四 2 5
    1 张三三 4  

    由于MVCC的原理是查找创建版本小于或等于当前事务版本,删除版本为空或者大于当前事务版本,小明的真实的查询应该是这样

    select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

    所以小明最后查询到的id=1的名字还是'张三',并且id=2的记录也能查询到。这样做是为了保证事务读取的数据是在事务开始前就已经存在的,要么是事务自己插入或者修改的

     

    幻读是这样的 , 比如下面的增加用户的例子 ,假定用户名是唯一索引不允许重复

    小明想要插入一条王五的数据 , 开启事务current_version=6查询名字为 '王五'的记录,发现不存在。

    同时小红开启事务current_version=7插入一条 王五的数据,结果是这样:

    idNamecreate_versiondelete_version
    1 张三 1  
    2 李四 2  
    3 王五 7  

    小明执行插入名字'王五'的记录,发现唯一索引冲突,无法插入,查询的时候分明看不到王五 , 但是插入总是说重复了 ,  这就是幻读。

    开源作品

    GO-FLY,一套可私有化部署的免费开源客服系统,安装过程不超过五分钟(超过你打我 !),基于Golang开发,二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的网页在线客服系统,致力于帮助广大开发者/中小站长快速整合私有客服功能
    github地址:go-fly
    官网地址:https://gofly.sopans.com

    赞赏作者

    微信交流

  • 相关阅读:
    命运(经典dp)
    A * B Problem Plus(fft)
    Hat's Fibonacci(大数加法+直接暴力)
    Can you find it?(哈希)
    String 类型与char 类型 输入
    QT 之 QMutexLocker如何安全锁住全局变量
    C语言中access/_access函数的使用实例详解
    %02x与%2x 之间的区别
    函数名&函数名取地址
    函数指针及其定义和用法,C语言函数指针详解
  • 原文地址:https://www.cnblogs.com/taoshihan/p/14434322.html
Copyright © 2020-2023  润新知