Mysql_数据库事务

文章目录

😊 @ 作者:Lion J
💖 @ 主页: https://blog.csdn.net/weixin_69252724
🎉 @ 主题: MySQL__事务)
⏱️ @ 创作时间:2024年04月26日
————————————————

这里写目录标题

  • 文章目录
    • 什么是事务呢?
    • 那数据库事务有什么作用呢??
    • 并发事务会带来哪些问题呢?
      • ●脏读:
      • ●丢失修改:
      • ●不可重复读:
      • ●幻读:
    • 并发事务的控制有什么?
      • **MVCC
    • 一致性非锁定读 和 锁定读
      • 一致性非锁定读
      • 锁定读
    • MVCC的实现?
      • 隐藏字段
      • undo-log
      • 在 可重复读 与 串行化 的级别下MVCC的差异?

什么是事务呢?

事务就是由单独单元的一个或多个sql语句组成,在这个单元中,每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在,类似于化学当中的原子(一种不可分割的最小单位)。

往通俗的讲就是,事务就是一个整体,里面的内容要么都执行成功,要么都不成功。不可能存在部分执行成功而部分执行不成功的情况。
就是说如果单元中某条sql语句一旦执行失败或者产生错误,那么整个单元将会回滚(返回最初状态)。所有受到影响的数据将返回到事务开始之前的状态,但是如果单元中的所有sql语句都执行成功的话,那么该事务也就被顺利执行。

我们的数据都是通过各种不同技术的存储引擎来引导存储的,不同的存储引擎,都有各自的特点。在mysql中,常见的存储引擎有innodb、myisam等。其中innodb支持事务(transaction),而myisam.等不支持事务。

可以通过show engines;语句来查看mysql支持的存储引擎

   show engines;

比如在生活中举个例子:
事务最经典也经常被拿出来说例子就是转账了。
假如小明要给小红转账 1000 元,这个转账会涉及到两个关键操作,这两个操作必须都成功或者都失败。

  1. 将小明的余额减少 1000 元
  2. 将小红的余额增加 1000 元。
    事务会把这两个操作就可以看成逻辑上的一个整体,这个整体包含的操作要么都成功,要么都要失败。这样就不会出现小明余额减少而小红的余额却并没有增加的情况。

那数据库事务有什么作用呢??

简单来说,数据库事务可以保证多个对数据库的操作(也就是 SQL 语句)构成一个逻辑上的整体。构成这个逻辑上的整体的这些数据库操作遵循:要么全部执行成功,要么全部不执行 。

开启一个事务(对于mysql8来说)

BEGIN 开始一个事务

update... insert... delete ...


ROLLBACK 事务回滚
COMMIT 事务确认

在这里插入图片描述

对于关系型数据库来说(mysql, sql server, oracle)事务来说都有,ACID特性
●原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
●一致性(Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
●隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
●持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

在这里插入图片描述

注意!!:
只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是需要满足的条件,C 是最终的目的!
在这里插入图片描述


并发事务会带来哪些问题呢?

在单体应用程序中(因为我对微服务项目不够深入__🤣),多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题

●脏读:

一个事务读取数据并且对数据进行了修改,这个修改对其他事务来说是可见的,即使当前事务没有提交。这时另外一个事务读取了这个还未提交的数据,但第一个事务突然回滚,导致数据并没有被提交到数据库,那第二个事务读取到的就是脏数据,这也就是脏读的由来。

顾名思义就是读取到了需要丢弃的数据

例如:事务 1 读取某表中的数据 A=20,事务 1 修改 A=A-1,事务 2 读取到 A = 19,事务 1 回滚导致对 A 的修改并未提交到数据库, A 的值还是 20但是此时,事务2读取到的A仍然是A=19

●丢失修改:

在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。

例如:事务 1 读取某表中的数据 A=20,事务 2 也读取 A=20,事务 1 先修改 A=A-1,事务 2 后来也修改 A=A-1,最终结果 A=19,事务 1 的修改被丢失。

●不可重复读:

指在一个事务内多次读同一数据。
在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,**由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。**这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

●幻读:

幻读与不可重复读类似。

不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;
幻读的重点在于记录新增比如多次执行同一条查询语句
时,发现查到的记录增加了。

它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

例如:事务 2 读取某个范围的数据,事务 1 在这个范围插入了新的数据,事务 2 再次读取这个范围的数据发现相比于第一次读取的结果多了新的数据。

并发事务的控制有什么?

MySQL 中并发事务的控制方式无非就两种:
锁 和 MVCC。

  1. 锁可以看作是悲观控制的模式
  2. 多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式。

锁控制方式下会通过锁来显示控制共享资源而不是通过调度手段,MySQL 中主要是通过 读写锁 来实现并发控制。

●共享锁:又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
●排他锁:又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条记录加任何类型的锁(锁不兼容)

读写锁可以做到读读并行,但是无法做到写读、写写并行。另外,根据根据锁粒度的不同,又被分为 表级锁和 行级锁 。

InnoDB引擎 不光支持表级锁,还支持行级锁,默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。
不论是表级锁还是行级锁,都存在共享锁(Share Lock)和排他锁(Exclusive Lock)这两类。

**MVCC

MVCC 是一种多版本并发控制机制,用于在多个并发事务同时读写数据库时保持数据的一致性和隔离性。它是通过在每个数据行上维护多个版本的数据来实现的。当一个事务要对数据库中的数据进行修改时,MVCC 会为该事务创建一个数据快照,而不是直接修改实际的数据行

MVCC 在 MySQL 中实现所依赖的手段主要是: 隐藏字段、read view、undo log。

  1. undo log : undo log 用于记录某行数据的多个版本的数据。
  2. read view 和 隐藏字段 : 用来判断当前版本数据的可见性。

1、读操作(SELECT):
当一个事务执行读操作时,它会使用快照读取。快照读取是基于事务开始时数据库中的状态创建的,因此事务不会读取其他事务尚未提交的修改
具体工作情况如下:
●对于读取操作,事务会查找符合条件的数据行,并选择符合其事务开始时间的数据版本进行读取
●如果某个数据行有多个版本,事务会选择不晚于其开始时间的最新版本,确保事务只读取在它开始之前已经存在的数据。
●事务读取的是快照数据,因此其他并发事务对数据行的修改不会影响当前事务的读取操作。

2、写操作(INSERT、UPDATE、DELETE):
当一个事务执行写操作时,它会生成一个新的数据版本,并将修改后的数据写入数据库。
具体工作情况如下:
●对于写操作,事务会为要修改的数据行创建一个新的版本,并将修改后的数据写入新版本。
●新版本的数据会带有当前事务的版本号,以便其他事务能够正确读取相应版本的数据。
●原始版本的数据仍然存在,供其他事务使用快照读取,这保证了其他事务不受当前事务的写操作影响。

3、事务提交和回滚:
●当一个事务提交时,它所做的修改将成为数据库的最新版本,并且对其他事务可见。
●当一个事务回滚时,它所做的修改将被撤销,对其他事务不可见。

4、版本的回收:
**为了防止数据库中的版本无限增长,MVCC 会定期进行版本的回收。**回收机制会删除已经不再需要的旧版本数据,从而释放空间。

MVCC 通过创建数据的多个版本和使用快照读取来实现并发控制。读操作使用旧版本数据的快照,写操作创建新版本,并确保原始版本仍然可用。这样,不同的事务可以在一定程度上并发执行,而不会相互干扰,从而提高了数据库的并发性能和数据一致性。一致性非锁定读和锁定读

一致性非锁定读 和 锁定读

一致性非锁定读与锁定读的区别主要针对的是读操作在加锁方式上的差别。这里先看下锁的分类吧。

一致性非锁定读

一致性非锁定读是InnoDB存储引擎通过多版本控制(multi versioning)的方式来读取当前执行时间数据库中的数据。如果被读的数据行被加了排他锁,在读取这行数据的时候并不会等待锁释放,而是读取该行的一个快照数据。 之所以称为非锁定读,因为不需要等待被访问行的X锁的释放。快照数据是指修改行之前的数据版本,该实现通过undo段来完成。

●非锁定读的方式极大提高了数据库的并发性。在InnoDB存储引擎中,这是默认的读取方式。

快照数据其实就是当前行数据的一个历史版本,每行记录可能有多个版本。这种技术成为多行版本技术。由此带来的并发控制,成为多版本并发控制(Multi Version Concurrency Control,MVCC)。

●在事务的隔离级别,READ COMMITED和REPEATABLE READ(InnoDB存储引擎默认的事物隔离级别)下,对快照数据的定义不同。
注意:

  1. 在READ COMMITTED事务隔离级别下,对于快照数据,非锁定读总是读取被锁定行的最新一份快照数据。而在
  2. REPEATABLE READ事务隔离级别下,对于快照数据,非锁定读总是读取事务开始时的数据版本。

也就是说在READ COMMITTED事务隔离级别下,非锁定读读取到的数据是最新的快照版本数据,也就是可以读到另一个事务已经提交了的快照数据。而在REPEATABLE READ下,只会读到事务开始前的数据。
这也就是为什么在read commited 级别下面, 会出现不可重复读的问题

锁定读

 在默认情况下,InnoDB存储引擎对数据采用的是一致性非锁定读。但是有些情况下为了保证数据逻辑的一致性,需要对SELECT的操作加锁。InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作。
在锁定读下,读取的是数据的最新版本,这种读也被称为 当前读(current read)。

  1. SELECT …… for update (同时会造成幻读问题)

  2. SELECT …… lock in share mode

 其中,SELECT …… for update对读取的记录加一个X锁(排它锁),其他事务不能对已锁定的行加任何锁。
而SELECT …… lock in share mode 是对读取的记录加一个S锁(共享锁),其他事物可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。

此外,SELECT …… FOR UPDATE, SELECT …… LOCK IN SHARE MODE必须在一个事物中,当事物提交了,锁也就释放了。因此在使用上诉两句SELECT锁定语句时,务必加上BEGIN,START TRANSACTION 或者SET AUTOCOMMIT=0
   在一致性非锁定读下,即使读取的记录已被其它事务加上 X 锁,这时记录也是可以被读取的,即读取的快照数据。

   上面说了,在 Repeatable Read 下 MVCC 防止了部分幻读,这边的 “部分” 是指在 一致性非锁定读 情况下,只能读取到第一次查询之前所插入的数据(根据 Read View 判断数据可见性,Read View 在第一次查询时生成)。但是!如果是 锁定读,每次读取的都是最新数据,这时如果两次查询中间有其它事务插入数据,就会产生幻读。
InnoDB 在实现Repeatable Read 时,如果执行的是当前读,则会对读取的记录使用 Next-key Lock ,来防止其它事务在间隙间插入数据

MVCC的实现?

   MVCC 的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB 通过数据行的 DB_TRX_ID 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改

隐藏字段

在内部,InnoDB 存储引擎为每行数据添加了三个 隐藏字段:
●DB_TRX_ID(6字节):表示最后一次插入或更新该行的事务 id此外,delete 操作在内部被视为更新,只不过会在记录头Record header 中的 deleted_flag 字段将其标记为已删除
●DB_ROLL_PTR(7字节) 回滚指针,指向该行的 undo log 。如果该行未被更新,则为空
●DB_ROW_ID(6字节):如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引ReadView

undo-log

undo-log日志中,主要有两个作用
●当事务回滚时用于将数据恢复到修改前的样子
●另一个作用是 MVCC ,当读取记录时,若该记录被其他事务占用或当前版本对该事务不可见,则可以通过 undo log 读取之前的版本数据,以此实现非锁定读

在 InnoDB 存储引擎中 undo log 分为两种:insert undo log 和 update undo log:

  1. insert undo log:
    指在 insert 操作中产生的 undo log。因为 insert 操作的记录只对事务本身可见,对其他事务不可见,故该 undo log 可以在事务提交后直接删除。不需要进行 purge 操作insert 时的数据初始状态:

  2. update undo log:update 或 delete 操作中产生的 undo log。该 undo log可能需要提供 MVCC 机制,因此不能在事务提交时就进行删除。提交时放入 undo log 链表,等待 purge线程 进行最后的删除
    如图
    在这里插入图片描述

在 可重复读 与 串行化 的级别下MVCC的差异?

在事务隔离级别 读已提交 和 可重复读(InnoDB 存储引擎的默认事务隔离级别)下,InnoDB 存储引擎使用 MVCC(非锁定一致性读),但它们生成 Read View 的时机却不同在 读已提交 隔离级别下的 每次select 查询前都生成一个Read View (m_ids 列表)在 RR 隔离级别下只在事务开始后 第一次select 数据前生成一个Read View(m_ids 列表)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32、GD32驱动SHT30温湿度传感器源码分享

一、SHT30介绍 1、简介 SHT30是一种数字湿度和温度传感器,由Sensirion公司生产。它是基于物理蒸发原理的湿度传感器,具有高精度和长期稳定性。SHT30采用I2C数字接口,可以直接与微控制器或其他设备连接。该传感器具有低功耗和快速响应的特点…

Pytorch 的神经网络 学习笔记

参照官方网址 Module — PyTorch 2.2 documentation 一. 介绍 1. torch.nn模块: torch.nn是PyTorch中专门用于构建神经网络的模块。它提供了构建深度学习模型所需的所有构建块,包括各种层类型(如全连接层、卷积层、循环层等)、…

笔记本硬盘坏了怎么把数据弄出来 笔记本硬盘数据恢复一般需要多少钱

现在办公基本都离不开笔记本电脑,就连学生写作业也大多是都在电脑上完成。硬盘作为电脑存储的重要组成部分,承载着存储文件和各类软件的重任。如果硬盘出现故障,基本上这台电脑就无法正常工作,同时我们可能面临丢失很多重要的数据…

js字符串方法总结_js 字符串方法(1)

var count0 var prosstr.indexOf(a) while(pros!-1) {countprosstr.indexOf(a,pros1) } console.log(count);3. chartAt() 返回指定位置的字符 根据下标获取字符var strabcdef console.log(str.charAt(2));4. lastIndexOf() 返回字符串字串出现的最后一处出现的位置索引 没有匹…

Hadoop之路

hadoop更适合在liunx环境下运行,会节省后期很多麻烦,而用虚拟器就太占主机内存了,因此后面我们将把hadoop安装到wsl后进行学习,后续学习的环境是Ubuntu-16.04 (windows上如何安装wsl) 千万强调,有的命令一…

架构师系列-Docker(一)-基础及MYSQL安装

轻量容器引擎Docker Docker是什么 Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。 它基于 Google 公司推出的 Go 语言实现,项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,…

高级控件5-RecyclerView

与ViewPager类似的一个滑动的高级控件是RecyclerView,使用更加灵活。 第1步:添加依赖 打开mvn官网,检索recyclerview,选择使用人数较多的版本,复制依赖,放入项目中即可 快捷方法(复制下面的代…

【Qt】信号与槽

1 🍑信号和槽概述🍑 在 Qt 中,用户和控件的每次交互过程称为⼀个事件。⽐如 “⽤⼾点击按钮” 是⼀个事件,“⽤⼾关闭窗⼝” 也是⼀个事件。每个事件都会发出⼀个信号,例如⽤⼾点击按钮会发出 “按钮被点击” 的信号&…

LabVIEW 2024安装教程(附免费安装包资源)

鼠标右击软件压缩包,选择“解压到LabVIEW.2024”。 返回解压后的文件夹,鼠标右击“ni_labview-2024”选择“装载”。 鼠标右击“Install”选择“以管理员身份运行”。 点击“我接受上述2条许可协议”,然后点击“下一步”。 点击“下一步”。 …

用例整体执行及pytest.ini文件

在我们写代码的过程中,一般都是右键或者命令行去执行一个用例 但是当我们写完后,需要整体执行一遍。那应该怎么搞呢? 我们可以在根目录下新建一个main.py或者run.py之类的文件,文件内容如下: if __name__ "__ma…

Stable Diffusion 常用放大算法详解

常用放大算法 图像放大算法大致有两种: 传统图像放大算法(Lantent、Lanczos、Nearest)AI图像放大算法(4x-UltraSharp、BSRGAN、ESRGAN等) 传统图像放大算法是基于插值算法,计算出图像放大后新位置的像素…

Redis 源码学习记录:字符串

redisObject Redis 中的数据对象 server/redisObject.h 是 Redis 对内部存储的数据定义的抽象类型其定义如下: typedef struct redisObject {unsigned type:4; // 数据类型,字符串,哈希表,列表等等unsigned encoding:4; …

微信小程序:9.小程序配置

全局配置文件 小程序根目录下的app.json文件是小程序的全局配置文件。 常用的配置文件如下: pages 记录当前小程序所有的页面存放路径信息 window 全局设置小程序窗口外观 tabBar 设置小程序底部的tabBar效果 style 是否启用新版style 小程序窗口的组成部分 了解windo节点常…

keytool,openssl的使用

写在前面 在生成公钥私钥,配置https时经常需要用到keytool,openssl工具,本文就一起看下其是如何使用的。 keytool是jdk自带的工具,不需要额外下载,但openssl需要额外下载 。 1:使用keytool生成jks私钥文件…

ArcGIS专题图制作—3D峡谷地形

6分钟教你在ArcGIS Pro中优雅完成炫酷的美国大峡谷3D地图 6分钟教你在ArcGIS Pro中优雅完成炫酷的美国大峡谷3D地图。 这一期的制图教程将带我们走入美国大峡谷,让我们一起绘制这张美妙的地图吧!视频也上传到了B站,小伙伴可以去! …

每日一题(力扣45):跳跃游戏2--贪心

由于题目已经告诉了我们一定可以跳到,所以我们只需去考虑前进最快的方法。即 判断当前下一步能跳的各个位置中,哪个能带你去去向最远的地方(why? 因为其他位置所能提供的最大范围都没最远那个大,所以最远的那个已经可以…

IBM SPSS Statistics for Mac v27.0.1中文激活版:强大的数据分析工具

IBM SPSS Statistics for Mac是一款功能强大的数据分析工具,为Mac用户提供了高效、精准的数据分析体验。 IBM SPSS Statistics for Mac v27.0.1中文激活版下载 该软件拥有丰富的统计分析功能,无论是描述性统计、推论性统计,还是高级的多元统计…

上门服务系统|上门服务小程序搭建流程

随着科技的不断进步和人们生活水平的提高,越来越多的服务开始向线上转型。传统的上门服务业也不例外,随着上门服务小程序的兴起,人们的生活变得更加便捷和高效。本文将为大家介绍上门服务小程序的搭建流程以及应用范围。 一、上门服务小程序搭…

ZYNQ之嵌入式开发04——自定义IP核实现呼吸灯、固化程序

文章目录 自定义IP核——呼吸灯实验固化程序 自定义IP核——呼吸灯实验 Xilinx官方提供了很多IP核,在Vivado的IP Catalog中可以查看这些IP核,在构建自己复杂的系统时,只使用Xilinx官方的免费IP核一般满足不了设计的要求,因此很多…

浅谈游戏机制

浅谈游戏机制 前言什么是游戏机制?机制组成机制类别结语 前言 最近在编写游戏开发文档的时候了解到游戏机制,第一次接触游戏机制的概念难免有些陌生,但感觉又跟常见,在网上查阅浏览了一些资料后了解到游戏机制还不止一个。 现在将…
最新文章