MySQL 事务

引入

1. 什么是计算机中的事务

事务的定义:在一个业务中,有很多操作步骤 / 任务,而事务对应的就是某项操作中不可再分割的单元,这个单元要么全部执行完,要么不执行。

MySQL 事务:一条 SQL 语句所产生的增删查改操作。(或是多条 SQL 语句、整个程序所产生的结果)

2. 计算机中为什么需要事务

举个经典的转账例子,看看使用事务和不使用事务之间的区别。

小明有 500 元,小红也有 500 元,现在正常情况下,小明转出 200 元,余额为 300;小红收到 200 元,余额为 700 元。

1-1

不使用事务和使用事务,两者的对比:

1-2

一、事务

1. 事务的回滚 (roll back)

事务的回滚:当程序出现异常,系统将将程序恢复到上一次状态的行为。

比如:上面转账系统出现问题时,系统重新将小明转出去的 200 元数据,又返回给了小明的账户中。

在 MySQL 数据库中,其实也是一样的,若增删查改数据库的过程中,出现了异常,系统就会自动将数据回滚,做到了间接的 " 不污染数据库 "。

2. 事务的基本特性 (ACID)

(1) 原子性 (Atomicity)

原子性又被称为不可分割性。

原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。如果事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

在 MySQL 数据库的操作中表示:要么将这个操作所用到的 SQL 全部执行完,要么一个 SQL 都不执行。

(2) 一致性 (Consistency)

一致性:在事务执行前后,数据库的完整性没有被破坏。这表示事务增删改查的数据必须完全符合所有的预设规则,即数据库中的数据都是合理合法的。

比方说:还是上面的转账的例子,事务需要遵循程序的规则,在不出现意外的情况下,小明给小红转了 200 元,那么小明就只能剩下 300 元,而小红的存款就必须得是 700 元。即事务执行前后,遵循数据严格的传输规则。

(3) 持久性 (Isolation)

持久性:一旦事务执行结束后,那么它对数据的增删改查就是永久的,即便系统故障也不会丢失。

(4) 隔离性 (Durability)

隔离性:数据库允许多个并发事务同时对其数据进行增删改查,隔离性可以防止多个事务并发执行时,而由于交叉执行所导致数据的不一致的情况。事务隔离分为不同级别,包括读未提交、读提交、可重复读和串行化。

二、并发与串行的概念

事务的隔离级别和事务的隔离性是息息相关的,隔离是相对于并发来说的,而并发的反面就是串行。所以说,隔离就是不同程度的并发。

举个例子:

情况(1):大学辅导员在班级群里发了一个在线文档,让同学们填。因为是在线的文档,所以每个同学都可以在同一时间内输入自己的信息,这就是并发执行。
情况(2):如果说,辅导员让同学们排队,一个一个地填写纸质的表格,那么这时候,就是串行,也叫做序列化。

结论: 可以看到,并发执行速度快,所有同学可以在最短的时间内填好表格,但可能会发生 " 同学A " 把信息填写到 " 同学B " 那一栏的表格的这种错误情况。而后者串行速度慢,但是每个同学填写表格之间互相不影响,基本不会出错。

问:既然并发和串行都有自己的优缺点,那么能不能 " 取其精华、去其糟粕 " 呢?

答:要做到完全融合两者的优点是不可能的!但在实际问题中,我们可以根据实际需要来调整数据库的隔离级别,通过不同的隔离级别控制事务之间的隔离性,同时也就控制了并发程度。

三、并发事务所产生的问题

并发事务所产生的问题也就是对应着 MySQL 中事务的隔离级别。

1. 脏读

脏读:一个事务读到另外一个事务还没有提交的数据。

2. 不可重复读

不可重复读:一个事务先后读取同一条记录 (或执行同一条 SQL语句),但两次读取的数据不同,称之为不可重复读。

3. 幻读

幻读::一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 “幻影”。

注意事项

虽然幻读和不可重复读很像,但不可重复读侧重于数据修改,两次读取到的同一行数据不一样;而幻读侧重于添加或删除,两次查询的 MySQL 记录行数不同。

不可重复读:

1-3

幻读:

1-4

解决方式

那么如何解决以上三种方式呢?

选择串行的方式,完全禁止并发事务的发生。

解决方式:大学辅导员可以让班长画一张 30 个格子的表格,让每个同学排队,线下填写表格,前一个同学填好了表格,就把表格拿给下一位同学,直至最后一位同学填好了给班长,班长检查正确无误之后,再提交给辅导员。

四、MySQL中事务的隔离级别

MySQL中事务的隔离级别,提供了四种:

1. 读未提交 (read uncommitted)

读未提交 (也叫未提交读):在该隔离级别中,事务A 可以读取到事务B 中未提交的数据。鉴于此,若 事务B 未提交的数据发生了回滚操作,那么 事务A 就直接读到了错误的数据,由此产生的问题称之为脏读。

也就是说,读未提交使得事务之间隔离级别最低,所以并发程度最高,但会引入脏读问题。进而引入不可重复读、幻读问题。

2. 读已提交 (read committed)

读已提交 (也叫提交读):在该隔离级别中,事务能读取到已经提交事务的数据,因此它不会有脏读问题。然而鉴于此,一个事务在不同时间的相同 SQL 查询中,可能会得到数据内容不同的结果,这种问题称之为不可重复读。

也就是说,读已提交使得事务之间隔离级别依旧较低,所以并发程度也就较高,但它解决了脏读问题。引入不可重复读问题,进而引入了幻读问题。

3. 可重复读 (repeatable read)

可重复读:MySQL 默认的事务隔离级别。 可重复读有效地解决了 " 不可重复读 " 的问题,但还存在幻读的问题。所谓的幻读指的是,在同一事务的不同时间使用相同 SQL 查询时,会产生不同的记录数目。

4. 串行化 / 序列化 (serializable)

串行化:事务最高隔离级别。它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题。但其执行效率低,所以真正使用的场景并不多。

小结

1-5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十七ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值