一. 事务的ACID四特性
-
原子性(Atomicity)
事务原子性,要求事务开始后,无论中间执行了多少指令/SQL,要么全部成功,要么全部失败,不会出现部分成功部分失败的情况。类似化学中原子(atom)指化学反应不可再分的基本微粒,原子在化学反应中不可分割。 -
一致性(Consistency)
事务一致性,是事务前后对数据完整性的约束,包括主键约束、外键约束或是一些用户自定义约束。事务执行的前后都是合法的数据状态,不会违背任何的数据完整性。 -
隔离性(Isolation)
事务隔离性,是定义在并发情况下多个事务之间相互影响及可见性的规则。不同情况下,对隔离性的要求会不同;不同的隔离级别,对并发性能的影响也不同。这也是本文重点要讨论的事务隔离级别 -
持久性(Durability)
事务持久性,要求事务一旦提交,对数据的更新一定是永久的,是不可回滚的,是保存在数据库文件中的。
二. 并发事务带来的问题
-
脏读(dirty read)
事务A查询2次余额不一致,第二次查询到了事务B未提交的数据,读取了脏数据,称之为脏读。
事务A | 事务B |
---|---|
开始事务 | ... |
查询余额=100元 | 开始事务 |
... | 更新余额=150元 |
查询余额=150元 | ... |
... | 提交事务 |
-
不可重复读(non-repeatable read)
事务A前2次读取余额一致,未受事务B更新数据的影响,因为事务B此时还未提交,事务A没有产生脏读;
事务A第3次查询余额不一致,因为事务B此时已提交影响到了事务A对同一数据的重复读取,称之为不可重复读。
事务A | 事务B |
---|---|
开始事务 | ... |
查询余额=100元 | 开始事务 |
... | 更新余额=150元 |
查询余额=100元 | ... |
... | 提交事务 |
查询余额=150元 | ... |
-
幻读(phantom read)
事务A两次读取数据条数不一致,第二次读取了事务B已提交的数据(主要是新增和删除的数据),有产生“幻觉”的意思,称之为幻读。
事务A | 事务B |
---|---|
开始事务 | ... |
查询余额>100的数据=5条 | 开始事务 |
... | 插入1条余额=50的数据 |
... | 提交事务 |
查询余额>100的数据=6条 | ... |
注意:
a. 不可重复读和幻读都是读取事务已提交的数据,这点跟脏读有本质区别
b. 不可重复读和幻读容易混淆,不可重复读侧重数据的【修改】,幻读侧重数据的【新增和删除】
三. 如何解决?事务隔离级别
-
读未提交(read uncommited)
允许当前事务读取其他事务未提交的数据,会产生脏读问题 -
读已提交(read commited)
允许当前事务读取其他事务已提交的数据,可避免脏读,但会造成不可重复读问题 -
可重复读(repeatable read)
保证当前事务多次读取同一数据的值是一致的,可避免不可重复读,但会产生幻读。 -
串行化(serializable)
所有读写操作均加锁,如果产生冲突则后来的事务需要等待前一个事务完成后才能继续执行。可以完全避免上述问题,但付出的代价最大,效率和并发能力最低
. | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read uncommited) | ✔ | ✔ | ✔ |
读已提交(read commited) | ✖ | ✔ | ✔ |
可重复读(repeatable read) | ✖ | ✖ | ✔ |
串行化(serializable) | ✖ | ✖ | ✖ |
a. ✔表示会产生该问题,✖表示不会产生该问题
b. mysql的InnoDB和Falcon存储引擎通过MVCC(Multiversion Concurrency Control)机制解解决了幻读问题。
网友评论