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

MySQL数据库精研之旅第十六期:深度拆解事务核心(上)

专栏:MySQL数据库成长记

个人主页:手握风云

目录

一、什么是事务

二、事务的ACID特性

三、为什么要使用事务

四、如何使用事务

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

4.2. 语法

4.3. 手动/自动提交事务

4.4. 开启一个事务,执行修改后回滚

4.5. 开启一个事务,执行修改后提交

4.6. 保存点


一、什么是事务

        事务把一组SQL语句打包成为一个整体,在这组SQL的执行过程中,要么全部成功,要么全部失败。这组SQL语句可以是一条也可以是多条。我们拿转账举例:

create table bank_account (id bigint primary key auto_increment,`name` varchar(25) 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` = '李四';

        张三给李四转100元,需要保证:不能出现张三的余额减少而李四的余额没有增加的情况,要么全部成功,要么全部失败;保证转账前后两人的总余额不变,转账前后数额要一致;转账后的余额结果应当保存到存储介质中,以便以后读取,对数据的修改应当落盘(保存到磁盘),持久化;在转账的处理过程中张三和李四的余额不能因其他的转账事件而受到干扰,把其他操作隔离开。

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

        对于隔离性,因为不同的客户端可以同时对数据库进行操作,执行的SQL语句也有可能相同。我们对一个账户余额减少100的操作,先从数据库中把1000读出来,把余额在原来的基础上减100,最后把修改过后的值写回数据库。如果有两个客户端并行执行此操作,减少了两次,余额应该是800,由于客户端1和客户端2同时(并行)进行了对数据的修改,导致得到了一个错误的结果。

二、事务的ACID特性

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

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

三、为什么要使用事务

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

        主流的数据库都支持事务,如果数据库无法支持ACID特性,那么就需要程序员耗费大量精力去维护。

四、如何使用事务

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

show engines;

        要使用事务那么数据库就要支持事务,从上图可以看出,MySQL支持事务的存储引擎是InnoDB。

4.2. 语法

-- 开启事务
start transaction;
-- 或
begin;-- 事务中要执行的SQL,一条或一组-- 提交当前事务,,并对更改持久化保存
commit;-- 回滚当前事务,取消其更改
rollback;-- 无论执行了commit或者rollback,事务都会结束

4.3. 手动/自动提交事务

        我们之前写的单条update、insert、delete语句也都在事务中,这是因为在默认情况下,,MySQL是自动提交事务的。我们执行的每个修改操作,都会自动开启一个事务并在语句执行完成之后自动提交,发生异常时自动回滚。

-- 查看当前语句是否自动提交
show variables like 'autocommit';

        如果是OFF,就需要手动commit或者rollback。

        我们也可以通过下列语句设置事务自动或者手动。

-- 设置事务自动提交
set autocommit=1;
set autocommit=ON;-- 设置事务手动提交
set autocommit=0;
set autocommit=OFF;

        手动提交模式下,不用显示开启事务,执行修改操作后,提交或回滚事务时直接使用 commit或 rollback。

4.4. 开启一个事务,执行修改后回滚

start transaction;

        只要手动开启一个事务,必须以commit或rollback结束,和是否自动提交没有关系。

-- 执行转账逻辑
update bank_account set balance = balance - 100 where `name` = '张三';
select * from bank_account;

update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;

-- 回滚之后,数据回退到最初状态
ROLLBACK;
select * from bank_account;

4.5. 开启一个事务,执行修改后提交

-- 开启一个新事务
begin;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';select * from bank_account;
-- 提交之后,才进行永久保存
commit;

        事务提交之后,无论哪个客户端查询之后,都是落盘的结果。已提交的事务不能回滚。

4.6. 保存点

        如同游戏当中存档点,在事务执⾏的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态。我们不光可以回滚到保存点,甚至可以回到事务的开启。

start transaction;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;-- 设置第一个保存点
savepoint sp1;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;-- 设置第二个保存点
savepoint sp2;-- 新增一条数据
insert into bank_account values(3, '王五',5000);
rollback to sp2;
select * from bank_account;

        在实际工作中,回滚使用的频率比保存点要高很多。

http://www.xdnf.cn/news/20213.html

相关文章:

  • python + Flask模块学习 1 基础用法
  • IC ATE集成电路测试学习——Stuck-at fault And Chain(一)
  • 场景切换 × 流畅过渡动画实现方案 | 图扑软件
  • 老师如何高效收集学生学籍信息,完成收集工作?
  • 大模型赋能电子制造全生命周期质量管理的应用及实践
  • 个人健康管理系统设计与实现
  • 代码随想录算法训练营第三天| 链表理论基础 203.移除链表元素 707.设计链表 206.反转链表
  • react antd mobile表单时间选择器
  • 系统架构思考20241204
  • 问卷系统测试报告
  • latex公式符号与字体
  • 【Lin通信】AUTOSAR架构下TC3xx芯片Lin报文收发详解
  • AI提示词增强丨用EARS语法进行产品原子化拆解
  • 【Redis】初识 Redis 与基础数据结构
  • 设置静态IP的方法
  • Docker跨架构部署实操第二弹
  • 代码改变生活:我用Python+LLM给自己写了个健身私教
  • 跨平台超低延迟RTSP播放器技术设计探究
  • EEMD-HHT算法
  • Android 权限机制默认授权分析
  • GPU版Pytorch的安装
  • 有鹿机器人的365天奇幻日记:我在景区当扫地僧
  • 如何通过 Gitee API 上传文件到指定仓库
  • go webrtc - 1 go基本概念
  • 鸿蒙Next的UI国际化与无障碍适老化实践:构建全球包容的数字世界
  • MySQL 综合练习
  • 【数据分享】上市公司数字化转型相关词频统计数据(2000-2024)
  • 解锁无限创意:Tldraw+cpolar如何通过内网穿透技术打破空间限制
  • 【leetcode】77.组合
  • DNS基本功能搭建