ACID与隔离级别
事务具有以下四种特征:
-
原子性(Atomicity)
事务包含的所有操作要么全部成功,要么全部失败回滚。
-
一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
-
隔离性(Isolation)
不同事务并发执行操作相同数据时,每个事务都有各自完整的数据空间,即一个事务内所操作使用的数据与其他并发执行的各事务不互相干扰。
-
持久性(Durability)
一个事务一旦提交,对数据库中数据状态变更应该是永久保存下来,即使发生系统崩溃或宕机,也一定能恢复到事务成功结束时的状态。
隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 存在 | 存在 | 存在 |
读已提交 | 不存在 | 存在 | 存在 |
可重复读 | 不存在 | 不存在 | 存在 |
串行化 | 不存在 | 不存在 | 不存在 |
下面用口语化对各个隔离级别进行解释。
假设,数据库中有这样一个数据,id=1 name=张三
读未提交
事务1中,将张三修改为李四,但未提交
事务2中,就读到了id=1 name=李四
此为读未提交,存在脏读
读已提交
事务1中,将张三修改为李四
事务2中,第一次读到了id=1 name=张三
事务1,提交
事务2中,第一次读到了id=1 name=李四
此为读已提交
可重复读
事务1中,将张三修改为李四或删除
事务2中,第一次读到了id=1 name=张三
事务1,提交
事务2中,第2次读到了id=1 name=张三
此为可重复读,此为mysql的默认隔离级别
串行化
所有事务按顺序排队执行
幻读
事务1中,新增一个数据,id=2 name=李四~~、或者删除id=1的数据(此为不可重复读)~~
事务2中,第一次select * 读到了一条数据。 id=1 name=张三
事务1,提交
事务2中,若事务1新增时第2次读到了两条数据~~,若事务1删除第2次读到的结果为空(此为不可重复读)~~
MVCC
修改数据:事务未提交前,数据的新旧版本共存,但拥有不同的版本号;
读取数据:先获取当前版本号V,再去查询<=V版本已提交的数据;
写操作获取行锁,读操作不需要锁,有效避免读写锁竞争,提高读写并发度。
分布式事务方案
1、TCC方案:try(对资源做锁定或者预留)、confirm(本地提交)、cancel(本地回滚)。基于bytetcc、seata等框架。基于TransactionManager来实现
2、本地消息表:ebay提出的,国内少有人用
3、可靠消息最终一致性方案:一般来说,基于MQ来实现
4、最大努力通知方案:本地事务执行完以后,由后台任务发送消息到MQ,由后端系统去执行(需做幂等),执行完通知上游系统
5、saga:这个只有华为的service comb实现了。