分布式-事务理解
ACID
- 原子性(AtomicAtomicity)
原子性,表示最小执行单元,要么全执行,要么全部执行,和Java线程的原子性的区别在于,java在操作共享变量时,该操作对应的cpu指令的条数,由于重排序和cpu线程调度操作一个操作可能子多个时间片段进行执行。也就是操作不可再分,这个要根据cpu指令来做判断。而事务原子性更注重的是一系列的操作同成功同失败。
- 一致性(ConsConsistency)
事务总是从一个一致性状态到下一个一致性的状态。最好理解的就是转账。
- 隔离性(IsoIsolation)
并发环境中,事务之间是互不干扰的,每个事务都有自己独立的数据空间。
- 持久性(DuraDurability)
一但事务提交成功,数据发生的变化将会被持久化,不会更改
隔离级别
- 未授权读
读未提交,存在脏读,幻读,不可重复读。简单的来说,在此隔离级别下,可以感知到到其他未提交的事务的数据变化。即事务A,B,B在提交之前将字段a的值改为2,初始值为1,那么事务A会读取到a=2的值,注意,此时事务B回滚,a将会恢复为1,那么就出现了数据不一致。
- 授权读
读已提交,不可重复读,存在幻读,可以解决脏读,事务读取到的一定是其他事物成功提交后的状态。但是同一个事务多次读取可能会出现数据不一致的情况。
- 可重复读
存在幻读,事务从开始到提交此间维护了一个隔离的数据状态,多次读取到的值都是同一个值,事务不结束不会感知到其他事务对数据状态造成的改变。但是存在幻读,由于此隔离级别导致了,当前事务在修改一个范围内的操作时,其他事务新增数据行,如果恰好在此范围内,那么在当前事务结束的时候,会发现,该范围内又出现了一条未修改的数据,从而出现幻读。
- 串行化
不能并发执行数据操作,单一线程处理,所以不存在这些数据不一致的问题。
- 隔离级别表
隔离级别 | 脏读 | 可重复度 | 幻读 |
---|---|---|---|
未授权读 | 存在 | 不可以 | 存在 |
授权读 | 不存在 | 不可以 | 存在 |
可重复读 | 不存在 | 可以 | 存在 |
串行化 | 不存在 | 可以 | 不存在 |
针对 隔离级别 提高数据操作的吞吐量
- 使用授权读(读已提交),程序加上乐观锁去保证数据的一致性,可借鉴我的并发相关文章。
通过数据中加入version字段来记录操作的版本号,每一次修改操作都会加1,在客户端通过CAS无锁机制去试探性的去通过version作为操作附加值来进行数据操作,从而保证数据的一致性。
为什么要使用version,这是为了解决ABA的问题,字段a的值从1->2->1,如果通过此方式去CAS的话,在一些特定的业务场景下会出现问题。事务A开始读的是1,事物1修改为2,事务2修改回1,由于不保证可重复读,所以当前事务任然会成功执行并提交事务,事与愿违。
- 为什么不使用未授权读
当我们使用乐观锁去控制的时候,如果不能保证数据的正确性,那么就就无法继续维护一致性了未授权读会导致读脏,如果事务回滚,那么想想看,拿着错误的数据去CAS有什么意义?