深入浅出MySQL事务实现底层原理

重要概念

事务的ACID

  • 原子性(Atomicity):即不可分割性,事务中的操作要么全不做,要么全做
  • 一致性(Consistency):一个事务在执行前后,数据库都必须处于正确的状态,满足完整性约束
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行
  • 持久性(Durability):事务处理完成后,对数据的修改就是永久的,即便系统故障也不会丢失

脏读、幻读、不可重复读

  • 脏读,读取了未提交的数据
  • 不可重复读,事务A期间读取多次b,b被其他事务影响,导致值不可重复
  • 幻读,幻读和不可重复读有点像,它是事务A期间统计多次同一批数据,统计结果不一样。原因是被其他事务影响。它们的区别主要在于前者读取精确的某几条数据,后者则是范围统计——多版本不好控制

主从复制的原理

  • 主数据库有个bin log记录了所有sql语句
  • 把主数据库的bin log的语句复制到从数据库
  • 从数据库在relay log重做日志中再执行一遍这些sql

具体而言,
在这里插入图片描述

  • 主数据库启用输出线程,输出bin log
  • 从数据库IO线程,负责从主数据库里拉取bin log,写入到relay log
  • sql线程,将relay log重做

三大日志

bin log、redo log和undo log

bin log是归档日志,用于主从复制、数据备份等。
redo log是重做日志,用于实现事务持久性。在事务在提交时断电重启后,可以正常从中恢复。
undo log为回滚日志,用于实现事务的原子性,即当事务失败时,可以全部操作都取消。

bin log和undo log都是MySQL里边服务层的概念,它记录的是逻辑记录,例如完成了什么SQL。而redo log是存储层的物理操作日志,例如“在某个数据页上做了更改”。
在执行更新语句过程,会记录 redo log 与 binlog 两块日志,以基本的事务为单位,redo log 在事务执行过程中可以不断写入,而 binlog 只有在提交事务时才写入,所以 redo log 与 binlog 的写入时机不一样。

buffer与同步

既然是日志,那就躲不开缓存和落盘策略,这当然也是很通用的一些解决实践。这里以redo log为例:
在这里插入图片描述

落盘时机,可以通过配置来指定:

  • 0,事务提交不落盘,根据异步同步线程的时间来定(通常是1s)
  • 1,每次事务提交都落盘
  • 2,写入pagecache,介于0和1之间

日志提交的事务

在进行数据库操作的时候,需要同时操作多个日志,这个时候如何保证事务性呢?例如,宕机之后,如何确保binlog和redo log的数据是一致的?
这和[[分布式事务]]做的事情基本是一样的。MySql中采用两阶段进行日志的事务提交。
在这里插入图片描述

将redo log拆成两个阶段,最终提交阶段在binlog完成之后再提交。故障恢复的时候,不管在什么阶段,一切认准binlog的提交记录。即使在redolog commit期间出错,那么只要binlog落库成功,说明redolog一定parepare完成,可以恢复提交。

这又侧面印证了一个想法:分布式事务,其实本质上是把一件很大的、多阶段的过程,拆解,细分,尽可能把最终这个影响数据一致的过程缩小到最小粒度,尽管无法完全消除,尽可能减少出错的可能性。例如上述例子,就是把耗时的redolog写入过程拆出去,缩小到最终redo log的提交这个更短、更细粒度的过程上。

MVCC如何实现

copy on write

MVCC其实体现的是copy on write的一种思想——追求数据不变性,那么就直接复制一份快照。
数据库这么大的数据量,当然不可能是真的复制一整个库、一整个表,只需要复制相应的行就可以了。那么MySQL到底是怎么实现的呢?
这是必然是一个非常复杂的机制,涉及到并发SQL复杂操作、多版本数据、各个事务之间实时的可见性管控。
核心的有两点:
数据库通过两个核心隐藏列来完成多版本记录:

  • DB_TRX_ID,当前事务ID。单调递增,因而可以通过大小确定当前事务和其他事务的可见性——对比事务ID大小即可。例如,事务ID小于它的就可见,大于它的就不可见。你可以理解,这个就是版本。
  • DB_ROLL_PTR。回滚指针,指向对应的redo log记录。上边记录了“版本号”,那么,我们就会好奇,copy on write中的精髓,copy又是怎么体现的呢?答案就是,通过回滚指针。它不会直接复制一行出来,而会在原行上边修改,如果需要找到上一个版本,就通过回滚指针找到redo log,从而找到上一个版本。

从插入和更新来分析实际分析一下:
insert,由于是新增数据,所以不需要redo log指针,只需要记录事务id。
在这里插入图片描述

update,更上边分析一样,除了记录事务ID还得记录回滚指针。
在这里插入图片描述

第二次修改,这里重点来了,多版本如何copy呢?答案是拉链:
在这里插入图片描述

可见性保证

事务之间可见性的如何保证,这个也是一大难题。
大致描述一下我的理解:MySQL在开启事务的时候,会收集当前活跃的事务列表,于是它就可以通过事务ID,加上上边的多版本数据,去分析当前存在的数据变更,自己可见的是哪些,不可见的是哪些。
下边是当前可视视图的声明。

class ReadView {
private:trx_id_t m_low_limit_id;      /* 目前出现最大的事务ID,大于等于这个 ID 的事务均不可见 */trx_id_t m_up_limit_id;       /* 小于这个 ID 的事务均可见 */trx_id_t m_creator_trx_id;    /* 创建该 Read View 的事务ID */trx_id_t m_low_limit_no;      /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */ids_t m_ids;                  /* 创建 Read View 时的活跃事务列表 */m_closed;                     /* 标记 Read View 是否 close */
}

处于最大、最小ID之间的,就是活跃但不可见的事务列表。
在这里插入图片描述

事务的实现

好了,这下我们有充足的知识可以来讨论如何实现事务了。

整体方案

  • 原子性,undo log,事务中断恢复
  • 持久性,redo log,同步写回磁盘,提交断电时可恢复
  • 隔离性,通过读写锁和MVCC来实现的
  • 一致性,通过上述三者来实现的。

隔离性,对应四种隔离级别

READ UNCOMMITTED

在这里插入图片描述

读不加锁,不排斥写。

  • 优点:读写并行,性能高
  • 缺点:造成脏读

READ COMITTED

在这里插入图片描述

读不加锁,读写分离。但这里MVCC的方式,是每次读的时候,都会读取不同版本,这会造成不可重复读问题。

当然,也有幻读问题。

REPEATABLE READ(Mysql默认隔离级别)

最简单的方式,读写锁实现,让读写串行:

在这里插入图片描述

  • 优点:实现起来简单
  • 缺点:无法做到读写并行

MVCC

在这里插入图片描述

通过版本控制,解决版本不同问题产生不可重复读的问题

  • 优点:读写并行
  • 缺点:实现的复杂度高,依然存在幻读的问题

InnoDB是可以解决幻读的,大致的思想也很简单, Next-key Lock对查询间隙进行加锁,不让插入自然也就不会有幻读问题。

SERIALIZABLE

在这里插入图片描述

注:
可线性化和可串行化,听起来很像,感觉也很像。其实不太一样,两者是分布式数据库中的一致性模型,但后者主要指事务中的一种隔离级别。
我的理解是,最大的区别在于,可线性化要求对于所有事件,都必须满足所有时刻的先后可见性。而可序列化仅需要保证多个并行的事务和某个事务序列结果一致即可。
这非常像Java中重排和happen-before的理念。

参考

  1. https://blog.csdn.net/weixin_36380516/article/details/107572412
  2. https://javaguide.cn/database/mysql/innodb-implementation-of-mvcc.html#readview

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

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

相关文章

vb.net打开CAD指指定路径文件

首先打开vsto,创建窗体,添加一个按钮,双击按钮录入代码: Public Class Form1Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.ClickDim cad As Objectcad CreateObject("autocad.Application")cad…

火箭升空AR虚拟三维仿真演示满足客户的多样化场景需求

在航空工业的协同研发领域,航空AR工业装配系统公司凭借前沿的AR增强现实技术,正引领一场革新。通过将虚拟信息无缝融入实际环境中,我们为工程师、设计师和技术专家提供了前所未有的共享和审查三维模型的能力,极大地提升了研发效率…

Go 语言简介 -- 高效、简洁与现代化编程的完美结合

在现代软件开发领域,选择合适的编程语言对于项目的成功至关重要。Go 语言(又称 Golang )自 2009 年由Google发布以来,以其简洁的语法、高效的并发模型以及强大的性能,迅速成为开发者们的新宠。Go语言不仅融合了传统编译…

博客开始使用 Cache Master 缓存插件

明月在给大家推荐 Cache Master 插件的时候(可参考【推荐个比较纯正的缓存插件——Cache Master】一文),仅仅是在其他站点上试用了一下,今天明月正式在博客上用上了 Cache Master,没有想到对 Dragon 主题的支持竟然是出…

MYSQL之安装

一,下载仓库包 wget -i -c https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm二,安装仓库 yum -y install mysql80-community-release-el7-3.noarch.rpmsed -i s/gpgcheck1/gpgcheck0/g mysql-community.repo三,安装MY…

GMSL图像采集卡,适用于无人车、自动驾驶、自主机器、数据采集等场景,支持定制

基于各种 系列二代 G MS L 图像采集卡(以下简称 二代图像采集卡)是一款自主研发的一款基于 F P G A 的高速图像产品,二代图像采集卡相比一代卡,由于采用PCIe G en 3 技术,速度和带宽都相应的有了成 倍的提高。该图像…

DataGrip软件执行已将创建好的sql文件步骤

一、在需要导入sql文件上右击找到SQLScript ,然后点击 Run SQL Script 二、找到sql文件,点击OK就可以了

怎么搭建微信留言板功能

在信息爆炸的时代,微信已经成为了我们日常生活中不可或缺的一部分。它不仅仅是一个简单的聊天工具,更是一个充满无限可能的营销平台。今天,我要向大家介绍的是如何在你的微信平台上搭建一个独具特色的留言板功能,让用户能够自由发…

福昕PDF使用技巧

因为突然间学校的企业版WPS突然很多功能就不能使用了,所以转向福昕PDF。 一、合并文件 添加需要合并的文件,可以使用ctrla等方式全选 找到最上方的“合并文件” 二、文本注释

攻击者常用的五个数据中转网站

近来,各种数据中转网站被攻击者广泛用于传播代码片段、配置文件和各种文本数据,尽管这为研究人员提供了观察的窗口,但敏感信息被上传到互联网上时,也会对受害者构成巨大威胁。 这些网站通常并不需要注册或者身份验证,…

谷歌快速收录怎么做?

快速收录顾名思义,就是让新的的网页内容能够迅速被谷歌搜索引擎抓取、索引和显示在搜索结果中,这对于做seo来说非常重要,因为它有助于新发布的内容尽快出现在谷歌的搜索结果中,从而增加网站的流量 想做谷歌快速收录谷歌推荐了几种…

Linux入侵应急响应与排查

入侵者在入侵成功后,往往会留下后门以便再次访问被入侵的系统, 而创建系统账号是一种比较常见的后门方式。 查询特权用户特权用户(uid 为0) awk -F: $30{print $1} /etc/passwd 查找远程可以登录的账户 awk /\$1|\$5|\$6/{print $1} /etc/shadow $1&a…

【链表】Leetcode 92. 反转链表 II【中等】

反转链表 II 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#x…

golang、laravel对接stripe海外支付接口的总结和流程(通俗易懂)

目录 stripe是什么&#xff1f; 环境 配置后台 首先让管理员把你设置成为开发者 然后进入后台 然后你要创建产品&#xff0c;开单周期要写每天&#xff0c;我这里理解成每天都会有人买的 获取产品id 获取密钥&#xff0c;后续代码需要用到 支付代码 唤起支付页面 测…

Jenkins pipeline发布前端项目

说明&#xff1a;第一次使用jenkins生成pipeline片段&#xff0c;做个记录... 1.全局工具配置添加自定义node版本 2.系统管理添加前端应用部署服务器 2.1 点击高级选择账号密码验证方式&#xff0c;添加服务器的用户和密码 3.系统管理--凭据--系统--全局凭据--添加自己的git凭据…

网站笔记:huggingface model memory calculator

Model Memory Utility - a Hugging Face Space by hf-accelerate 这个工具可以计算在 Hugging Face Hub上托管的大型模型训练和执行推理时所需的vRAM内存量。模型所需的最低推荐vRAM内存量表示为“最大层”的大小&#xff0c;模型的训练大约是其大小的4倍&#xff08;针对Adam…

PL5358A 单芯锂离子/聚合物电池保护IC芯片

一般说明 PL5358A系列产品是锂离子/聚合物电池保护的高集成解决方案。PL5358A包含先进 的功率MOSFET&#xff0c;高精度电压检测电路和延迟电路。5358A被放入一个超小的SOT23-5封装&#xff0c;只有一个外部元件&#xff0c;使其成为理想的解决方案&#xff0c;在有限的…

NDIS协议驱动(一)

Microsoft Windows 操作系统使用基于 1978 年国际标准化组织 (ISO) 开发的七层网络模型的网络体系结构。 ISO 开放系统互连 (OSI) 参考模型将网络描述为“一系列协议层&#xff0c;具有分配给每个层的一组特定函数。 每个层都向更高层提供特定的服务&#xff0c;同时阻止这些层…

中国区 AWS 控制台集成 ADFS 登录

前言 本文将使用一台 Windows Server 2019 服务器实现自建 AD ADFS 环境集成到中国区 AWS 控制台进行单点登录. 参考文档: https://aws.amazon.com/cn/blogs/china/adfs-bjs/ 配置 AD 生产环境建议先给本地连接设置静态 IP 地址, 不设置也没事儿, 后面配置功能的时候会有 W…

设计模式11——代理模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 代理模式&#xff08;Proxy&am…