精通Java事务编程(9)-总结
事务作为抽象层,允许应用忽略DB 内部一些复杂并发问题和某些硬件、软件故障,简化应用层的处理逻辑:事务中止(transaction abort),而应用仅需重试。对复杂访问模式,事务可大大减少需要考虑的潜在错误情景数量。
如没有事务,各种错误情况(进程崩溃,网络中断,停电,磁盘已满,意外并发)意味着数据可能各种不一致。如非规范化的数据可能很容易与源数据不同步。没有事务处理,就很难推断复杂的交互访问可能对数据库造成影响。
隔离等级要点:
-
脏读
客户端读到另一客户端尚未提交的写。读已提交 或更强的隔离级别可防止
-
脏写
一个客户端覆写了另一客户端尚未提交的写。几乎所有事务实现都可防止
-
读倾斜(不可重复读)
同一个事务中,客户端在不同时间点看见数据库不同值。快照隔离 用于解决这问题,允许事务从某特定时间点的一致性快照中读数据,MVCC实现
-
更新丢失
两个客户端同时执行 读取 - 修改 - 写入。其中一个写操作,在没有合并另一个写入变更情况下,直接覆盖了另一个写结果。所以导致数据丢失。快照隔离的一些实现可自动防止这种异常,而另一些实现则需手动锁定(
SELECT FOR UPDATE
) -
写倾斜
一个事务读取一些东西,根据它所看值决定,并将该决定写数据库。但写时,该决定的前提不再true。只有可串行化隔离才能防止
-
幻读
事务读取某些符合查询条件的对象,同时另一客户端写,改变了先前查询结果。快照隔离可防简单的幻读,但写倾斜的幻读需特殊处理,如采用索引范围锁定。
弱隔离级别可防止上述的一些异常,但还得应用程序开发人员手动处理其它复杂 case,如显式加锁。
只有可串行化隔离级别能防所有这些问题,有三种不同实现方案:
-
严格串行执行事务
若每个事务的执行很快,且单CPU核即可满足事务吞吐要求,这是简单有效的选择
-
2PL
数十年来,一直是可串行化的标准实现,但许多应用考虑性能而放弃使用之
-
可串行化快照隔离(SSI)
最新算法,避免先前方案的大部分缺点。使用乐观锁机制,允许事务并发执行而不互相阻塞。仅当事务提交时,才检查可能的冲突,若发现违背串行化,则中止事务
- 点赞
- 收藏
- 关注作者
评论(0)