MySQL-06-事务与ACID
6.1 事务及其相关概念
1. 什么是事务?
- 事务就是将一组SQL语句放在同一批次内去执行,如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行,一句话总结就是:要么全部执行,要么全部不执行
2. 事务的原则(ACID)
- 原子性(Atomic)
- 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性(Consistency)
- 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 例如:转账过程中,AB两个共1000元,那么不管事务怎么执行,两个人的钱的总和一定是1000不会变。除非有别的新事务发生
- 隔离性(Isolation)
- 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性(Durability)
- 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。如果在系统故障前,事务没有提交,则回滚。不然,则保证更改
- 注意,尽可能让某批操作满足这四个特性,那么,我们就可以称它是一个事务,或者说是一个正确的、完美的事务。
3. 并发情况下,事务潜在的问题
-
参考链接:https://blog.csdn.net/qq_33591903/article/details/81672260
-
脏读
-
一个事务读取了另外一个事务未提交的数据。
-
典例:转账和存款同时进行
时间顺序 转账事务 存钱事务 1 开始 2 开始 3 查询余额,2000 4 查询余额为1000(这里发生了脏读) 取款1000,余额改变为1000 5 转入2000,余额为3000 6 取款失败,回滚余额为2000 7 提交事务 事务提交 -
结果:余额为3000,正确结果应为4000
-
-
不可重复读
-
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对,数据可能变化,也可能丢失)
-
出现在
delete
和update
操作中 -
举例
时间顺序 事务A 事务B 1 开始事务 开始事务 2 查询余额3000 3 更改余额为6000 4 其他操作 提交事务 5 再次查询余额,为6000 -
按照正确逻辑,事务A在执行期间,每次查询结果应该相同
-
-
幻读
-
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
-
与不可重复读的区别:幻读在第一次一定是不存在的,第二次却存在了。因为发生了
insert
操作 -
例如
时间 事务A 事务B 1 开始事务 开始事务 2 首次查询,数据量为100行 3 新增100行数据 4 提交事务 5 其他操作 6 再次查询,数据量为200行 -
按照逻辑,事务A两次查询的结果数量应该是相同的
-
6.2 事务的四种隔离级别
-
四种隔离级别的实现涉及到MySQL的锁机制与MVCC机制,这里不详述,日后在在详细分析
-
为了权衡『隔离』和『并发』的矛盾,ISO定义了4个事务隔离级别,每个级别隔离程度不同,允许出现的副作用也不同。
- 未授权读取,也称为读未提交(Read Uncommitted)
- 最低级别,允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作
- 授权读取,也称为读提交(Read Committed)
- 语句级别,允许不可重复读和幻读,但不允许脏读。
- 可重复读取(Repeatable Read)
- 事务级别;只会出现幻读问题。
- 序列化(Serializable):提供严格的事务隔离,事务完全串行执行,毫无并发可言,并发性能极低,但不会出现任何问题
- 未授权读取,也称为读未提交(Read Uncommitted)
-
注意:这四个级别只是一个标准,各个数据库厂商,并不完全按照标准做的。
-
副作用
隔离级别 脏读 不可重复读 幻读 Read Uncommitted(RU) √ √ √ Read Committed(RC) × √ √ Repeatable Read(RR) × × √ Serializable(SE) × × ×
6.3 MySQL的事务执行
-
注意,只有InnoDB引擎支持事务
-
事务执行流程范例
-- 1.关闭自动提交,MySQL默认自动开启 SET autocommit=0 -- 开启事务 START TRANSACTION -- 执行事务 ...各种SQL语句 -- 提交事务 COMMIT -- 如果失败,则回滚 ROLLBACK -- 还原自动提交 SET autocommit =1 -- 保存点 SAVEPOINT 保存点名称 -- 设置一个事务保存点 ROLLBACK TO SAVEPOINT 保存点名称 -- 回滚到保存点 RELEASE SAVEPOINT 保存点名称 -- 删除保存点