【MySQL】别让数据 “翻车”!MySQL 事务:从崩溃到稳如泰山的秘密武

61 阅读6分钟

前言:

在后端开发中,你是否遇到过这样的糟心场景?用户支付成功,余额扣了但订单却没生成;批量导入数据时突然断电,重启后部分数据重复、部分数据丢失……这些“数据翻车”的背后,几乎都藏着一个共同的漏洞——没用好 MySQL 事务。

如果把数据库比作一个繁忙的仓库,那数据操作就是工人搬运货物的过程。要是搬运到一半突然停电,货物扔在半路、货架空空如也,整个仓库就会陷入混乱。而 MySQL 事务,就是给这个搬运过程装了一道“安全锁”:要么把所有货物完好地搬到位,要么一旦出问题就退回原点,绝不留下半拉子工程。今天我们就扒透事务的底层逻辑,教你用它把数据安全牢牢握在手里。

文章目录 一:事务的概念以及使用场景 二:事务的ACID特性---数据安全的“四梁八柱” 3.1 Atomicity (原子性): 3.2 Consistency (一致性): 3.3 Isolation (隔离性): 3.4 Durability (持久性): 三:为什么要使用事务? 四:那么该如何使用事务呢? 五:进阶:隔离级别——解决“并发事务”的冲突 不同隔离级别存在的问题: 六:避坑指南:这些事务“陷阱”一定要避开

  1. 陷阱1:把“非事务安全表”当事务表用
  2. 陷阱2:在事务中执行“非事务操作”
  3. 陷阱3:事务过大,导致锁等待或死锁 七:总结:事务不是“银弹”,但没有事务万万不能 一:事务的概念以及使用场景 事务把一组SQL语句打包成为一个整体,在这组SQL的执行过程中,要么全部成功,要么全部失败。这组SQL语句可以是一条也可以是多条。 以一个转账例子为例:

初始状态:

先进行张三余额减少100

UPDATE bank_account set balance = balance - 100 where name = '张三'; AI写代码 sql 1

在进行李四余额增加100

UPDATE bank_account set balance = balance + 100 where name = '李四'; AI写代码 sql 1

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

张三的账户余额减少 100 ,变成 900 ,李四的账户余额增加了 100 ,变成 1100 ,不能出现张三的余额减少而李四的余额没有增加的情况; 张三和李四在发生转账前后的总额不变,也就是说转账前张三和李四的余额总数为1000+1000=2000 ,转账后他们的余额总数为 900+1100=2000 ; 转账后的余额结果应当保存到存储介质中,以便以后读取; 还有一点需要要注意,在转账的处理过程中张三和李四的余额不能因其他的转账事件而受到干扰; 这四点在事务的整个执行过程中必须要得到保证,这也就是事务的 ACID 特性

二:事务的ACID特性—数据安全的“四梁八柱” 事务的ACID特性指的是 Atomicity (原子性), Consistency (一致性), Isolation (隔离性) 和 Durability (持久性)。

3.1 Atomicity (原子性):   一个事务中的所有操作,要么全部成功,要么全部失败,不会出现只执行了一半的情况,如果事务在执行过程中发生错误,会回滚( Rollback )到事务开始前的状态,就像这个事务从来没有执行过一样;

3.2 Consistency (一致性):  在事务开始之前和事务结束以后,数据库的完整性不会被破坏。这表示写入的数据必须完全符合所有的预设规则,包括数据的精度、关联性以及关于事务执行过程中服务器崩溃后如何恢复;

3.3 Isolation (隔离性):  数据库允许多个并发事务同时对数据进行读写和修改,隔离性可以防止多个事务并发执⾏时由于交叉执行而导致数据的不一致。事务可以指定不同的隔离级别,以权衡在不同的应⽤场景下数据库性能和安全;

3.4 Durability (持久性):  事务处理结束后,对数据的修改将永久的写入存储介质,即便系统故障也不会丢失

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

四:那么该如何使用事务呢?  要使用事务那么数据库就要支持事务,在MySQL中支持事务的存储引擎是InnoDB,可以通过show engines; 语句查看:

语法:

开始一个新的事务

START TRANSACTION;

BEGIN; AI写代码 sql 1 2 3 提交当前事务,并对更改持久化保存

COMMIT; AI写代码 sql 1 回滚当前事务,取消其更改

ROLLBACK; AI写代码 sql 1 • START TRANSACTION 或 BEGIN 开始⼀个新的事务; • COMMIT 提交当前事务,并对更改持久化保存; • ROLLBACK 回滚当前事务,取消其更改; • 无论提交还是回滚,事务都会关闭

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

开启事务

表中数据

执行sql使张三余额减少100

执行sql使李四余额增加100

发现此时的余额相比之前已经修改了

执行回滚操作

发现回到了初始状态值

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

开启事务,先查看表中的初始值

再次执行张三减100,李四加100操作

进行事务提交

再查询发现数据已被修改,说明数据已经持久化到磁盘

在事务执行的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态

在次进行开启事务并对张三减100,李四加100操作

我们来设置保存点,看看最终效果如何

SAVEPOINT savepoint1; AI写代码 sql 1 对张三减100,李四加100操作

设置第⼆个保存点

SAVEPOINT savepoint2; AI写代码 sql 1 插入一条新记录

insert into bank_account values (null, '王五', 1000); AI写代码 sql 1

回滚到第二个保存点

ROLLBACK TO savepoint2; AI写代码 sql 1 发现回滚到了插入王五数据前 ————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                    

原文链接:blog.csdn.net/2301_803502…