InnoDB存储引擎-事务


1. 事务概述


事务可由一条简单的SQL语句组成,也可以由一组复杂的SQL语句组成. 事务是访问并更新数据库中各种数据项的一个程序执行单元. 在事务中的操作, 要么都做修改, 要么都不做.

对于 InnoDB存储引擎而言, 其默认的事务隔离级别 RR , 完全遵循和满足了事务的 ACID 特性.


1.1 原子性


原子性指整个数据库事务是不可分割的工作单位. 只有使事务中所有的数据库操作都执行成功, 才算整个事务成功. 事务中任何一个 SQL 语句执行失败, 已经执行成功的 SQL 语句也必须撤销, 数据库状态应该退回到执行事务前的状态.


1.2 一致性


一致性指事务将数据库从一种状态转变为下一种一致的状态. 在事务开始之前和事务结束后, 数据库的完整性约束没有被破坏.


1.3 隔离性


事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离, 即该事务提交前对其他事务都不可见.


1.4 持久性


事务一旦提交, 其结果是永久性的. 即使发生宕机等故障, 数据库也能恢复.



2. 事务的实现


隔离性是由锁实现的, 原子性, 一致性, 持久性通过数据库的 redo log 和 undo log 来完成.


2.1 redo

基本概念

重做日志用来实现事务的持久性. 其由两部分组成: ①重做日志缓冲 (redo log buffer), 其在内存; ②是重做日志文件 (redo log file), 其是持久的.

InnoDB存储引擎, 其通过 Force Log at Commit 机制实现事务的持久性, 即当事务提交的时候, 必须先将该事务的所有日志文件进行持久化, 待事务 COMMIT 操作完成后才算完成.

为了保证每次日志都写入重做日志文件, 在每次将重做日志缓冲写入重做日志文件后, InnoDB存储引擎都需要调用一次 fsync 操作.

参数 innodb_flush_log_at_trx_commit 用来控制重做日志刷新到磁盘的策略. 该参数默认1. 参数解释如下:

0事务提交时不进行刷盘, 由后台线程去每秒刷盘一次.
1(默认)事务提交时,必须调用 fsync 函数进行刷盘.
2事务提交时,仅写入操作系统的缓冲种,不进行 fsync.

随然用户可以通过设置为0或2来提高并发性能, 但是这样会丧失事务的持久性.


重做日志和二进制日志


  1. 重做日志是在 InnoDB存储引擎层产生; 而二进制日志是在 MySQL 数据库层面产生的.
  2. 二进制日志是一种逻辑日志; 重做日志是物理日志, 记录的是对于每个页的修改.
  3. 两种日志记录的时间点不同, 二进制日志是在事务提交完成后进行一次写入; 重做日志文件在事务种不断的写入.

两阶段提交


在事务提交时, 先写二进制日志, 再写InnoDB存储引擎的重做日志. 对于上述两个操作也是原子的, 即二进制日志和重做日志必须同时写入.

若二进制日志写完了, 而在 写入InnoDB存储引擎时(第三步)发生了宕机, 那么 slave 可能会接受到 master 传过去的二进制日志并执行, 最终导致主从不一致, 如下图示



为了解决上述问题, MySQL数据库在 binlog 与 InnoDB存储引擎之间采用两阶段提交. 当事务提交时, InnoDB存储引擎会先做一个 PREPARE 操作, 将事务的 xid 写入, 接着进行二进制日志的写入, 如下图演示.


MySQL数据库中InnoDB存储引擎的两阶段提交用于确保事务在主库(Master)和从库(Slave)之间的一致性。下面是对图中各个步骤的解释:

  1. innodb prepare(步骤①)
    • 在主库上,事务首先进入准备阶段。此时,InnoDB会记录事务的所有变更到内存中的事务日志(redo log),但这些变更还没有被实际应用到数据库文件中。
    • 这个阶段确保了即使在事务提交之前发生故障,数据库也能通过重做日志恢复到一致的状态。
  2. write binlog(步骤②)
    • 主库将事务的变更记录写入到二进制日志(binlog)中。二进制日志记录了所有修改数据库状态的操作,用于复制到从库或在主库故障时恢复。
    • 写入binlog是两阶段提交的第一阶段,称为“prepare”阶段。
  3. 发送binlog到从库(步骤③)
    • 主库将二进制日志发送到从库。从库接收到binlog后,将其写入到自己的中继日志(relay log)中。
    • 这个过程确保了从库能够接收到主库上所有事务的变更,以便进行数据复制。
  4. innodb write redo log(步骤④)
    • 主库在确认从库已经接收到二进制日志后,将事务的变更从内存中的事务日志(redo log)应用到数据库文件中,完成事务的提交。
    • 这个阶段是两阶段提交的第二阶段,称为“commit”阶段。

通过这种两阶段提交机制,MySQL确保了即使在主库和从库之间发生故障,事务的一致性和完整性也能得到保证。这种机制对于分布式数据库系统来说非常重要,因为它可以防止数据不一致和丢失。



3. undo


3.1 基本概念


在对数据库进行修改时, InnoDB 还会产生一定量的 undo . 这样如果用户执行的事务或语句由于某种原因失败时, 就可以用这些 undo 信息将数据回滚到修改之前的样子.

undo 是逻辑日志.

undo 存放在共享表空间.

除了 回滚操作, undo 的另一个作用是 MVCC , 即在 InnoDB 存储引擎种 MVCC 实现是通过 undo 读取之前的行版本信息, 以此来实现非锁定读.

当事务提交后, 并不会立马删除 undo , 这是因为 MVCC 中可能有使用到.



4. 事务的隔离级别及其实现原理


SQL 表中定义了四个隔离级别:

读未提交

读已提交

可重复读 (InnoDB存储引擎默认隔离级别)

串行化读

串行化读 的事务隔离级别下, InnoDB 存储引擎会对每个 SELECT 语句后自动加上 LOCK IN SHARE MODE (共享锁), 因此在整个事务隔离级别下, 就不是一致性的非锁定读了.

隔离级别的实现原理

实现隔离机制的方法主要有两种:

  • 读写锁
  • 一致性快照读,即 MVCC

MySql使用不同的锁策略(Locking Strategy)/MVCC来实现四种不同的隔离级别。RR、RC的实现原理跟MVCC有关,RU和Serializable跟锁有关。


4.1 读未提交(Read Uncommitted)


官方说法:

SELECT statements are performed in a nonlocking fashion, but a possible earlier version of a row might be used. Thus, using this isolation level, such reads are not consistent.

读未提交,采取的是读不加锁原理。

  • 事务读不加锁,不阻塞其他事务的读和写
  • 事务写阻塞其他事务写,但不阻塞其他事务读;

4.2 读已提交

MVCC

4.3 可重复读

MVCC

4.4 串行化

  • 所有 <font style="color:rgb(180, 180, 180) !important;background-color:rgb(36, 36, 41) !important;">SELECT</font> 语句会隐式转化为 <font style="color:rgb(180, 180, 180) !important;background-color:rgb(36, 36, 41) !important;">SELECT … FOR SHARE</font>,即加共享锁。
  • 读加共享锁,写加排他锁,读写互斥。如果有未提交的事务正在修改某些行,所有 select 这些行的语句都会阻塞。



5. 不好的事务习惯

  1. 在循环中提交
  2. 长事务 (应该拆解为小事务)


6. 实现原理(来自DeepSeek)


MySQL 5.7通过以下机制实现事务的ACID特性及隔离级别:

一、ACID实现原理

  1. 原子性(Atomicity)
    • 实现机制:Undo Log
      当事务执行时,所有修改会生成对应的Undo Log。若事务失败或回滚,MySQL利用Undo Log逆向操作恢复数据。例如,插入操作会记录删除的Undo Log,删除操作会记录插入的Undo Log。
  2. 持久性(Durability)
    • 实现机制:Redo Log + 刷盘策略
      事务提交时,修改先写入Redo Log(顺序写,性能高),再异步刷到磁盘。崩溃恢复时,通过Redo Log重放未落盘的修改。InnoDB的innodb_flush_log_at_trx_commit=1强制每次提交刷Redo Log到磁盘。
  3. 隔离性(Isolation)
    • 实现机制:锁(Locking) + MVCC(多版本并发控制)
      • :写操作加行锁、间隙锁(Gap Lock)、临键锁(Next-Key Lock),解决脏写和部分幻读。
      • MVCC:通过ReadView和Undo Log链实现非阻塞读,解决脏读、不可重复读。
  4. 一致性(Consistency)
    • 由应用逻辑(如约束、触发器等)和数据库其他三个特性(原子性、隔离性、持久性)共同保证。

二、四个隔离级别的实现原理

MySQL支持四种隔离级别,隔离性由MVCC共同实现:

1. 读未提交

  • 行为:允许读取其他事务未提交的数据(脏读)。
  • 实现
    • 写操作加行级排他锁(X Lock),事务结束后释放。
    • 读操作不加锁,直接读取最新版本(包括未提交的数据)。

2. 读已提交

  • 行为:事务内每次查询生成新快照,解决脏读,但存在不可重复读。
  • 实现
    • MVCC:每条SELECT语句生成独立的ReadView,仅读取已提交的数据版本。
    • 锁机制:写操作加行锁,事务提交后释放锁。例如,UPDATE操作加X锁,提交后释放。

3. 可重复读

  • 行为:事务内首次读生成快照,后续读复用该快照,解决不可重复读。通过临键锁解决幻读。
  • 实现
    • MVCC:事务开始时生成ReadView,后续所有读操作基于该视图,通过Undo Log链访问历史版本。
    • 锁机制
      • 写操作(如UPDATE)加临键锁(Next-Key Lock),锁住记录+间隙,阻止其他事务插入。
      • 普通SELECT使用快照读(无锁),SELECT ... FOR UPDATE使用当前读(加临键锁)。

4. 串行化

  • 行为:强制事务串行执行,无并发问题,性能最低。
  • 实现
    • 所有SELECT隐式转换为SELECT ... FOR SHARE(加S锁),读写互斥。
    • 写操作加X锁,读操作加S锁,通过严格的锁冲突实现串行化。

三、MVCC与锁的协作

  • MVCC核心结构
    • Undo Log链:每行记录包含DB_TRX_ID字段(最后修改的事务ID),通过Undo Log构建历史版本链。
    • ReadView:记录活跃事务ID列表,判断数据版本可见性(通过比较DB_TRX_ID与ReadView的up_limit_idlow_limit_id)。
  • 不同隔离级别的ReadView生成策略
    • RC:每次SELECT生成新ReadView。
    • RR:事务首次SELECT生成ReadView,后续复用。
  • 临键锁(Next-Key Lock)的作用
    • 锁住记录及之前的间隙(如id=5的锁范围是(-∞,5]),阻止其他事务插入,解决幻读。


四、总结

  • ACID依赖机制
    • 原子性→Undo Log,持久性→Redo Log,隔离性→锁+MVCC,一致性→三者共同保障。
  • 隔离级别权衡
    • 隔离级别越高,锁冲突越多,并发性能越低。
    • MySQL的RR通过MVCC+临键锁在性能与一致性间取得平衡。

通过理解这些机制,可以更好地设计事务逻辑和调优数据库并发性能。


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

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

相关文章

web项目的目录结构

web项目的目录结构 WEB-INF 存放class文件、jar文件和配置文件&#xff0c;对于用户来说该文件夹是不可见的WEB-INF/web.xml web应用程序的描述文件&#xff0c;用来配置资源&#xff0c;如servlet、过滤器、监听器等WEB-INF/classes 用于存放class文件&#xff0c;也是该web应…

数据结构_队列Queue(C语言实现)

一、队列的基本概念 1.队列定义 队列是一种先进先出的线性表数据结构&#xff08;First in First out&#xff09;,现实中的例子就是&#xff0c;排队购票&#xff0c;先排队的先购票&#xff0c;购完票之后直接从这个队中离开&#xff0c;后来的在这个队后面排队&#xff0c;这…

C++对CPU缓存的合理利用

缓存体系 在计算机的体系结构中,存储速度是分了好几层: CPU缓存,又分成了L1/L2/L3等多层缓存,我们暂时看成同一层。访问速度最快 内存,访问速度次之,大概是CPU缓存的几十分之一 硬盘,访问速度最慢,是内存访问速度的几十分之一 所以,在计算机体系结构中,把下一层的数…

贝叶斯定理:理解概率更新与实际场景应用

贝叶斯定理及其应用&#xff1a;从基础到实战 贝叶斯定理&#xff08;Bayes’ Theorem&#xff09;是概率论中最基础也是最强大的工具之一。它通过将先验知识与新证据结合&#xff0c;能够帮助我们在不确定的情况下做出更加精准的判断。本文将从贝叶斯定理的核心概念、公式开始…

组件之间的传递参数传递(常用父向子传递)

现在&#xff0c;有子组件<MdsWxSourceDetailref"mdsWx":rank-obj"activeRankObj":media-name"activeObj.mediaName" :error-info"activeErrorInfo" ></MdsWxSourceDetail>以上代码在MdsIndexRankDetail&#xff0…

java毕业设计-基于springboot区块链的电子病历数据共享平台设计与实现(附源码数据库文档资料)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【新启航】3D 逆向抄数的三维能力架构:数据采集工具操作 × 几何处理算法应用 × 行业场景适配技能

摘要3D 逆向抄数的落地效果依赖多维度能力协同&#xff0c;本文提出 “数据采集工具操作 - 几何处理算法应用 - 行业场景适配技能” 的三维能力架构。通过拆解各维度核心要素&#xff0c;分析数据采集工具&#xff08;激光、结构光等&#xff09;的操作要点&#xff0c;解析几何…

RocksDB 在 macOS M 系列 上运行时报错的解决方案

问题现象 项目中引入可Kafka Stream &#xff0c;Windows下启动不报错 &#xff0c;但是在 macOS M系列 环境下就会报错&#xff0c;初步定位是使用 Java 项目调用 RocksDB 时&#xff0c;运行过程中出现以下报错&#xff1a; UnsatisfiedLinkError: no rocksdbjni in java.lib…

深度学习之第五课卷积神经网络 (CNN)如何训练自己的数据集(食物分类)

简介 之前一直使用的是现有人家的数据集&#xff0c;现在我们将使用自己的数据集进行训练。 基于卷积神经网络 (CNN) 的 MNIST 手写数字识别模型 一、训练自己数据集 1.数据预处理 我们现在有这样的数据集如下图&#xff1a; 每一个文件夹里面有着对应的图片。我们要将这些…

【Big Data】AI赋能的ClickHouse 2.0:从JIT编译到LLM查询优化,下一代OLAP引擎进化路径

目录 1. 什么是ClickHouse&#xff1f; 2. 诞生背景与发展历程 3. 架构设计解析 3.1 存储引擎&#xff1a;MergeTree家族 3.2 分布式模型&#xff1a;分片与副本 3.3 执行流程&#xff1a;向量化与并行计算 4. 解决的问题与适用场景 4.1 典型问题 4.2 适用场景 5. 关…

Vue实践篇-02,AI生成代码

问题描述这个是需求&#xff1a;动态表格、表格里边下拉框&#xff0c;弹框选择基础的列表&#xff0c;还行&#xff0c;这种真的是一时不知如何是好。打算晚上吃了饭找前端同事&#xff0c;帮忙看看。晚饭前&#xff0c;AI一下看看。结果&#xff0c;惊为天人&#xff01;&…

2025-08-28-zabbix5.0创建监控项通过脚本简单实现监控oracle11g的磁盘组和表空间的使用量

title: zabbix5.0创建监控项通过脚本简单实现监控oracle11g的磁盘组和表空间的使用量 authors: Loong date: 2025-08-28使用SQLPLUS配合crontab任务 用来执行sql获取信息的脚本 /home/oracle/zabbix_oracle_check.sh #!/bin/bash #用于zabbix agent被动模式的 非入侵性的检测 #…

MySQL-Redo Log(重做日志)

MySQL 的 Redo Log&#xff08;重做日志&#xff09;是 InnoDB 存储引擎的核心组件之一&#xff0c;是保证数据库持久性&#xff08;Durability&#xff09; 和崩溃恢复&#xff08;Crash Recovery&#xff09; 的关键机制。1. 什么是 Redo Log&#xff1f;它的核心作用是什么&…

嵌入式linux相机(2)

本人从0开始学习linux&#xff0c;使用的是韦东山的教程&#xff0c;在跟着课程学习的情况下的所遇到的问题的总结,理论虽枯燥但是是基础。本人将前几章的内容大致学完之后&#xff0c;考虑到后续驱动方面得更多的开始实操&#xff0c;后续的内容将以韦东山教程Linux项目的内容…

云计算学习100天-第34天 -zabbix监控2

SourceURL:file:///home/student/Documents/zabbix.doczabbix服务器配置1. 拷贝zabbix软件包到pubserver#在此之前先从真机拷贝安装包[rootserver1 ~]# scp /linux-soft/s2/zzg/zabbix_soft/*.rpm 192.168.88.5:/root/#然后拷贝到pubserver[rootzabbixserver ~]# scp /linux-so…

猫头虎AI分享:无需OCR,基于ColQwen2、Qwen2.5和Weaviate对PDF进行多模态RAG的解决方案

无需OCR&#xff0c;基于ColQwen2、Qwen2.5和Weaviate对PDF进行多模态RAG的解决方案 关键词&#xff1a;多模态RAG、ColQwen2、Qwen2.5-VL、Weaviate 向量数据库、PDF 检索问答、无需 OCR、ColBERT 多向量、跨模态检索、MaxSim 相似度、知识库构建、AI 文档处理、视觉语言模型、…

HTML第三课:特殊元素

HTML第三课&#xff1a;特殊元素特殊元素代码展示特殊元素 不在行级元素和块级元素概念里面的元素无法控制没有宽高的元素 代码展示 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewpo…

蓝桥杯算法之基础知识(5)

目录 Ⅰ.in方法的使用 Ⅱ.字典的使用 Ⅲ.1MB 、KB、 B、 b(即bit)的转换&#xff08;必学&#xff09; Ⅳ.闰年or平年 Ⅴ.count和counter方法 1. count() 方法的使用场景 2. Counter 类的介绍 3. count() 与 Counter 的区别 4. Counter 的高级应用 5.Counter的另一种使用 Ⅵ.ma…

lesson52:CSS进阶指南:雪碧图与边框技术的创新应用

目录 一、CSS雪碧图&#xff1a;从性能优化到交互革命 1.1 技术原理与现代价值 1.2 2025年实现工具与自动化流程 1.2.1 构建工具集成方案 1.2.2 在线生成工具推荐 1.3 高级应用案例与代码实现 1.3.1 多状态按钮系统 1.3.2 响应式雪碧图实现 1.4 最佳实践与性能优化 二…

案例——从零开始搭建 ASP.NET Core 健康检查实例

1. 项目创建与基础设置 创建新项目 首先&#xff0c;创建一个新的 ASP.NET Core Web API 项目&#xff1a; dotnet new webapi -n HealthCheckDemo cd HealthCheckDemo添加必要的 NuGet 包 添加健康检查相关的 NuGet 包&#xff1a; dotnet add package Microsoft.AspNetCore.D…