当前位置: 首页 > news >正文

MySQL之事务

我们学习了数据库之后,就是为了解决生活中的问题,对应MySQL中就是事务,此文一探究竟——《事务》

1. 什么是事务?

事务把⼀组SQL语句打包成为⼀个整体,在这组SQL的执⾏过程中,要么全部成功,要么全部失败。这组SQL语句可以是⼀条也可以是多条。来看⼀个转账的例⼦,如图:
在这里插入图片描述
在这个例⼦中,涉及了两条更新语句:

我们先创建一个表,来帮助我们探讨事务的奥秘。

CREATE TABLE `bank_account` (`id` bigint PRIMARY KEY AUTO_INCREMENT, `name` varchar(255) NOT NULL, # 姓名`balance` decimal(10, 2) NOT NULL # 余额
);
INSERT INTO bank_account(`name`, balance) VALUES('张三', 1000);
INSERT INTO bank_account(`name`, balance) VALUES('李四', 1000);

此时,我们将转账过程就可以看成是表的更新操作

# ================更新操作===================
# 张三余额减少100
UPDATE bank_account set balance = balance - 100 where name = '张三';
# 李四余额增加100
UPDATE bank_account set balance = balance + 100 where name = '李四';

如果转账成功,应该有以下结果:

  1. 张三的账⼾余额减少 100 ,变成 900 ,李四的账⼾余额增加了 100 ,变成 1100 ,不能出现张
    三的余额减少⽽李四的余额没有增加的情况;
  2. 张三和李四在发⽣转账前后的总额不变,也就是说转账前张三和李四的余额总数为
    1000+1000=2000 ,转账后他们的余额总数为 900+1100=2000 ;
  3. 转账后的余额结果应当保存到存储介质中,以便以后读取;
  4. 还有⼀点需要要注意,在转账的处理过程中张三和李四的余额不能因其他的转账事件⽽受到⼲扰;

以上这四点在事务的整个执⾏过程中必须要得到保证,这也就是事务的 ACID 特性

2. 事务的ACID特性

事务的ACID特性指的是 Atomicity (原⼦性), Consistency (⼀致性), Isolation (隔离性)和 Durability (持久性)。

  • Atomicity (原⼦性) : ⼀个事务中的所有操作,要么全部成功,要么全部失败,不会出现只执⾏了⼀半的情况,如果事务在执⾏过程中发⽣错误,会回滚( Rollback )到事务开始前的状态,就像这个事务从来没有执⾏过⼀样
  • Consistency (⼀致性): 在事务开始之前和事务结束以后,数据库的完整性不会被破坏。这表⽰写⼊的数据必须完全符合所有的预设规则,包括数据的精度、关联性以及关于事务执⾏过程中服 务器崩溃后如何恢复;
  • Isolation (隔离性): 数据库允许多个并发事务同时对数据进⾏读写和修改,隔离性可以防⽌多个事务并发执⾏时由于交叉执⾏⽽导致数据的不⼀致。事务可以指定不同的隔离级别,以权衡在不 同的应⽤场景下数据库性能和安全;
  • Durability (持久性): 事务处理结束后,对数据的修改将永久的写⼊存储介质,即便系统故障也不会丢失

3. 为什么要使用事务?

事务具备的ACID特性,是我们使⽤事务的原因,在我们⽇常的业务场景中有⼤量的需求要⽤事务来保证。⽀持事务的数据库能够简化我们的编程模型, 不需要我们去考虑各种各样的潜在错误和并发问题,在使⽤事务过程中,要么提交,要么回滚,不⽤去考虑⽹络异常,服务器宕机等其他因素,因此我们经常接触的事务本质上是数据库对 ACID 模型的⼀个实现,是为应⽤层服务的。

4. 如何使用事务

4.1 查看支持事务的存储引擎

要使⽤事务那么数据库就要⽀持事务,在MySQL中⽀持事务的存储引擎是InnoDB,可以通过show engines; 语句查看:

在这里插入图片描述

4.2 语法

  • 通过以下语句可以完成对事务的控制:
# 开始⼀个新的事务
START TRANSACTION;
# 或
BEGIN;
# 提交当前事务,并对更改持久化保存
COMMIT;
# 回滚当前事务,取消其更改
ROLLBACK;
  • START TRANSACTIONBEGIN 开始⼀个新的事务
  • COMMIT 提交当前事务,并对更改持久化保存
  • ROLLBACK 回滚当前事务,取消其更改
  • ⽆论提交还是回滚,事务都会关闭

4.3 开启⼀个事务,执行修改后回滚

在这里插入图片描述

4.4 开启⼀个事务,执行修改后提交

在这里插入图片描述

4.5 保存点

在事务执⾏的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态,
回滚时不指定保存点,直接回滚到事务开始时的原始状态,事务关闭

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.6 ⾃动/⼿动提交事务

  • 默认情况下,MySQL是⾃动提交事务的,也就是说我们执⾏的每个修改操作,⽐如插⼊、更新和删
    除,都会⾃动开启⼀个事务并在语句执⾏完成之后⾃动提交,发⽣异常时⾃动回滚。
  • 查看当前事务是否⾃动提交可以使⽤以下语句
 show variables like 'autocommit';

在这里插入图片描述

  • 可以通过以下语句设置事务为⾃动或⼿动提交
# 打开自动提交事务
set autocommit =1;  //方法1
set autocommit =on; //方法2
# 关闭自动提交事务
set autocommit =0;  //方法1
set autocommit =off;//方法2

在这里插入图片描述

  • 只要使⽤ START TRANSACTIONBEGIN 开启事务,必须要通过 COMMIT 提交才会持久化,与是否设置 SET autocommit ⽆关
  • ⼿动提交模式下,不⽤显⽰开启事务,执⾏修改操作后,提交或回滚事务时直接使⽤ commit 或 rollback
  • 已提交的事务不能回滚

5. 事务的隔离性和隔离级别

5.1 什么是隔离性

MySQL服务可以同时被多个客户端访问,每个客户端执⾏的DML语句以事务为基本单位,那么不同的客⼾端在对同⼀张表中的同⼀条数据进⾏修改的时候就可能出现相互影响的情况,为了保证不同的事务之间在执⾏的过程中不受影响,那么事务之间就需要要相互隔离,这种特性就是隔离性。

5.2 隔离级别

事务具有隔离性,那么如何实现事务之间的隔离?隔离到什么程度?如何保证数据安全的同时也要兼顾性能?这都是要思考的问题。
事务间不同程度的隔离,称为事务的隔离级别,不同的隔离级别在性能和安全⽅⾯做了取舍,有的隔离级别注重并发性,有的注重安全性,有的则是并发和安全适中,在MySQL的InnoDB引擎中事务的隔离级别有四种,分别是:

  • READ UNCOMMITTED ,读未提交
  • READ COMMITTED ,读已提交
  • REPEATABLE READ ,可重复读 (默认)
  • SERIALIZABLE,串⾏化

5.3 查看和设置隔离级别

  • 事务的隔离级别分为全局作⽤域和会话作⽤域,查看不同作⽤域事务的隔离级别,可以使⽤以下的⽅式:
# 5.7版本
-- 查询全局隔离级别
SELECT @@global.tx_isolation;-- 查询会话隔离级别
SELECT @@session.tx_isolation;# 8.0版本
-- 查询全局隔离级别
SELECT @@GLOBAL.transaction_isolation;-- 查询会话隔离级别
SELECT @@SESSION.transaction_isolation;

在这里插入图片描述

  • 设置事务的隔离级别和访问模式,可以使⽤以下语法:
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level|access_mode;
# 隔离级别
level: {REPEATABLE READ # 可重复读READ COMMITTED # 读已提交READ UNCOMMITTED # 读未提交SERIALIZABLE # 串⾏化
}

5.4 不同隔离级别存在的问题

5.4.1 READ UNCOMMITTED - 读未提交与脏读
5.4.1.1 存在问题

出现在事务的 READ UNCOMMITTED 隔离级别下,由于在读取数据时不做任何限制,所以并发性能很⾼,但是会出现⼤量的数据安全问题,⽐如在事务A中执⾏了⼀条 INSERT 语句,在没有执⾏COMMIT 的情况下,会在事务B中被读取到,此时如果事务A执行回滚操作,那么事务B中读取到事务A写入的数据将没有意义,我们把这个现象叫做 “脏读” 。

问题重现:

在这里插入图片描述
在这里插入图片描述

由于 READ UNCOMMITTED 读未提交会出现"脏读"现象,在正常的业务中出现这种问题会产⽣⾮常危重后果,所以正常情况下应该避免使⽤ READ UNCOMMITTED 读未提交这种的隔离级别。

5.4.2 READ COMMITTED - 读已提交与不可重复读
5.4.2.1 存在问题

为了解决脏读问题,可以把事务的隔离级别设置为 READ COMMITTED ,这时事务只能读到其他事务提交之后的数据,但会出现不可重复读的问题,⽐如事务A先对某条数据进⾏了查询,之后事务B对这条数据进⾏了修改,并且提交( COMMIT )事务,事务A再对这条数据进⾏查询时,得到了事务B修改之后的结果,这导致了事务A在同⼀个事务中以相同的条件查询得到了不同的值,这个现象叫"不可重复读"。

问题重现:

在这里插入图片描述
在这里插入图片描述

5.4.3 REPEATABLE READ - 可重复读与幻读
5.4.3.1 存在问题

为了解决不可重复读问题,可以把事务的隔离级别设置为 REPEATABLE READ ,这时同⼀个事务中读取的数据在任何时候都是相同的结果,但还会出现⼀个问题,事务A查询了⼀个区间的记录得到结果集A,事务B向这个区间的间隙中写⼊了⼀条记录并提交,事务A再查询这个区间的结果集时会查到事务B新写⼊的记录得到结果集B,两次查询的结果集不⼀致,这个现象就是"幻读"。
MySQL的InnoDB存储引擎使用了Next-Key锁解决了大部分幻读问题

问题重现:

在这里插入图片描述

在这里插入图片描述

5.4.4 SERIALIZABLE - 串行化

进⼀步提升事务的隔离级别到 SERIALIZABLE ,此时所有事务串⾏执⾏,可以解决所有并发中的安全问题。

5.5 不同隔离级别的性能与安全

隔离级别越高,并发性越低,安全性(隔离力度)越高


http://www.mrgr.cn/news/67831.html

相关文章:

  • Moore Perf System 1.1版本
  • 在 Mac 和 Windows 系统中快速部署 OceanBase
  • Linux 系统目录结构
  • 低代码环境中的领域与根实体解析
  • 基于Zynq FPGA对雷龙SD NAND的测试
  • 昇思大模型平台打卡体验活动:基于MindSpore实现GPT1影评分类
  • hive面试题,超详细解析。各类型专利top 10申请人,以及对应的专利申请数
  • python入门到精通知乎万赞推荐书籍《流畅的Python》,《流畅的Python》PDF免费下载
  • Hive中各种Join的实现
  • 【系统架构设计师】高分论文:论企业应用系统的分层架构风格
  • 数据结构之单链表(C语言)
  • linux基础知识
  • day-81 打家劫舍 II
  • 焊接覆层耐磨板行业全面且深入的分析
  • 【零基础学习CAPL】——XML工程创建与使用详解
  • uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
  • Java题目笔记(十四)Date +综合练习
  • ruoyi-vue集成tianai-captcha验证码
  • 如何将现有VUE项目所有包更新到最新稳定版
  • C++之queue容器
  • 前端-计算机网络
  • 信息流不同行业账户流量池有区别吗?
  • 宠物空气净化器是养宠智商税吗?真实测评霍尼韦尔、希喂、米家
  • 【HarmonyOS】鸿蒙中Interface实例实现的书写格式
  • 从Apache Atlas到Aloudata BIG,数据血缘解析有何改变?
  • 为什么Uptime+Kuma本地部署与远程使用是网站监控新选择?