欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 【MySQL】事务|概念|如何回滚|基本特性|MySQL事务隔离性具体怎么实现的

【MySQL】事务|概念|如何回滚|基本特性|MySQL事务隔离性具体怎么实现的

2025/3/9 7:32:18 来源:https://blog.csdn.net/qq_73017178/article/details/146082709  浏览:    关键词:【MySQL】事务|概念|如何回滚|基本特性|MySQL事务隔离性具体怎么实现的

目录

1.为啥引入

2.是啥

3.如何回滚(日志)

🔥4.面试题:谈谈事务的基本特性

(1)原子性

(2)一致性(收入和支出相匹配)

(3)持久性

🔥(4)隔离性

脏读问题

是什么?

如何解决?

不可重复读问题

是什么?

图解​编辑

如何解决?

幻读问题

是什么?

如何解决?


1.为啥引入

多个SQL配合,出现特殊情况,前面执行了,后面没执行

日常开发中,有很操作,不是通过一个SQL就能完成的,往往需要多个SQL配合完成,当执行多个SQL操作的时候,如果中间出现了特殊的情况(程序崩溃,系统崩溃,网络断开,主机掉电了...),就可能会出现前面SQL执行成功,后面的SQL执行失败了

举例(具体场景): 

库存表(id,count)

订单表(orderId,userId,goodId...)

进行下单操作,触发库表数据-1 && 订单表新增记录

经常会涉及到通过多个SQL配合,完成某个操作的

这个时候就需要使用到事务,来确保上述的操作,是可靠的,完整的


2.是啥

事务,就是把多个操作,打包成一个整体,就能够保证,这个整体要么都执行成功,要么就一个都不执行,有效避免部分执行,部分未执行,产生的一些”中间状态引起的问题“

原子性:把多个操作,打包成一个整体

Q1:什么叫”一个都不执行“的理解

A1:这里并不是真的没执行,事务中的若干个SQL必然是要一条一条执行的,事务能够保证,当执行到某一条的时候如果出现问题了(程序崩溃,系统崩溃,网络断开,主机掉电了...),数据库就能够自动的把前面SQL操作的影响,给恢复回去,看起来就好像一条SQL都没执行的样子

其实这里翻新的操作,成为”回滚

数据库事务的原子性,核心就是通过”回滚“机制来保证的


3.如何回滚(日志)

为了实现回滚机制,数据库会在执行事务的时候,记录日志,数据库的日志是写入到硬盘的文件

当事务最终都执行完毕,中间没有差错,这些记录的内容就可以不要了

但是如果执行事务的过程中,出现了问题,MySQL就可以根据日志中记录的内容,来进行恢复操作

1)之前进行了新增操作,就把数据删掉

2)之前进行了删除操作,就把数据新增上来

3)之前进行了修改操作,就把数据改回去

4)之前是查询操作,不影响,不需要任何恢复行为

只要数据库处于正常工作状态,就能够始终保证事务前面进行的操作被正确回滚(关系型数据库一般都能够支持这一点)

eg:

程序崩溃/网络断开:程序崩溃,但数据库是正常的,就直接进行回滚操作即可

系统崩溃/主机掉电了:这种情况MySQL服务器也挂了,那么无法立即回滚,过一段时间程序员把环境进行恢复的时候,数据库能重新启动的时候,就能够发现上次有个事务出问题了,按照前面记录的日志内容进行回滚


🔥4.面试题:谈谈事务的基本特性

(1)原子性

有回滚机制,能够触发还原

(2)一致性(收入和支出相匹配)

执行事务之前,和执行事务完毕之后,数据是一致的(不会出现这种”对不上“的情况)

也是和回滚有关的,一旦触发回滚了,回滚回去的数据得是对的;如果顺利执行,没有触发回滚,数据也是符合要求的

这个特性其实是对:”数据正确“的承诺

(3)持久性

执行事务对数据库产生的修改,就会在硬盘上持久保存,重启后仍然存在

但凡见到“持久性”就要联想到一件事:把数据存储在硬盘上

此处的持久,程序重启/主机重启。数据仍然能存在,但是如果存储在内存中,就不是持久的,内存中的数据会随着程序重启/主机重启而消息

Q1:数据不丢失和持久性一样吗

不丢失 = 持久性 + 一致性

🔥(4)隔离性

1)为何会有这个特性

如果多个客户端正好把事务赶到一块了,就需要数据库服务器都能给出处理,更糟糕的是,如果这多个事务都尝试操作同一个表,情况就会更复杂(并发处理的,这样速度比一个一个处理速度快)

2)如果一起同时处理,可能出现的问题

脏读问题
是什么?

数据库中,如果有事务A和事务B,事务A针对某个表做出了一些修改,在事务A提交之前(也就是commit告诉数据库服务器,事务完毕之前),事务B就对这里的数据进行了读取,最终就可能出现A后续操作又把上述数据进行了修改,导致最终B读到的数据和A提交的数据,是不同的

即事务B读到的是一个“临时数据”(也就是脏数据),临时数据可能会随时被修改掉

如何解决?

针对"写操作“加锁,A这边写的时候,B不能读,A写完了,B才能读

未加锁之前:执行A的同时,也能执行B(同时执行)

加锁后:执行A的过程中,B就不能执行了,要等待

这就相当于降低了”并发能力“,也就会降低数据库服务器的处理效率,提高了”隔离性“,也提高了数据的准确性

不可重复读问题
是什么?

存在三个事务.ABC.

事务A针对数据进行修改,提交;

接下来事务B进行读取数据(事务B这里的多个sql都要进行读操作);

在执行B的过程中又有一个事务C,又针对数据进行了修改

就会使B里面的不同读操作,读出来的结果不一样.

图解

开始读的数据和结束读的数据,存在差异 

如何解决?

引入读加锁,就会使“并发程度”又进一步降低,效率也随之降低“隔离性”又进一步提高,数据的准确性也会提高.这个时候,ABC都不能并发了.

幻读问题
是什么?

事务A先修改并提交数据,事务B进行读数据.此时事务C,没有修改B读的数据,但是给对应的表进行了新增数据/删除数据等操作..导致事务B中,读到的数据集不同(已有的数据内容是一致的,数都是据的条数增加/减少)

可以视为是“不可重复读”的特殊情况

简单理解:读的数据内容不变,但是数据量多了

而不可重复读:读的数据内容变了

如何解决?

解决幻读的方式,“串行化”使所有的事务都严格的按照“一个接一个”的方式执行.完全没有并发了.此时执行效率是最低的,隔离性也是最高的,数据也是最准确的. 

小结:

<1> 脏读:事务B读到了事务A中未提交的临时数据(脏数据) => 写加锁

<2> 不可重复读:事务B读的过程中,又有事务C对刚才事务A提交的数据进行了修改,使事务B内部不同的读操作读到的结果不同  =>读加锁

<3> 幻读:和不可重复读类似,事务B读的过程中,事务C没有修改数据内容,而是修改了”结果集“,导致B内不同的读操作读到的结果集合不同 => 串行化

解决上述问题过程中,要想让数据更准确,就需要牺牲一部分的并发/效率

3)MySQL事务隔离性具体怎么实现的

MySQL给程序员提供了四个隔离级别,可以在MySQL中配置文件中进行设置

<1> read uncommitted:允许读取其他事务未提交的数据 

-> 脏读 + 不可重复读 + 幻读  (并发程度最高,隔离性最低)

<2> read committed:只能读取其他事务提交后的数据

-> 解决了脏读,存在不可重复读+幻读 (并发程度低,隔离性提高)

<3> repeatable read:针对读操作和写操作都加锁了

-> 解决了脏读 + 不可重复读,存在幻读 (并发程度又低,隔离性又提高)

<4> 串行化(serializable):所有的事务都是串行执行的

-> 解决了脏读 + 不可重复读 + 幻读 (并发基本没有,隔离性最高)

修改MySQL的配置文件,使MySQL服务器处于某个隔离级别中来运行

eg:

做一个和钱有关的系统,可以设置成串行化

做一个短视频点赞系统,就可以设置成读未提交,追求最大的效率

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词