• MySQL隔离性实现原理


    MySQL数据库读写并发存在线程安全问题,比如脏读、幻读、不可重复读
    MySQL实现隔离性本质是通过MVCC和Read View

    多版本并发控制(MVCC):
    是MySQL解决读写冲突的一种无锁的策略,根据事务开始的先后顺序,按递增为事务分配不同的事务ID

    记录的一些隐藏字段:
    DB_TRX_ID:最近修改改记录的事务ID
    DB_ROLL_PTR: 回滚指针,指向这条记录的上一个版本
    DB_ROW_ID: 隐藏主键,如果数据表没有主键, InnoDB以 DB_ROW_ID 生成一个聚簇索引

    记录的不同的版本通过回滚指针相连形成了版本链
    假如有一条记录是姓名为张三,ID为7的事务修改姓名为李四,ID为9的事务修改姓名为王五,形成的版本链大致如下:
    在这里插入图片描述

    回滚操作就是用历史版本覆盖当前版本,一个个版本可以叫做一个个快照

    版本链存在MySQL的undo日志当中,undo日志可以理解为MySQL中的一段缓冲区

    当前读和快照读:
    读取某条记录的最新版本就是当前读,读取历史版本叫做快照读。
    增删改都是当前读,需要加锁,select操作也有可能是当前读,这时也需要加锁
    这时候这些当前读就是串行化的。快照读读取的是历史版本,所以不用加锁,这就是mvcc提高读写并发效率的方式。

    select是当前读还是快照读取决于隔离级别,而确认读取版本链中的哪个版本还需要Read View

    Read View 是MySQL 源码中的一个类
    事务进行 快照读 的时候生产读视图 (Read View),可以记录维护系统当前活跃的事务的ID等信息。

    Read View类成员中影响快照读读取哪个版本的成员有如下几个:

    m_ids;               //Read View生成时刻活跃事务ID的列表
    
    up_limit_id;         //m_ids列表中最小的ID
    
    low_limit_id;        //目前已出现过的事务ID的最大值+1
                         
    creator_trx_id       //创建该ReadView的事务ID
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    确认读取版本链中的哪个版本就是通过版本中的ID和上面的类成员比较
    在这里插入图片描述

    如果隔离级别是读提交,可以认为没有隔离性,不用上述的方式,隔离级别如果是串行化,操作都加锁自然也不需要上述方式,读提交和可重复读这两种隔离级别都会用到MVCC+Read View的方式来确定读取到的记录是哪一个版本

    而读提交和可重复读隔离级别不同,也就是快照读读到的版本不同的原因在于:
    读提交隔离级别在某个事务中的每一次快照读都会产生新的Read View,而可重复读隔离级别在某个事务中只在第一次快照读时产生Read View,之后不管其他事务做什么,这个Read View都不变。

    总之,MySQL的隔离性本质的实现原理就是多版本并发控制(MVCC)和读视图(Read View)同时起作用。

  • 相关阅读:
    [.NET学习] EFCore学习之旅 -3 一些其他的迁移命令
    中标麒麟操作系统网络应用服务部署与实现
    Docker--harbor私有仓库部署与管理
    OFDM同步技术
    Neo4j 基本语法
    Java基础题(巩固语法)
    08、SpringCloud之SpringBoot-Admin监控组件学习笔记
    使用PdfSharp从模板生成Pdf文件
    网课答案公众号搭建-网课题库接口
    本周Github有趣开源项目:Rspress等6个
  • 原文地址:https://blog.csdn.net/sqjddb/article/details/126198258