目录
1 事务的概念
2 事务的特性 ACID
3 事务的提交和回滚
4 事务的并发问题(脏读、不可重复读、幻读)
4.1 脏读
4.2 不可重复读
4.3 幻读
5 事务隔离级别
转载博文:
MySql事务及原理详解-鸿蒙开发者社区-51CTO.COM
https://ost.51cto.com/posts/11191
【数据库】快速理解脏读、不可重复读、幻读
https://blog.csdn.net/qq_33591903/article/details/81672260
1 事务的概念
- 事务是数据库中最小的工作单元,是一个原子操作
- 事务有一条或多条 SQL 语句组成
- 在同一事务中,所有的 SQL 语句都成功执行时,整个事务成功!有一个SQL语句执行失败,则整个事务都执行失败!
|
2 事务的特性 ACID
- 原子性 (Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会在中间某个环节结束
- 一致性 (Consistent):一方面,在事务开始之前和事务结束以后,数据库的完整性没有被破坏;另一方面,写入的数据必须完全符合所有的预设规则
- 隔离性 (Isolation):不同的会话或线程,操作数据库的时候可能产生多个事务。如果同时操作一张表或同一行数据,必然产生并发或干扰操作。隔离性要求事务间对表或数据操作是透明的,互相不存在干扰的,通过这种方式保证一致性。
- 持久性(Durable):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
|
3 事务的提交和回滚
在事务的执行过程中,每一条 DML 操作都会被记录到“事务性活动的日志文件”中,我们可以提交事务,也可以回滚事务。提交事务 (commit) 会清空“事务性活动的日志文件”,将数据全部彻底持久化到数据库中,提交事务标志着事务的结束,是一种 SQL 语句全部成功的结束。回滚事务 (rollback) 会清空该事务之前所有的 DML 操作,并清空“事务性活动的日志文件”,回滚事务标志着事务的结束,是一种 SQL 语句全部失败的结束。 MySQL 默认情况下是自动提交事务的,即每执行一条 DML 语句,提交一次事务。可以通过 begin 或 start transaction 开启事务。 |
4 事务的并发问题(脏读、不可重复读、幻读)
4.1 脏读
脏读表示一个事务在处理过程中,读取到了其他事务未进行提交的数据。这种数据被称之为脏数据,依据脏数据进行的操作可能是不正确的。
时间顺序 | 转账事务 | 取款事务 |
---|
1 | | 开始事务 | 2 | 开始事务 | | 3 | | 查询账户余额为2000元 | 4 | | 取款1000元,余额被更改为1000元 | 5 | 查询账户余额为1000元(产生脏读) | | 6 | | 取款操作发生未知错误,事务回滚,余额变更为2000元 | 7 | 转入2000元,余额被更改为3000元(脏读的1000+2000) | | 8 | 提交事务 | | 备注 | 按照正确逻辑,此时账户余额应该为4000元 | |
4.2 不可重复读
不可重复读是指在一个事务范围内,多次进行相同的查询,却得到不同结果。也就是说多次读取同一条记录,但记录中的某些列的值被修改过。
时间顺序 | 事务A | 事务B |
---|
1 | 开始事务 | | 2 | 第一次查询,小明的年龄为20岁 | | 3 | | 开始事务 | 4 | 其他操作 | | 5 | | 更改小明的年龄为30岁 | 6 | | 提交事务 | 7 | 第二次查询,小明的年龄为30岁 | | 备注 | 按照正确逻辑,事务A前后两次读取到的数据应该一致 | |
4.3 幻读
幻读是指当事务不是独立执行时发生的一种现象,幻读主要是说多次读取一个范围内的记录,包括直接查询所有记录结果或聚合统计,发现了结果数量的不一致性 (包括结果的增多或减少)。
时间顺序 | 事务A | 事务B |
---|
1 | 开始事务 | | 2 | 第一次查询,数据总量为100条 | | 3 | | 开始事务 | 4 | 其他操作 | | 5 | | 新增100条数据 | 6 | | 提交事务 | 7 | 第二次查询,数据总量为200条 | | 备注 | 按照正确逻辑,事务A前后两次读取到的数据总量应该一致 |
5 事务隔离级别
看一下 SQL92 ANSI/ISO 定义的事务的四种隔离级别:
- Read Uncommitted (读未提交):事务未提交的数据对其他事务也是可见的,会出现脏读
- Read Committed (读已提交):一个事务开始后,只能看到已提交的事务所做的修改,会出现不可重复读
- Repeatable Read (可重复读):在同一个事务中多次读取同样的数据结果是一致的,这种隔离级别未定义解决幻读的问题
- Serializable (串行化):最高的隔离级别,通过强制事务的串行执行
那么这几个级别能解决什么问题呢:
- 在读未提交级别,不能解决任何事务并发的问题
- 在读已提交级别,能够解决脏读问题
- 在可重复读级别,能够解决不可重复读问题
- 在串行化级别,能够解决所有问题,但是相应的会降低数据库事务的并发度,降低性能
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|
读未提交 | 是 | 是 | 是 | 读已提交 | 否 | 是 | 是 | 可重复读 | 否 | 否 | 是 | 串行化 | 否 | 否 | 否 | | |