MySQL事务及实现原理

一、MySQL事务简单介绍
MySQL事务是指一组操作,它们被看作一个单独的工作单元,要么全部成功,要么全部失败回滚。在MySQL中,事务可以确保数据的一致性和完整性。

事务通常由四个关键词来描述:

1、BEGIN 或 START TRANSACTION:标志着事务的开始。
2、COMMIT:表示事务完成,并把所有的修改持久化到数据库。
3、ROLLBACK:表示事务的失败,并且撤销所有对数据库的修改。
4、SAVEPOINT:可以设置事务的一个保存点,可以回滚到此处。
在MySQL中,只有使用了InnoDB存储引擎的表才支持事务。

当执行一系列的SQL语句时,如果其中有一个SQL语句执行失败,则所有SQL语句都会回滚,也就是说之前的所有SQL操作都被撤销,数据库回到之前的状态。而只有当所有SQL语句都执行成功后,它们才会被提交到数据库中,这就保证了数据的一致性。

事务在开发中常用于保证数据的完整性和一致性,例如在进行银行转账时,需要保证从一个账户扣除的金额一定会被转入到另一个账户中,如果出现了其中一个账户扣除了金额而另一个账户没有收到对应的金额的情况,那么这就是一种数据的不一致性。在这种情况下,使用事务可以保证这个问题不会发生,因为要么所有的操作都成功,要么都失败。

二、事务特性ACID介绍

原子性(Atomicity)
事务中的所有操作要么全部成功,要么全部失败回滚。如果有一个操作失败,则整个事务都应该回滚到最初状态。

例如,假设我们有一个银行转账系统。当我们从一个账户转账到另一个账户时,需要确保资金的安全和正确性。如果转账过程中任何一个步骤失败,例如金额不足或接收方账户不存在,则必须回滚到最初状态,确保事务的原子性。

一致性(Consistency)
在事务执行过程中,数据库必须始终保持一致状态。在事务执行的任何时刻,数据库必须满足一组事务的约束条件。

例如,假设我们有一个订单系统。当用户下订单时,订单总金额必须小于用户账户的余额。如果订单总金额大于用户账户的余额,则必须回滚事务,以保持一致性。

隔离性(Isolation)
事务应该在相互隔离的环境中执行,以避免并发执行时可能出现的问题。每个事务都应该以一种完全独立的方式执行,不受其他事务的影响。

例如,如果两个用户在同一时间购买同一件商品,系统必须确保两个用户看到的是正确的库存量,并且不会出现两个用户都买到同一件商品的情况。

持久性(Durability)
一旦事务成功提交,其结果就应该持久保存在数据库中,即使系统崩溃或重新启动,数据也应该仍然存在。

例如,假设我们有一个电子邮件系统。当用户发送电子邮件时,该邮件必须被保存在数据库中,即使系统在发送电子邮件后崩溃,也必须确保该邮件在系统恢复后仍然存在。

需要注意的是,不同的数据库管理系统对事务的实现方式可能会有所不同,因此在使用事务时,需要根据具体的数据库管理系统和应用场景来选择适合的实现方式。

三、事务隔离级别

在没有隔离级别的情况下,可能会发生以下情况:

脏读(Dirty Read):一个事务读取了另一个事务还未提交的数据,如果这个事务回滚,那么读到的数据就是无效的,这种情况称为脏读。
不可重复读(Non-repeatable Read):一个事务在执行过程中多次读取同一数据,由于其他事务对该数据进行了修改,因此这些读取操作得到的结果可能不同,这种情况称为不可重复读。
幻读(Phantom Read):一个事务按照相同的查询条件两次查询,但是得到的结果集却不同。这是因为其他事务对该表进行了新增或删除操作,导致当前事务查询到的结果集不一致,这种情况称为幻读。
这些情况都是由于多个事务之间的数据相互干扰导致的,而隔离级别就是用来解决这些问题的。
 

四、MySQL事务实现原理
(一)事务原理总述
MySQL 事务是基于 InnoDB 存储引擎实现的。MySQL 的事务原理主要包括以下几个方面:

redo log:InnoDB 在执行事务时,会将事务的修改操作记录在 redo log 中,以保证事务的持久性。redo log 记录了每个事务对数据所做的修改,包括修改的行、列和修改前后的值等信息。当事务提交时,会将 redo log 写入到磁盘中,以保证数据的持久性。
undo log:InnoDB 在执行事务时,会将事务的修改操作记录在 undo log 中,以支持事务的回滚和 MVCC 功能。undo log 记录了每个事务对数据所做的修改,包括修改的行、列和修改前的值等信息。当事务需要回滚时,会使用 undo log 中的信息将数据恢复到事务执行前的状态。
MVCC:InnoDB 实现了多版本并发控制(MVCC)来支持事务的隔离性。MVCC 是通过保存多个版本的同一行来实现的,每个版本都有一个唯一的时间戳,表示该版本的生命周期。在事务执行过程中,会根据当前事务的隔离级别确定可见的数据版本,以保证事务之间的隔离。同时也可以保证并发性。
锁机制:InnoDB 通过实现共享锁和排它锁来保证数据的一致性和隔离性。共享锁用于读操作,可以多个事务同时持有;排它锁用于写操作,同一时间只能有一个事务持有。在事务执行过程中,会根据需要自动加锁和解锁,以保证数据的一致性、隔离性和并发性。
事务提交与回滚:InnoDB 支持事务的原子性,一旦事务提交,就会将修改操作写入磁盘中,并释放所有锁。如果事务发生异常或被回滚,会将修改操作回滚,并释放所有锁。
综上所述,MySQL 事务的原理涉及多个方面,包括 redo log、undo log、MVCC、锁机制以及事务提交和回滚等。这些机制共同保证了事务的 ACID 特性,同时也保证了数据的一致性、并发性和持久性。

(二)undo log 原子性分析
undo log 是 InnoDB 存储引擎中用于实现事务回滚和 MVCC 的机制之一,可以保证事务的原子性。其原理如下:

当一个事务需要修改一行数据时,InnoDB 首先将该行数据的原始值拷贝到 undo log 中,然后执行修改操作。如果事务需要回滚,可以使用 undo log 中的原始值将数据恢复到修改前的状态。如果事务提交,则可以将 undo log 中的信息删除。

在事务执行期间,每次对数据进行修改时,InnoDB 将修改前的值保存到 undo log 中,以便在事务回滚时使用。如果事务提交,则将 undo log 中的信息删除,以保证数据的一致性。如果事务发生异常或回滚,可以使用 undo log 中的信息将数据恢复到事务开始前的状态,以保证事务的原子性。

总之,undo log 通过保存数据的原始值来保证事务的原子性,可以使得数据修改操作能够撤销和回滚,并确保数据的一致性。

(三)redo log 持久性分析
redo log 是 InnoDB 存储引擎实现事务持久性的重要机制之一。在事务提交时,InnoDB 会将事务所做的修改操作记录在 redo log 中,并确保其持久化到磁盘上,从而保证数据的持久性。

具体来说,InnoDB 使用 WAL 技术(Write-Ahead Logging)来实现 redo log 的持久化。WAL 技术的基本思想是先将修改操作记录到 redo log 中,再将数据写入磁盘中。这样可以确保在出现宕机等异常情况时,可以通过 redo log 中的信息将数据恢复到事务执行前的状态,从而保证数据的一致性和持久性。

在 InnoDB 中,redo log 是以固定大小的文件形式存在的。当 redo log 文件被写满后,InnoDB 会自动创建新的 redo log 文件,并将新的修改操作记录在新的文件中。旧的 redo log 文件可以在不影响数据一致性的情况下被删除,从而实现 redo log 的循环利用。

为了确保 redo log 的持久化,InnoDB 在写入 redo log 时会采用一些优化技术,例如 write-ahead logging 和 group commit。write-ahead logging 是指在修改数据之前,先将修改操作记录在 redo log 中,再将数据写入磁盘中。这样可以确保即使出现宕机等异常情况,也可以通过 redo log 中的信息将数据恢复到事务执行前的状态。而 group commit 是指将多个事务的提交操作合并到一起,一起写入 redo log 中,从而减少写入磁盘的次数,提高写入性能。

综上所述,InnoDB 通过 WAL 技术实现 redo log 的持久化,并采用 write-ahead logging 和 group commit 等优化技术来提高写入性能。这些机制共同保证了 MySQL 数据库的事务持久性,从而保证了数据的一致性和可靠性。

(四)多版本并发控制(MVCC)隔离性分析
MVCC(Multi-Version Concurrency Control)是 InnoDB 存储引擎用来实现事务隔离的一种技术。MVCC 技术通过为每个事务保存一个可见的数据版本,来实现在并发访问的情况下保证事务的隔离性。MVCC 主要涉及以下两个方面:

版本号

在 MVCC 中,每一行数据都会有多个版本号,每个版本号对应着一个事务,表示该版本是由该事务所修改的。事务在进行修改时,会为该行数据生成一个新的版本,该版本号比当前最大的版本号大1。而查询操作只能读取版本号小于等于当前事务的版本号的数据。

事务版本链

每个事务都有一个版本链,版本链是由该事务创建的所有版本所组成的链表。在该链表上,每个版本都指向前一个版本,最后一个版本指向 NULL。版本链的作用是,当事务需要回滚时,可以沿着版本链将数据恢复到事务开始的状态。

通过使用版本号和事务版本链,MVCC 实现了 InnoDB 存储引擎的多版本并发控制,同时也保证了事务的隔离性。在执行查询操作时,根据当前事务的隔离级别,InnoDB 存储引擎会选择可见的数据版本。在可重复读的隔离级别下,InnoDB 存储引擎会将当前事务的版本号作为可见的最大版本号,因此当前事务只能读取该版本号之前的数据版本,避免了脏读和不可重复读等问题。


MVCC只在RR和RC隔离级别下生效,不同的是RR级别下在事务第一个select语句开始的时候生成快照读视图,RC级别下每次select都会生成新的读视图。

需要注意的是,MVCC 技术虽然可以有效地提高并发性,但同时也会带来一些问题,如版本链过长可能导致性能问题,同时需要占用更多的存储空间来保存多个版本。因此,在使用 MVCC 技术时,需要权衡其带来的利弊,合理地设置事务隔离级别和存储空间等参数。

(五)MySQL的锁机制一致性与隔离性性分析
锁机制主要是为了保证并发事务的一致性和隔离性。在并发事务中,多个事务可能同时操作相同的数据,如果不进行锁定,就会产生数据不一致的问题。例如,两个事务同时对同一行数据进行修改,如果没有锁机制,可能会导致数据被覆盖,从而造成数据的不一致。

通过使用锁机制,可以保证每个事务在修改数据时,都能够独占相应的资源,防止其他事务对数据的并发操作,从而保证了事务的一致性。同时,锁机制也可以通过设置不同的隔离级别来保证事务之间的隔离性,避免不同事务之间的互相干扰和影响。

因此,锁机制既保证了并发事务的一致性,也保证了事务之间的隔离性。具体原理可以概括为:在事务修改数据之前,需要先获得相应的锁,获得锁之后,事务才可以修改数据,并且在整个事务期间,这部分数据都是锁定的,其他事务如果要修改数据,必须等待当前事务提交或回滚后释放锁。

行锁与表锁
锁按照粒度可以分为行锁和表锁。表锁会锁定整张表,而行锁则只锁定需要操作的数据,显然行锁具有更好的并发性能。但是由于加锁本身需要消耗资源(获得锁、检查锁、释放锁等都需要消耗资源),因此在锁定数据较多情况下使用表锁可以节省大量资源。

InnoDB同时支持表锁和行锁,出于性能考虑,绝大多数情况下使用的都是行锁。InnoDB实现了两种标准行级锁:

共享锁(S Lock):允许事务读一行数据。在select语句后面加上lock in share mode可以显式获取共享锁

排他锁(X Lock):允许事务删除或更新一行数据。update、delete和insert语句会自动给涉及数据集加排他锁,select语句需要在语句后加上for update显式加排他锁

#排他锁
SELECT * FROM table_name WHERE ... FOR UPDATE;
#共享锁
SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;

意向锁
意向锁是一种特殊的表级锁,它是为了协调行级锁和表级锁而引入的。在进行行级锁定之前,InnoDB 存储引擎会先使用意向锁来协调并通知其它事务该行的锁定情况,从而提高并发性能。

意向锁分为两种类型:

意向共享锁(Intention Shared Lock,IS锁):表示一个事务想要在某个数据行上加共享锁,此时会先设置该表的 IS 锁。当一个事务想要在某个数据行上加行级共享锁时,需要检查该表的 IS 锁是否存在,如果存在,则说明有其它事务想要在该表上加行级共享锁,此时需要等待其它事务释放 IS 锁后再进行加锁操作。
意向排他锁(Intention Exclusive Lock,IX锁):表示一个事务想要在某个数据行上加排他锁,此时会先设置该表的 IX 锁。当一个事务想要在某个数据行上加行级排他锁时,需要检查该表的 IX 锁是否存在,如果存在,则说明有其它事务想要在该表上加行级共享锁或行级排他锁,此时需要等待其它事务释放 IX 锁后再进行加锁操作。
使用意向锁的主要目的是减少锁冲突,提高并发性能,同时保证数据的一致性。如果没有意向锁的协调机制,可能会导致不同事务之间的锁定产生冲突,从而降低并发性能。

行锁算法(记录锁+间隙锁+下一键锁)
在行锁中,有三种行锁算法:Record Lock、Gap Lock和Next-Key Lock。下面对这三种锁进行详细分析:

Record Lock(记录锁):Record Lock是在行上设置的锁,用于保证在事务中不会有其他事务对同一行进行修改。在事务中对某一行进行修改时,会对该行加上记录锁,其他事务需要对该行进行修改时,必须等待该记录锁被释放。
Gap Lock(间隙锁):Gap Lock是在索引记录之间设置的锁,用于防止其他事务在这些索引记录之间插入新的索引记录。在事务中对索引进行修改时,会对索引记录之间的间隙加上间隙锁,其他事务需要在这些间隙之间插入新的索引记录时,必须等待间隙锁被释放。
Next-Key Lock(下一键锁):Next-Key Lock是Record Lock和Gap Lock的结合体,同时锁住了索引记录和索引记录之间的间隙。在事务中对索引进行修改时,会对索引记录及其间隙加上下一键锁,其他事务需要对这些索引记录及其间隙进行修改时,必须等待下一键锁被释放。
在上述三种锁中,Record Lock用于保证行的并发访问,Gap Lock用于保证索引记录之间的并发访问,Next-Key Lock则是前两种锁的结合体,用于同时保证行和索引记录之间的并发访问。

需要注意的是,Next-Key Lock并不仅仅是Record Lock和Gap Lock的简单叠加,而是在两种锁的基础上增加了额外的约束条件。例如,Next-Key Lock会锁定当前索引记录及其间隙,并要求下一个索引记录不能被锁定。这种锁的机制可以有效地避免死锁的发生,同时保证数据的一致性和完整性。

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

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

相关文章

安装buildkit,并使用buildkit构建containerd镜像

背景 因为K8s抛弃Docker了,所以就只装了个containerd,这样就需要一个单独的镜像构建工具了,就用了buildkit,这也是Docker公司扶持的,他们公司的人出来搞的开源工具,官网在 https://github.com/moby/buildkit 简介 服务端为buildkitd,负责和runc或containerd后端连接干活,目前…

魔音音乐 5.0.1 | 界面优美,可无损下载,可播放

魔音Morin 是一款免费下载付费音乐和免费播放音乐的软件。现在听歌都需要付费,不想付费听音乐就来魔音Morin,完全免费的音乐资源非常丰富,可同步四大音乐平台歌单,还有各类音乐榜单,自带音乐社、同步歌单以及搜索音乐功…

iTOP-RK3568开发板独立NPU通过算法加特应用到以下的场景

iTOP-3568开发板采用瑞芯微RK3568处理器,内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz,RK809动态调频。集成了双核心架构GPU,ARM G52 2EE、支持OpenGLES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。 内置独立NPU,算力…

国内大语言模型哪家更好用?

大家好,我是袁庭新。 过去一年,AI大语言模型在爆发式增长,呈现百家争鸣之态。国内外相关厂商积极布局,并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务,甚至对它们产…

基于Springboot在线视频网站的设计与实现

基于Springboot视频网站的设计与实现 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:idea 源码获取:https://do…

Android 开发 TabLayout 自定义指示器长度

前言 原生 TabLayout 的指示器长度是充满整个屏幕的,但在实际开发中 UI 会设计成 指示器的长度等于或者小于标题字体长度,如图 如果设置成跟字体长度一样即使用 API: mTabLayout.setTabIndicatorFullWidth(false);或者在 xml 布局文件中的TabLayout标签…

vscode配色主题推荐:Andromeda !

vscode配色主题推荐:Andromeda ! 图标库 vscode-icons ! Andromeda:Dark theme with a taste of the universe; 仙女座:一套宇宙深空体验的哑暗色主题; 高对比度,色彩饱和; Easy Installation Open the extensions sidebar on Visual Studio CodeSearc…

判断自己的mac是macOS x64 还是macOS ARM64

在终端输入 uname -a 这样的是x64 这样的是ARM64

Skydel 24.9版本震撼发布,升级五大关键功能

在信号传播与仿真领域,Skydel软件一直是行业内的佼佼者。我们与您分享升级快讯,Skydel软件24.9.0版本已正式发布,此次更新不仅带来了五大全新功能,还在性能优化、用户体验以及远程API方面进行了全面升级,为用户带来更高…

面试题:如何能够保证T2在T1执行完后执行,T3在T2执行完后执行?——CountDownLatch原理

CountDownLatch的使用方式 CountDownLatch用于某个线程等待其他线程执行完任务再执行,与thread.join()功能类似。常见的应用场景是开启多个线程同时执行某个任务,等到所有任务执行完再执行特定操作,如汇总统计结果。 面试题:如何…

最新Java零基础知识(持续更新中......)

1. 学习前的准备 一个好的学习方法(如何更高效学习): 成为一名合格的程序员,需要具备两个关键能力: 指法速度:高效的代码输入速度。编程思想:能够用编程的方式解决现实问题的能力。 指法速度&am…

SpringBoot中的Component和ComponentScan注解工作原理

Spring IoC 容器的工作是通过管理对象的生命周期和配置来保持业务逻辑清晰,但是 Spring 容器并不会自动知道要管理哪些 bean。所以我们来告诉 Spring 应该处理哪些 bean 以及如何处理,很简单这就是 Spring 的 Component 和 ComponentScan 注释的作用所在…

算法题总结(二十)——并查集

并查集理论基础 并查集常用来解决集合连通性问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。 大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。 并查集主要有两个功能: 将…

linux介绍与基本指令

前言 本次博客将会讲解linux的来源历史、linux操作系统的理解以及它的一些基本指令。 1.linux的介绍 linux的来源 linux的来源最初还是要说到unix操作系统的。 1968年,一些来自通用电器公司、贝尔实验室和麻省理工学院的研究人员开发了一个名叫Multics的特殊操作…

C语言 | Leetcode C语言题解之第502题IPO

题目&#xff1a; 题解&#xff1a; #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX_INT_NUMBER 0x7FFFFFFEtypedef struct {int capital;int profit; } ProNode;int CompareProfit(const ProNode *a, const ProNode *b) { /* 从大到小排序 */return b->pr…

根据发生异常的汇编指令以及函数调用堆栈,从内存的角度出发,估计出问题的可能原因,确定排查方向,快速定位C++软件问题

目录 1、前言 2、初步分析dump文件 3、加载更多模块的pdb文件&#xff0c;可能能看到更多行的函数调用堆栈 4、从内存的角度去看&#xff0c;估计是访问了野指针导致的&#xff0c;沿着这个怀疑的方向快速地定位了问题 5、最后 C软件异常排查从入门到精通系列教程&#xf…

力扣OJ算法题:合并两个有序链表

—————————————————————————————————————————— 正文开始 OJ算法题&#xff1a;合并两个有序链表 思路 创建一个新的空链表&#xff08;可以用malloc优化&#xff09;和两个指针L1、L2分别指向两个链表&#xff0c;遍历两个链表&am…

Chromium 中chrome.contextMenus扩展接口实现分析c++

一、chrome.contextMenus 使用 chrome.contextMenus API 向 Google Chrome 的上下文菜单中添加项。您可以选择从右键菜单中添加的对象类型&#xff0c;例如图片、超链接和页面。 权限 contextMenus 您必须在扩展程序的清单中声明 "contextMenus" 权限&#xff0c…

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…

Ubuntu(22.04)本地部署Appsmith

Ubuntu&#xff08;22.04&#xff09;安装Appsmith 简要介绍 Appsmith 是一个开源的低代码开发平台&#xff0c;旨在帮助开发者和非开发者快速构建定制化的内部应用程序和管理工具。通过直观的拖拽界面和丰富的预配置组件&#xff0c;Appsmith 让用户无需编写大量代码即可创建…