【数据库】mysql事务

news2024/11/14 17:03:32

一、事务的基本概念

1、事务的定义

事务可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成。。

  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
  • 事务用来管理 insert、update、delete 语句

2、事务的特性

事务需遵循ACID四个特性:

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

  • C(consistency),一致性。一致性指事务将数据库从一种状态转变为另一种一致的状态。在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。

  • I(isolation),隔离性。数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务的隔离性要求每个读写事务的对象与其他事务的操作对象能相互分离,即该事务提交前对其他事务都不可见,这通常使用 来实现。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)

  • D(durability) ,持久性事务一旦提交,其结果就是永久性的,即使发生宕机等故障,数据库也能将数据恢复。持久性保证的是事务系统的高可靠性,而不是高可用性。

 3、事务的类型

(1)扁平事务(Flat Transactions)

是事务类型中最简单的一种,而在实际生产环境中,这可能是使用最为频繁的事务。在扁平事务中,所有操作都处于同一层次,其由BEGIN WORK开始,由COMMIT WORK或ROLLBACK WORK结束。处于之间的操作是原子的,要么都执行,要么都回滚

(2)带有保存点的扁平事务(Flat Transactions with Savepoints)

除了支持扁平事务支持的操作外,允许在事务执行过程中回滚到同一事务中较早的一个状态(保存点),这是因为可能某些事务在执行过程中出现的错误并不会对所有的操作都无效,放弃整个事务不合乎要求,开销也太大。保存点(savepoint)用来通知系统应该记住事务当前的状态,以便以后发生错误时,事务能回到该状态。

保存点在事务内部是递增的,ROLLBACKU不影响保存点的计数,单调递增编号能保持事务执行的整个历史过程 。

当发生系统崩溃是,所有的保存点都将消失,因为其保存点是易失的,这意味着当进行恢复时,事务需要从开始处重新执行,而不能从最近的一个保存点继续执行

(3)链事务(Chained Transactions)

可视为保存点模式的一个变种。链事务的思想是:在提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式地传给下一个要开始的事务。注意,提交事务操作和开始下一个事务操作将合并为一个原子操作。这意味着下一个事务将看到上一个事务的结果,就好像在一个事务中进行的。

假设T2事务执行过程中系统崩溃导致执行失败,将会从T2的起始位置重新执行,T1事务在崩溃之前已经完成提交。 链事务回滚只限于当前事务,即只能恢复到最近一个的保存点。

 

(4)嵌套事务(Nested Transactions)

是一个层次结构框架。有一个顶层事务(top-level transaction)控制着各个层次的事务。顶层事务之下嵌套的事务被称为子事务(subtransaction),其控制每一个局部的变换。

  • 子事务既可以提交可以回滚,但是它的提交操作并不会马上生效,除非其父事务已经提交。因此,任何子事务都在顶层事务提交后才真正提交。 
  • 树中的任意一个事务的回滚会引起其他的所有子事务一同回滚,故子事务仅保留A、C、I特性,不具备D的特性
  • 只有叶子节点的事务才能访问数据库,发送消息,获取其他类型的资源。而高层的事务仅负责逻辑控制,决定何时调用相关的子事务。即使一个系统不支持嵌套事务,可以通过保存点技术来模拟嵌套事务。

 

(5)分布式事务

通常是一个在分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。对于分布式事务,同样需要满足ACID特性,要么都发生,要么都失效。

假设一个用户使用ATM机进行跨行转账操作,例如老王持卡从招商银行储蓄卡转账10000元到工商银行储蓄卡中。此时可以报ATM机视为节点A,招商银行后台数据库视为节点B,工商银行后台数据库视为节点C,那么转账操作可以分解为以下步骤:

① 节点A发出转账命令

② 节点B执行储蓄卡余额减去10000

③ 节点C执行储蓄卡余额加上10000

④ 节点A通知用户操作成功或者通知用户操作失败。

这个场景需要使用分布式事务,因为节点A不能通过调用一个数据库完成该任务,其需要访问网络中两个节点的数据库,而每个结点的数据库执行的事务操作又都是扁平的。

【小结】

对于MySQL的InnoDB存储引擎来说,它支持扁平事务、带有保存点的扁平事务、链事务、分布式事务。对于嵌套事务,MySQL数据库并不是原生的,因此对于有并行事务需求的用户来说MySQL就无能为力了,但是用户可以通过带有保存点的事务来模拟串行的嵌套事务。


二、mysql事务ACID特性的实现原理

1、原子性实现原理

实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句InnoDB实现回滚 靠的是 undo log,当事务对数据库进行修改时,InnoDB会生成对应的undo log。如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

undo log属于逻辑日志,它记录的是sql执行相关的信息当发生回滚时,InnoDB会根据undo log的内容做与之前相反的工作。对于insert,回滚时会执行delete。对于delete,回滚时会执行insert。对于update,回滚时则会执行相反的update,把数据改回去。

2、持久性实现原理 

InnoDB作为MySQL的存储引擎,数据是存放在磁盘中的,但如果每次读写数据都需要磁盘IO,效率会很低。为此,InnoDB提供了缓存(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲。当从数据库读取数据时,会首先从Buffer Pool中读取,如果Buffer Pool中没有,则从磁盘读取后放入Buffer Pool。当向数据库写入数据时,会首先写入Buffer Pool,Buffer Pool中修改的数据会定期刷新到磁盘中(这一过程称为刷脏)。

Buffer Pool的使用大大提高了读写数据的效率,但是也带了新的问题:如果MySQL宕机,而此时Buffer Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证。

于是,redo log被引入来解决这个问题。当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作。当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入redo log日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。

既然redo log也需要在事务提交时将日志写入磁盘,为什么它比直接将Buffer Pool中修改的数据写入磁盘(即刷脏)要快呢?主要有以下两方面的原因:

  • 刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。

  • 刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入。而redo log中只包含真正需要写入的部分,无效IO大大减少。

3、隔离性实现原理

隔离性追求的是并发情形下事务之间互不干扰。简单起见,我们主要考虑最简单的读操作和写操作(加锁读等特殊读操作会特殊说明),那么隔离性的探讨,主要可以分为两个方面。

第一方面,(一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性。

隔离性要求同一时刻只能有一个事务对数据进行写操作,InnoDB通过锁机制来保证这一点。锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁。获得锁之后,事务便可以修改数据。该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

按照粒度,锁可以分为表锁行锁以及其他位于二者之间的锁(间隙锁)。表锁操作数据时会锁定整张表并发性能较差行锁只锁定需要操作的数据并发性能好。但是由于加锁本身需要消耗资源,因此在锁定数据较多情况下使用表锁可以节省大量资源。MySQL中不同的存储引擎支持的锁是不一样的,例如MyIsam只支持表锁,而InnoDB同时支持表锁和行锁,且出于性能考虑,绝大多数情况下使用的都是行锁。

第二方面,(一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性。

InnoDB默认的隔离级别是RR(REPEATABLE READ),RR解决脏读、不可重复读、幻读等问题,使用的是MVCC。MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。它最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要基于以下技术及数据结构:

  1. 隐藏列:InnoDB中每行数据都有隐藏列,隐藏列中包含了本行数据的事务id、指向undo log的指针等。

  2. 基于undo log的版本链:每行数据的隐藏列中包含了指向undo log的指针,而每条undo log也会指向更早版本的undo log,从而形成一条版本链。

  3. ReadView:通过隐藏列和版本链,MySQL可以将数据恢复到指定版本。但是具体要恢复到哪个版本,则需要根据ReadView来确定。所谓ReadView,是指事务(记做事务A)在某一时刻给整个事务系统(trx_sys)打快照,之后再进行读操作时,会将读取到的数据中的事务id与trx_sys快照比较,从而判断数据对该ReadView是否可见,即对事务A是否可见。

4、一致性实现原理

一致性是事务追求的最终目标。前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要应用层面进行保障。实现一致性的措施包括:

  • 保证原子性、持久性和隔离性,如果这些特性无法保证,事务的一致性也无法保证。

  • 数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等。

  • 应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致。


 三、MySQL数据库隔离级别

1、并发事务问题

(1)脏读

一个事务B读取到另一个事务A还没有提交的数据,这种现象是脏读。

(2)不可重复读

事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。

脏读与不可重复读的区别

前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据

 (3)幻读

一个事务按照条件查询数据时,没有对应数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”。

【不可重复读与幻读的区别】

前者是原数据变了,后者是数据行变了(插入了新数据)。

2、事务隔离级别

SQL 标准定义了四种隔离级别,这四种隔离级别分别是

  • 读未提交READ UNCOMMITTED);

  • 读提交 READ COMMITTED);

  • 可重复读 REPEATABLE READ);

  • 串行化 SERIALIZABLE

事务隔离是为了解决脏读、不可重复读、幻读问题,下表展示了 4 种隔离级别对这三个问题的解决程度:

上述4种隔离级别MySQL都支持,并且InnoDB存储引擎默认的支持隔离级别是REPEATABLE READ,但是与标准SQL不同的是,InnoDB存储引擎在REPEATABLE READ事务隔离级别下,使用Next-Key Lock的锁算法,因此避免了幻读的产生。所以,InnoDB存储引擎在默认的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的SERIALIZABLE隔离级别

3、事务隔离级别的实现机制 

(1)READ UNCOMMITTED & READ COMMITTED

通过Record Lock算法实现了行锁,但READ UNCOMMITTED允许读取未提交数据,所以存在脏读问题。而READ COMMITTED允许读取提交数据,所以不存在脏读问题,但存在不可重复读问题。

(2)REPEATABLE READ

使用Next-Key Lock算法实现了行锁,并且不允许读取已提交的数据,所以解决了不可重复读的问题。另外,该算法包含了间隙锁,会锁定一个范围,因此也解决了幻读的问题

(3)SERIALIZABLE

对每个SELECT语句后自动加上LOCK IN SHARE MODE,即为每个读取操作加一个共享锁。因此在这个事务隔离级别下,读占用了锁,对一致性的非锁定读不再予以支持。


 四、事务控制语句

BEGIN 或 START TRANSACTION -- 用于显式开启一个事务:

BEGIN; -- 或者使用 START TRANSACTION;

COMMIT -- 用于提交事务,将所有的修改永久保存到数据库:

COMMIT;

ROLLBACK -- 用于回滚事务,回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;:

ROLLBACK;

SAVEPOINT -- 用于在事务中设置保存点,以便稍后能够回滚到该点:

SAVEPOINT savepoint_name;

ROLLBACK TO SAVEPOINT -- 用于回滚到之前设置的保存点:

ROLLBACK TO SAVEPOINT savepoint_name;

 RELEASE SAVEPOINT --用于删除一个事务的保存点,当没有保存点时,执行该语句会抛异常。

 RELEASE SAVEPOINT savepoint_name

SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

--查看事务隔离级别
select @@TRANSACTION_ISOLATION;

--设置事务隔离级别
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ |SERIALIZABLE]

 

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

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

相关文章

Java项目:112SSM在线电影订票系统

博主主页:Java旅途 简介:分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 在线电影订票系统基于SpringSpringMVCMybatis开发,系统分为前台和后台,前台主要用来用户浏览电影信息,订票&#xff0c…

第7章-第9节-Java中的Stream流(链式调用)

1、什么是Stream流 Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,用于解决集合类库既有的鼻端。 2、案例 假设现在有一个需求, 将list集合中姓张的元素过滤到一个新的集合中;然后将过滤…

Dell 机架式服务器 - 高级定制服务

Dell 机架式服务器 - 高级定制服务 1. Dell Technologies2. 机架式服务器 - 高级定制服务2.1. Servers & Storage (服务器及存储) -> Servers2.2. Rack Servers (机架式服务器)2.3. Shop2.4. PowerEdge Rack Servers (PowerEdge 机架式服务器)2.5. PowerEdge R760 Rack …

个性化Python GUI计算器搭建

大家好,本文将介绍在Python中使用Tkinter几分钟内制作自己的全功能GUI计算器。 要完成所提到的功能,除了通常随Python标准库一起安装的Tkinter之外,不需要任何额外的库。 如果使用的是Linux系统,可能需要安装: $ pi…

519基于单片机的自动切割流程控制系统

基于单片机的自动切割流程控制系统[proteus仿真] 自动切割流程控制系统这个题目算是课程设计和毕业设计中常见的题目了,本期是一个基于单片机的自动切割流程控制系统 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】,赞赏任意文章 2&…

双指针(简化哈希)力扣15.三数之和

题目 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。 …

密码学(二)

文章目录 前言一、Certificate Authorities二、Key Agreement Protocols 前言 本文来自 Intel SGX Explained 请参考:密码学(一) 一、Certificate Authorities 非对称密钥密码学中的公钥和私钥假设每个参与方都拥有其他参与方的正确公钥。…

【上海】买套二手房需要多少钱?

上次我们看了苏州的二手房,这次我们一起来看下上海的二手房价格如何。 数据来源 数据来自贝壳二手房,每个区最多获取了3千条房源信息,数据共计4万条左右 对数据感兴趣的朋友,公众号后台发送上海二手房获取数据文件 各区房源单价…

【VRTK】【VR开发】【Unity】19-VRTK实现旋转运动

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【背景】 在实际开发中,旋转运动也是时常需要模拟的重要运动类型。常见的场景有开关门,方向盘轮胎以及拉动拉杆等等。 旋转运动的实现可以基于物理系…

STM32入门教程-2023版【3-3】gpio输入

关注 星标公众号 不错过精彩内容 大家好,我是硬核王同学,最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 上两小节我们已经把GPIO的结构和8种输入输出模式都讲完了,到这里还不懂的可以回…

JVM主要的几种垃圾回收算法

1、Java 为什么要实现自动内存管理 ? 简化开发过程:通过内存自动管理可以避免手动分配和释放内存的麻烦,减少了内存泄漏和内存错误的风险,让研发能更专注于业务逻辑,不必纠结于内存管理的细节。 提高开发效率&#xff…

vivado 创建编译后工程

创建后期合成项目 合成后项目以合成网表、完全生成的块设计、完全生成的IP以及相应的约束。然后,您可以分析、布局和实施设计 注意:您可以使用XST或第三方合成工具来创建合成网表。 重要!使用EDIF和NGC文件时,顶部单元格名称必…

ChatGPT扩展系列之网易数帆ChatBI

在当今数字化快速发展的时代,数据已经成为业务经营与管理决策的核心驱要素。无论是跨国大企业还是新兴创业公司,正确、迅速地洞察数据已经变得至关重要。然而,传统的BI工具往往对用户有一定的技术门槛,需要熟练的操作技能和复杂的查询语句,这使得大部分的企业员工难以深入…

业界首款PCIe 4.0/5.0多通道融合接口SSD技术解读

之前小编写过一篇文章劝大家不要碰PCIe 5.0 SSD,详细内容,可以再回顾下: 扩展阅读:当下最好不要入坑PCIe 5.0 SSD 如果想要进一步了解PCIe 6.0,欢迎点击阅读: 浅析PCIe 6.0功能更新与实现的挑战 PCIe 6.…

Hyperledger Fabric 消息协议

Fabric 中大量采用了 gRPC 消息在不同组件之间进行通信交互,主要包括如下几种情况:客户端访问 Peer 节点,客户端和 Peer 节点访问排序节点,链码容器与 Peer 节点交互,以及多个 Peer 节点之间的 Gossip 交互。 消息结构…

探索雷盛537威士忌的魅力:从观色、闻香到品鉴

威士忌,这一源于苏格兰的特别烈酒,以其丰富的味蕾和特别的魅力征服了全球的品鉴者。品鉴威士忌不仅仅是一种感官体验,更是一种探索和发现的旅程。在本文中,我们将以雷盛537威士忌为例,与您深入了解品鉴威士忌的全过程&…

【Matplotlib】基础设置之图形组合07

figures, subplots, axes 和 ticks 对象 figures, axes 和 ticks 的关系 这些对象的关系可以用下面的图来表示: 示例图像: 具体结构: figure 对象 figure 对象是最外层的绘图单位,默认是以 1 开始编号(MATLAB 风格…

LeetCode(202)快乐数⭐

编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1&#xff…

软件测试|Python对JSON的解析和创建详解

简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,已经成为当今互联网应用中广泛使用的数据格式之一。Python提供了内置的模块来解析和创建JSON数据,使得在Python中处理JSON变得非常简单。本文将详细介绍Python…

通过Docker搭建4节点的Tendermint集群

Tendermint:0.34.24 Docker:20.10.21 Docker-Compose:2.20.2 OS:Ubuntu 20.04 Go:1.19.2 Linux/amd64 1 修改Tendermint源码 1.1 修改监听IP 为什么要将127.0.1修改成0.0.0.0呢?因为容器内的服务如果是以…