事务一般是针对DB来讨论
而且基本是讨论4方面,目前的解释都是在DB上讨论的
ACID
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
以在线购物为例
A花费100 购买B的商品,整个操作整体被当成事务处理
Before
A账户1000
B账户1000
After
A账户900
B账户1100
原子性
整个操作包含2个部分
1、A账户 1000-100=900
2、B账户 1000+100=1100
这两个步骤一起成功,或者一起失败,不能只发生其中一个动作
一致性
如果上面2个步骤其中一个失败了,AB账户就会有金额上的损失
持久性
完成操作后,所有数据都会保存在DB
隔离性
在多事务并发执行时,事务彼此间不影响
银行转账
A账户初始1000
B账户初始0
C账户初始900
事务1:A转账200 到B账户
事务2:C转账100 到B账户
正常执行结束后,
A:800
B:300
C:800
可能出现的问题
脏读:
当一个事务允许读取另外一个事务修改但未提交的数据时,就可能发生脏读。
如果事务1和2 ,出现脏读,并且一个事务2失败,就可能会
出现B的数据出现问题,事务2失败,但是B中依然会有300
不可重复读
在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
幻读
在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
隔离级别
隔离级别 |
脏读 |
不可重复读 |
幻影读 |
未提交读 |
可能发生 |
可能发生 |
可能发生 |
提交读 |
- |
可能发生 |
可能发生 |
可重复读 |
- |
- |
可能发生 |
可串行化 |
- |
- |
- |