如何理解MySQL隔离性---3个记录隐藏字段、undo日志、Read View

目录

一、3个记录隐藏字段

二、undo 日志

三、read view


一、3个记录隐藏字段

        本片文章是帮助理解上篇文章Mysql隔离性的辅助知识。

        mysql在建表时,不仅仅创建了表的结构,还创建了3个隐藏字段。

DB_TRX_ID :6 byte,最近修改( 修改/插入 )事务ID,记录创建这条记录/最后一次修改该记录的事务ID

DB_ROLL_PTR : 7 byte,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就 行,这些数据一般在 undo log 中)

DB_ROW_ID : 6 byte,隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引

         DB_TRX_ID该字段占6个字节,其中存储最近修改或插入的事务ID,也就是你当前对表进行插入或者修改此时的事务ID就会被存储到该字段中。

        DB_ROLL_PTR占7个字节,为指针指向该记录的上一个版本。

        DB_ROW_ID占6字节,如果我们建表时没有主键,InnoDB会生成一个隐藏的主键,根据该主键来建立聚簇索引。

        假设当前的建立表为:

         实际的三个隐藏字段会这样存储:

           我们目前并不知道创建该记录的事务ID,隐式主键,我们就默认设置成null,1。第一条记录也没有其他版本,我们设置回滚指针为null。      

二、undo 日志

        MySQL的日志是具有功能性和保存数据的功能的。这里的数据包括sql语句。
        我们这里理解undo log,简单理解成,就是 MySQL 中的一段内存缓冲区,用来保存日志数据的就行。

       undo log主要解决两个问题:

        1.回滚

        2.MVCC ---》多版本控制 ---》来解决隔离性和 隔离级别

        我们上文表格中的数据为 1 , a。

        此时,来了一个事务10,准备修改 a 为 abc。undo log就要发挥作用。

        事务10,因为要修改,所以要先给该记录加行锁。

        修改前,现将改行记录拷贝到undo log中,所以,undo log中就有了一行副本数据。

        事务10提交,释放锁。

        现在又有一个事务11,准备修改 abc为dcb。

        事务11,因为也要修改,所以要先给该记录加行锁。

        修改前,现将改行记录拷贝到undo log中,所以,undo log中就又有了一行副本数据。此时,新的 副本,我们采用头插方式,插入undo log。

        事务11提交,释放锁。

        这样,我们就有了一个基于链表记录的历史版本链。所谓的回滚,无非就是用历史数据,覆盖当前数 据。 上面的一个一个版本,我们可以称之为一个一个的快照

        有了这个版本链,那回滚就可以依靠它来执行,想要回滚时直接将先前的数据覆盖现在的数据即可。

        那我在insert等其他修改时,其他事务要select,此时select读取,是读取最新的版本呢?还是读取历史版本?

        当前读:读取最新的记录,就是当前读。增删改,都叫做当前读,select也有可能当前读.

        快照读:读取历史版本(一般而言),就叫做快照读。

        我们可以看到,在多个事务同时删改查的时候,都是当前读,是要加锁的。那同时有select过来,如果也要读取最新版(当前读),那么也就需要加锁,这就是串行化。 但如果是快照读,读取历史版本的话,是不受加锁限制的。

        那么,是什么决定了,select是当前读,还是快照读呢?隔离级别.

        那么,如何保证,不同的事务,看到不同的内容呢?也就是如何如何实现隔离级别?

三、read view

        Read View就是事务进行 快照读 操作的时候生产的 读视图 (Read View),在该事务执行的快照读的那一 刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)

         Read View 在 MySQL 源码中,就是一个类,本质是用来进行可见性判断的。 即当我们某个事务执行快照 读的时候,对该记录创建一个 Read View 读视图,把它比作条件,用来判断当前事务能够看到哪个版本的 数据,既可能是当前最新的数据,也有可能是该行记录的 undo log 里面的某个版本的数据。

        简化后的结构体如图所示:

         该事务执行的快照读的那一 刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID,其中最小的id放在up_limit_id中,最大的id放在low_limit_id中。

        我们现在拥有的数据版本链(undo log中的链式结构)以及当前快照读的 ReadView。

        我们将read view中的事务id与数据版本链中id做对比,就能知道当前快照读所能读到的内容。

        在画图之前要记住

/** 高水位,大于等于这个ID的事务均不可见*/

trx_id_t  m_low_limit_id

/** 低水位:小于这个ID的事务均可见 */

trx_id_t  m_up_limit_id;

        我们举个例子。

         事务4:修改name(张三) 变成name(李四)

         当 事务2 对某行数据执行了 快照读 ,数据库为该行数据生成一个 Read View 读视图

//事务2的 Read View

m_ids; // 1,3

up_limit_id; // 1

low_limit_id; // 4 + 1 = 5,原因:ReadView生成时刻,系统尚未分配的下一个事务ID creator_trx_id // 2

        此时版本链是:

        现在要是对比,看事务二是否能读到版本链中的哪一个。

//事务2的 Read View

m_ids; // 1,3

up_limit_id; // 1

low_limit_id; // 4 + 1 = 5,原因:ReadView生成时刻,系统尚未分配的下一个事务ID creator_trx_id // 2

对比:

up_limit_id<DB_TRX_ID<=low_limit_id;

并且DB_TRX_ID不在m_Ids中。

证明,事务2可以读取事务4修改之后的版本。

        整篇文章的流程为:

        我们知道了建表时会创建三个隐藏的记录字段用来记录事务的ID、地址与隐藏的主键。这三个会帮助实现回滚,回滚需要用到undo log,undo log中存放的一个个副本数据成链状表示。在不同的隔离级别下,不同事务读到的数据不一样,需要read view来协助,在read view中的low_limit_id,up_limit_id与undo log中的DB_TRX_ID做对比,来判断能读到什么版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61263.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

梳理日常开发涉及的负载均衡

负载均衡是当前分布式微服务时代最能提及的词之一&#xff0c;出于对分层、解耦、弱依赖、可配置、可靠性等概念的解读&#xff0c;一对一的模式变得不再可信赖&#xff0c;千变万化的网络环境中&#xff0c;冗余和备份显得格外重要&#xff0c;稍大型的系统就会存在大量微服务…

MES系统在机器人行业生产管理种的运用

机器人的智能水平也伴随技术的迭代不断攀升。 2021年的春晚舞台上&#xff0c;来自全球领先工业机器人企业abb的全球首款双臂协作机器人yumi&#xff0c;轻松自如地表演了一出写“福”字&#xff0c;赢得了全国观众的赞叹。 在汽车装配领域&#xff0c;一台机器人可以自主完成一…

中级课程——XSS

文章目录 介绍挖掘思路分类反射型存储型dom类型 介绍 挖掘思路 注入点&#xff1a;各种输入框 测试代码&#xff08;poc&#xff09;&#xff1a;js语句 分类 反射型 存储型 dom类型

Wisej.NET Crack,Wisej.NET的核心功能

Wisej.NET Crack&#xff0c;Wisej.NET的核心功能 Wisej.NET是一个跨平台的web框架&#xff0c;用于使用.NET和C#/VB.NET而不是HTML和JavaScript构建现代HTML5应用程序。它包含创建任务关键型web应用程序所需的一切&#xff0c;包括UI组件、会话处理、状态管理和后端集成。借助…

go-admin 使用开发

在项目中使用redis 作为数据缓存&#xff1a;首先引入该包 “github.com/go-redis/redis/v8” client : redis.NewClient(&redis.Options{Addr: config.QueueConfig.Redis.Addr, // Redis 服务器地址Password: config.QueueConfig.Redis.Password, // Redis 密码&…

如何使用Mac终端给树莓派pico构建C/C++程序进行开发,以及遇到各种问题该怎么处理,不使用任何IDE或编辑器(例如VS Code)

写本文的原因是官方的教程已经过时了&#xff0c;如果你现在按照官方教程来在 Mac 上进行配置&#xff0c;那么会遇到一堆问题&#xff0c;比如我几乎把能踩的“雷”都踩了。所以这里记录了完整过程&#xff0c;以及各种错误的原因和处理方法&#xff0c;不然以后换 Mac 了或者…

Jenkins自动化打包脚本

一、背景 jenkins可以设置定时任务打包&#xff0c;也已手动点按钮打包&#xff0c;还可以通过执行http请求打包&#xff0c;今天我们就通过shell脚本&#xff0c;通过curl命令进行jenkins打包。 二、步骤 2.1 在jenkins上构建项目 设置触发器 2.2 通过shell脚本触发远程构…

halo --- 上传图片服务器错误

文章目录 问题定位过程1、查看日志 报错的是数据库操作异常2、再次上传一张小一点的图片3、检查nginx的配置文件 原因解决 问题 上传图片时&#xff0c;报错服务器错误&#xff08;包括上传附件、博客文章插入图片、上传相册&#xff09; 定位过程 1、查看日志 报错的是数据库…

Jmeter(四) - 从入门到精通 - 创建网络测试计划(详解教程)

1.简介 在本节中&#xff0c;您将学习如何创建基本的 测试计划来测试网站。您将创建五个用户&#xff0c;这些用户将请求发送到JMeter网站上的两个页面。另外&#xff0c;您将告诉用户两次运行测试。因此&#xff0c;请求总数为&#xff08;5个用户&#xff09;x&#xff08;2…

PyTorch 微调终极指南:第 2 部分 — 提高模型准确性

一、说明 如今&#xff0c;在训练深度学习模型时&#xff0c;通过在自己的数据上微调预训练模型来迁移学习已成为首选方法。通过微调这些模型&#xff0c;我们可以利用他们的专业知识并使其适应我们的特定任务&#xff0c;从而节省宝贵的时间和计算资源。本文分为四个部分&…

【深度学习笔记】TensorFlow 常用函数

TensorFlow 提供了一些机器学习中常用的数学函数&#xff0c;并封装在 Module 中&#xff0c;例如 tf.nn Module 提供了神经网络常用的基本运算&#xff0c;tf.math Module 则提供了机器学习中常用的数学函数。本文主要介绍 TensorFlow 深度学习中几个常用函数的定义与用法&…

工厂方法模式-java实现

介绍 工厂方法模式&#xff0c;通过把工厂抽象为一个接口&#xff0c;这样当我们新增具体产品的时候&#xff0c;就只需要实现一个新的具体工厂类即可。一个具体工厂类&#xff0c;对应着一个产品。 请注意&#xff1a;在工厂方法模式中&#xff0c;一个具体工厂类只对应生产…