【MySQL】 -- 事务

news2025/1/19 14:20:13

如果对表中的数据进行CRUD操作时,不加控制,会带来一些问题。
比如下面这种场景:

image.png
有一个tickets表,这个数据库被两个客户端机器A和B用时连接对此表进行操作。客户端A检查tickets表中还有一张票的时候,将票出售了,而火车票的总数是一个固定值,客户端A此时还没有来得及更新数据库
这时客户端B检查了票数,发现还有一张,又卖了一次票。这种情况,就出现了同一张票被卖了两次的场景。

这就是在进行CRUD时,不加控制带来的问题。
只要当进进行CRUD时满足以下属性,才能解决上面的问题:

  1. 买票的过程得是原子的
  2. 买票互相应该不能影响
  3. 买完票应该要永久有效
  4. 买前,和买后都要是确定的状态

而MySQL的事务机制,就能够有效的解决此问题。

1. MySQL事务

事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。

MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。

事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假设一种场景:你毕业了,学校的教务系统后台MySQL中,不再需要你的数据,要删除你的所有信息, 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条 MySQL 语句构成,那么所有这些操作合起来,就构成了一个事务。

一个 MySQL数据库,可不止一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向MySQL服务器发起事务处理请求。而每条事务至少一条 SQL ,最多很多SQL ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。甚至,因为事务由多条SQL构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?

所以一个完整的事务,不仅仅是简单的DML组合而成,还要满足以下4个特点:

  • 原子性(Atomicity) :事务中的所有操作要么全部完成,要么全部不完成。
  • 一致性(Consistency) :事务执行前后,数据库的状态必须保持一致。
  • 隔离性(Isolation) :一个事务的执行不能被其他事务干扰。
  • 持久性(Durability) :一旦事务提交,其对数据库的修改应该永久保存。

以上 四个属性可以简称为ACID

所以事务就是一条或者多条SQL语句组成并包含ACID

有了事务这种机制后,能够简化我们的编程模型, 不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我 们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服 务的.而不是伴随着数据库系统天生就有的。

1.1 MySQL事务支持的版本

MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM不支持。
使用show engines可以查看。

image.png

1.2 事务的提交方式

事务的提交方式常见的有两种

  • 自动提交
  • 手动提交

使用show variables like 'autocommit';可以查看事务提交的方式。

image.png
ON表示为自动提交。

可以通过set autocommit来更改自动提交模式。值为0,表示禁止自动提交。

image.png
值为1,表示开启自动提交。

image.png

1.3 事务常见的操作方式

为了方便演示,这里创建一张测试表account。

create table if not exists account( 
id int primary key, 
name varchar(50) not null default '', 
blance decimal(10,2) not null default 0.0 
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

这里还需要不同的主机连接到同一个数据库中,我使用本地和服务器的mysql客户端进行连接。
使用SHOW PROCESSLIST;可以查看数据库的连接情况。

image.png
除此之外还需要将mysql的默认隔离级别设置成读未提交。
set global transaction isolation level READ UNCOMMITTED;
使用此命令设置完成后,重启客户端进行连接隔离级别才会生效。

image.png

先查看事务是否是自动提交,使用show variables like 'autocommit';命令进行查看。

image.png
ON表示开启自动提交。以下提交的方式都是自动提交的。

1.3.1 开始一个事务

开始一个事务,可以使用being或者start transaction

image.png

1.3.2 创建一个保存点

使用savepoint 保存点名进行设置一个保存点

image.png

1.3.3 回滚到保存点

使用rollback to 保存点名即可回滚到指定的保存点中。
使用rollback可以直接回滚到最开始。

image.png

使用示例-事务的开始和回滚

image.png
此时另一个客户端在查询时,也可以查询到。做到了一致性。

image.png
这样两个客户端同时操作一个表的时候,就可以有效的解决冲突了。

事务使用示例-自动回滚

当提交方式为自动提交的时候,客户端崩溃的后,MySQL会自动回滚。(隔离级别设置为提交未读)

在客户端A中使用事务进行插入。如下。

image.png
插入一条记录后,从另一个客户端B中就可以查询到,如下:
image.png

此时,客户端A崩溃了,那么MySQL就会自动回滚。

image.png
自动回滚后,在客户端B中就无法查询到插入的这条记录了。

image.png

事务使用示例-提交后,客户端崩溃后,MySQL的数据不会在受到影响。(持久化特性)

在客户端A事务中插入一条记录,然后手动提交,客户端A崩溃。
image.png
此时在另一个客户端B中进行查询,依然可以查询到。

image.png
事务做到了数据持久化,不会被影响。

事务使用示例-begin操作会自动更改提交方式,不会受MySQL是否自动提交影响

image.png

image.png

事务使用示例-单条 SQL 与事务的关系

单条SQL:

image.png
此时客户端B在进行查询的时候就无法查询到此记录。

image.png

事务:

image.png
此时客户端B在进行查询的时候依然可以查询到此记录。数据已经被持久化了。

image.png

1.4 总结

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是 否设置set autocommit无关。
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为 MySQL 有 MVCC )

事务操作注意事项:

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务 还没有提交)。
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB 支持事务, MyISAM 不支持事务
  • 开始事务可以使 start transaction 或者 beginbegin更简洁 推荐使用。

2. 事务隔离级别

  • MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务的方式进行。
  • 一个事务可能由多条SQL语句构成,也就意味着任何一个事务,都有执行前、执行中和执行后三个阶段,而所谓的原子性就是让用户层要么看到执行前,要么看到执行后,执行中如果出现问题,可以随时进行回滚,所以单个事务对用户表现出来的特性就是原子性。
  • 但毕竟每个事务都有一个执行的过程,在多个事务各自执行自己的多条SQL时,仍然可能会出现互相影响的情况,比如多个事务同时访问同一张表,甚至是表中的同一条记录。
  • 数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性
  • 数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

数据库的隔离级别一共有以下四种。

  • 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的 执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多 并发问题,如脏读,幻读,不可重复读等,上面为了做实验方便,用的就是这个隔离性。
  • 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默 认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
  • 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
  • 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突, 从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争 (这种隔离级别太极端,实际生产基本不使用)

2.1 查看隔离性

  • SELECT @@global.tx_isolation;:查看全局的隔离级别
    image.png
  • SELECT @@session.tx_isolation; 或者 SELECT @@tx_isolation;:查看当前会话的隔离级别
  • image.png

2.2 设置隔离级别

  • 设置当前会话 or 全局隔离级别语法:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | Serializable}

比如设置当前会话隔离级别为Serializable。

image.png

设置全局隔离性的话,另起一个会话就会被影响。重启MySQL客户端生效

image.png

2.2.1 读未提交【Read Uncommitted】

该隔离级别,效率虽然很高,但是问题太多,严重不建议使用。
问题如下:
1、将事务的隔离级别设置为Read Uncommitted

image.png

2、在一个终端A中开启事务,然后插入一条记录。不进行提交。

image.png
3、在另一个终端中进行查询

image.png

这就是Read Uncommitted隔离级别做严重的问题,读到了未提交的数据。这种现象称之为脏读~

2.2.2 读提交【Read Committed】

按照命名来看,对比读未提交,读提交只读已提交的数据。但是这种隔离级别有新的问题。读到的值不同。问题如下:
1、将隔离级别设置为Read Committed

image.png

2、开启事务,不提交在另一个客户端进行查询

image.png
在另一个终端中读不到。

image.png

3、进行提交,在另一个终端再次读取。
终端A使用commit提交后,在终端B中就可以查到了。

image.png

到此,读提交解决了读未提交的问题。
但是,如果在终端A更新插入一条记录,不提交,终端B就能读到了。回到了读未提交的现象。

image.png

终端B还是读到了

image.png
这种现象叫做不可重复读,解决这个问题,又有了新的隔离级别。 可重复读【Repeatable Read】

2.2.3 可重复读【Repeatable Read】

这种隔离级别解决了读未提交和读提交的问题,但是又带来了幻读的问题。如下:
1、设置隔离级别为Repeatable Read

image.png

2、开启事务,插入记录

image.png

不提交,此时在另一个终端就无法进行查询到。解决读未提交的问题。

image.png
继续在终端A中插入一条记录

image.png

此时在终端中就能查询到了。

image.png
继续插入,不提交,另一个终端也无法查到。

同样的,在终端A中插入一条记录,并提交结束事务。

image.png
然后再终端B查询终端Acommit后的纪律。

image.png
但是,多次查询后,在终端B中无法查询到A commit到的记录。

这倒也没有什么影响,也符合可重复的特点。
但是,一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读 (phantom read)。

2.2.4 串行化【Serializable】

对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用。

两个终端都使用事务,当A进行更新的时候,会一直阻塞,直到终端B提交后才可以。
recording.gif
实际这种完全不会被采用。

2.2.5 总结

  • 事务隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平衡点。
  • 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了
  • 幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样
  • 说明: mysql 默认的隔离级别是可重复读,一般情况下不要修改
  • 上面的例子可以看出,事务也有长短事务这样的概念。事务间互相影响,指的是事务在并行执行的 时候,即都没有commit的时候,影响会比较大。

image.png

3. 事务的一致性

  • 事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务 成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中 断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一 致)的状态。因此一致性是通过原子性来保证的。
  • 其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑 做支撑,也就是说,一致性,是由用户决定的。
  • 而技术上,通过AID保证C

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

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

相关文章

Aidlux 1.4 部署Nextcloud 2024.6实录 没成功

Aidux阉割版Debain10,坑很多,比如找不到实际的系统日志,有知道的大神吗? 1 Apache2安装 # 测试Apache2 sudo apt update && sudo apt upgrade sudo apt install apache2 -y80端口疑似被禁止只能换端口 rootlocalhost:/…

云计算技术高速发展,优势凸显

云计算是一种分布式计算技术,其特点是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,并通过多部服务器组成的系统进行处理和分析这些小程序,最后将结果返回给用户。它融合了分布式计算、效用计算、负载均衡、并行计算、网络存储…

ctr/cvr预估之NFM模型

ctr/cvr预估之NFM模型 在数据驱动的广告和推荐系统中,准确预测用户的点击行为(Click-Through Rate, CTR)和转化行为(Conversion Rate, CVR)是提升营销效率和用户体验的关键。因子分解机(Factorization Mac…

RK3568技术笔记七 安装Ubuntu Linux

在新弹出的窗口中,单击“CD/DVD (SATA)”。如下图所示: 在右侧选择“使用ISO映像文件”。然后单击“浏览”,找到SAIL-RK3568开发板光盘->通用工具->虚拟机Ubuntu->ubuntu-18.04.4-desktop-amd64.iso。最后点击…

韩顺平0基础学java——第28天

p569-591 坦克大战!(绘图监听事件线程文件处理) 绘图 绘图原理 Component类提供了两个和绘图相关最重要的方法: 1. paint(Graphics g)绘制组件的外观 2. repaint()刷新组件的外观。 当组件第一次在屏幕显示的时候,程序会自动的调用paint()…

Dify知识库接入微信

Dify知识库接入微信 看到此文章,相信您已经搭建好了Dify知识库,还没有Dify知识库请先部署好后再来尝试将Dify接入微信 准备材料如下 搭建好的Dify知识库里的api接口和key24小时不关机的服务器一个 (推荐浪浪云的服务器简单方便)需要一个微信…

数学建模整数规划学习笔记

与线性规划的本质区别在于决策变量是否取整。 (1)分支定界法 若不考虑整数限制先求出相应松弛问题的最优解: 若松弛问题(线性规划)无解,则ILP(整数规划)无解。 若求得的松弛问题最…

校园任务平台系统的设计

管理员账户功能包括:系统首页,个人中心,管理员管理,论坛管理,任务咨询管理,用户管理,基础数据管理 前台账户功能包括:系统首页,个人中心,任务资讯公告&#…

代码随想录第29天|贪心算法

基础知识 原理: 选择每一阶段的最优解, 从而达到全局最优解套路: 无, 只能举反例, 想不出反例则可以尝试用贪心算法 455. 分发饼干 思路: 使用贪心策略 每次用大饼干满足大胃口的孩子(用小饼干则会浪费)或用小饼干满足小胃口的孩子 一定是遍历孩子, 不能遍历饼干, 否则结果不…

大模型时代,新手和程序员如何转型入局AI行业?

在近期的全国两会上,“人工智能”再次被提及,并成为国家战略的焦点。这一举措预示着在接下来的十年到十五年里,人工智能将获得巨大的发展红利。技术革命正在从“互联网”向“人工智能”逐步迈进,我将迎来新一轮技术革新和人才需求…

鸿蒙开发:【组件启动规则(FA模型)】

组件启动规则(FA模型) 启动组件是指一切启动或连接应用组件的行为: 启动PageAbility、ServiceAbility,如使用startAbility()等相关接口。连接ServiceAbility、DataAbility,如使用connectAbility()、acquireDataAbili…

MySQL之复制(八)

复制 复制和容量规划 备库什么时候开始延迟 一个关于备库比较普遍的问题是如何预测备库会在何时跟不上主库。很难去描述备库使用的复制容量为5%与95%的区别,但是至少能够在接近饱和前预警并估计复制容量。首先应该古纳差复制延迟的尖刺。如果有复制延迟的曲线图&…

如何将现有系统逐步优化成微服务设计

目录 基础服务改造核心步骤准备阶段实施阶段 基础服务设计 本文诞生于学习架构实践专栏后的深思以及总结,结合公司之前“大泥球”的架构风格,改造服务设计的思维。 改造公司系统服务主要原因:1、代码类似“屎山”,牵一发而动全身&…

Freertos-----任务之间的消息传递(使用消息队列信号量方法)

这次来分享任务之间的数据传递的方法,方法有很多种,我展示2种,让大家对freertos有更深刻的印象 目录 消息队列 信号量 消息队列 首先直接打开普中的例程,然后在里面加上ADC的驱动代码,先初始化外设先,我…

亚足联官方公布18强赛抽签时间及规则,国足确认位列第五档,你们觉得国足能进世界杯吗?

亚足联官方公布18强赛抽签时间及规则,国足确认位列第五档,你们觉得国足能进世界杯吗? 今天亚足联官方宣布了世预赛18强赛分组抽签仪式时间,本次抽签仪式将于6月27日15点在马来西亚吉隆坡举行。除了抽签时间之外,足联还…

L55--- 257.二叉树的所有路径(深搜)---Java版

1.题目描述 2.思路 (1)因为是求二叉树的所有路径 (2)然后是带固定格式的 所以我们要把每个节点的整数数值换成字符串数值 (3)首先先考虑根节点,也就是要满足节点不为空 返回递归的形式dfs(根节…

Service方法增加@Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException

Service方法增加Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException 场景处理方法原因 场景 首先确认的是Service添加了Service或Component等注解,另外也增加了ComponentScan确定扫描的包路径是包含对应Service的,但就是无法找到这个bean。 通…

C51与MDK共存版本安装教程

目录 一、安装准备 1.1 新建文件夹 1.2 网盘链接-加Q 667198390 二、 双版本共存安装教程 2.1 安装Keil5 C51 2.2 安装Keil5 MDK 2.3 C51和MDK的共存 2.4 生成许可证 2.5 安装STM32Pack包 一、安装准备 1.1 新建文件夹 如下图: 在合适的网盘里&#xff08…

阿里云如何实现express的自动化部署(保姆级教程)

本篇文章将详细介绍一下阿里云如何实现express的自动化部署,作者本人总结的保姆级教程!!! 首先去阿里云官网 (阿里云-计算,为了无法计算的价值) 搜索函数计算fc 如果没有开通过选择免费开通,…

计算机组成原理 | 计算机系统概述

CPI:(Clockcycle Per Instruction),指每条指令的时钟周期数。 时钟周期:对CPU来说,在一个时钟周期内,CPU仅完成一个最基本的动作。时钟脉冲是计算机的基本工作脉冲,控制着计算机的工作节奏。时钟周期 是一个时钟脉冲所…