本系列文章描述了DB并发控制的黯淡:

  • 2PL虽保证了串行化,但性能和扩展不好
  • 性能良好的弱隔离级别,但易出现各种竞争条件(丢失更新,写倾斜,幻读

串行化的隔离级别和高性能就是相互矛盾的吗?也许不是,一个称为可串行化快照隔离(SSI, serializable snapshot isolation)算法很有前途。提供完整的可串行化保证,而性能与快照隔离相比只有很小性能损失。 SSI在 2008 年首次被提出,如今既用于单节点DB(PostgreSQL9.1后的可串行化)和分布式DB(FoundationDB)。由于 SSI 与其他并发控制机制相比还很年轻,还在实践中证明自己。

3.3.1 悲观锁、乐观锁

两阶段锁是一种 悲观锁机制(pessimistic) ,其设计原则:若有操作可能出错(如与其他事务发生锁冲突),则直接放弃,等待直到绝对安全。和多线程编程中的互斥锁一致。

某种意义上,串行执行是很悲观的:事务期间,每个事务对整个DB(或DB的一个分区)持有互斥锁,我们只能假定每笔事务执行够快、短时持锁,来稍微弥补悲观色彩

相比之下,串行化快照隔离 是一种 乐观锁。如若存在潜在冲突,也不阻止事务,而是继续执行事务,寄希望于一切平安。而当事务想提交时(只有可串行化的事务才被允许提交。),DB会检查是否冲突(即违反隔离性原则):若是,则中止事务并重试。

乐观锁是古老的想法,其优缺点争论已久。若存在很多冲突,则性能不佳,大量事务需中止。若系统已接近最大吞吐量,重试的额外负载会使系统性能更差。

但若系统有足够性能提升空间,且事务之间争用不大,乐观锁比悲观锁更高效。可交换的原子操作能减少争用:如若多个事务同时增加某计数器,则应用增量的顺序(只要计数器不在同一个事务中读取)就无关紧要,所以并发增量可全部应用且无需冲突。

SSI基于快照隔离,即事务中的所有读取都基于DB的一致性快照(参阅本文的快照隔离、可重复读),这和早期乐观锁的主要区别。在快照隔离基础上,SSI新增一种算法检测写入之间的串行化冲突,并确定要中止哪些事务。

3.3.2 基于过期条件来决策

讨论写倾斜时,有一种场景:事务先从DB读一些数据,根据查询结果决定采取后续操作,如修改数据。但快照隔离下,数据可能在查询期间就已被其他事务修改,导致原事务在提交时决策的依据信息已变。

即事务基于某些前提而行动,事务开始时条件成立,如目前有两名医生正在值班,当事务提交时,数据可能已改变,前提已不再成立。

当应用执行查询时(如当前有多少医生在值班),DB本身不知道应用会如何使用该查询结果。为了安全,DB假定对该结果集的变更都可能会使该事务中的写无效。 即事务中的查询与写可能存在因果依赖关系。为提供可串行化隔离,DB必须检测事务是否会修改其它事务的查询结果,并在此情况下中止写事务。

DB如何知道查询结果是否已变?可分为如下case:

  • 读取是否作用于一个(即将)过期的MVCC对象(读取之前已经有未提交的写入)
  • 检查写是否影响即将完成的读取(读取后,又有新写入)

3.3.3 检测旧MVCC读取

快照隔离通常采用MVCC实现。当事务从 MVCC DB的一致性快照读时,会忽略创建快照时还没提交的事务写入。如图-10:

  • 事务43认为 Aliceon_call = true ,因事务 42(修改 Alice 值班状态)还没提交
  • 然而,事务43提交时,事务42已提交

即从快照读取时,被忽略的写已生效,直接导致事务43做决定的前提不再成立。

为防止这种异常,DB需跟踪一个事务由于MVCC可见性规则而被忽略的其它事务写。当事务提交时,DB会检查是否存在被忽略的写现在已被提交的,若是,则当前事务必须中止。

为何要等到提交?当检测到读旧值,为何不立即中止事务43,考虑如下场景:

  • 若事务43是只读事务,则无需中止,因为无写倾斜风险

  • 当事务43读DB 时,DB还不知道事务是否要稍后执行写操作

  • 此外,事务42可能在事务43提交时,被中止或仍处于未被提交,因此读取的并非旧值

通过避免不必要的中止,SSI可高效支持那些需在一致性快照中运行很长时间的读事务。

3.3.4 检测写是否影响之前的读

读取数据后,另一个事务修改了数据:

2PL下讨论了索引范围锁,允许DB锁定和某查询匹配的所有行,如WHERE shift_id = 1234。可在此使用类似技术,只有一点差异:SSI锁不阻塞其他事务。

图-11中,事务42、43 都在班次1234查找值班医生。若 shift_id 有索引,则DB能使用索引项1234记录事务42、43读取这个数据的事实。若无索引,可在表级别跟踪此信息。该信息只需保留很小一段时间:当所有并发事务完成后,就能丢弃。

当另一事务写时,先检查索引,从而确定是否在最近存在一些读目标数据的其它事务。这过程类似在受影响字段范围上获取写锁,但锁不会阻塞其它事务读取,而是直到读事务提交时才进一步通知它们:所读到的数据已变化。

图-11中,事务43通知事务42其先前读已过时,反之亦然。事务42先提交并成功,尽管事务 43写影响了42 ,但因43没提交,所以写还没生效。当43提交时,来自42的冲突写入已被提交,所以43必须中止。

3.3.5 性能

许多工程细节会影响算法实际效果。如一个需权衡考虑的是跟踪事务的读、写的粒度:

  • 若DB详细跟踪每个事务的操作(细粒度),确实能准确确定哪些事务需中止,但记录元数据的开销可能也很大
  • 而跟踪速度更快时(粗粒度),可能导致更多不必要的事务中止

有的case读过期数据不会造成太大影响:这还是完全取决于具体场景,有时可确信执行结果都是可串行化的,PostgreSQL 使用该理论减少不必要的中止。

相比于2PL,可串行化快照隔离最大优点:事务无需阻塞等待其它事务所持有的锁。这和快照隔离一样,读写不互相阻塞。这使查询延迟更稳定、可预测。尤其是只读查询可运行在一致快照,无需任何锁,对读密集系统友好。

相比于串行执行,可串行化快照隔可突破单CPU核吞吐量限制:FoundationDB将检测到的串行化冲突分布在多台机器,从而提高吞吐量。即使数据可能跨多台机器分区,事务也能在保证可串行化隔离等级同时,读写多个分区中的数据。

事务中止率会显著影响SSI性能。如长时间读、写数据的事务很可能会发生冲突并中止,因此SSI要求读写型事务尽量短(但只读的长事务则没问题)。总体上,对慢事务,SSI比2PL或串行执行更能容忍。

精通Java事务编程(8)-可串行化隔离级别之可串行化的快照隔离相关推荐

  1. Java事务编程-弱隔离级别之写倾斜与幻读

    多个事务并发写相同对象时,会出现脏写和更新丢失两种竞争条件.为避免数据不一致,可: 借助DB内置机制 或通过显式加锁.执行原子写操作 但这还不算并发写可能引发的全部问题. 为医院写一个值班管理程序.医 ...

  2. 并发事务正确性的准则 可串行化_从0到1理解数据库事务(上):并发问题与隔离级别...

    最近准备写一篇关于Spanner事务的分享,所以先分享一些基础知识,涉及ACID.隔离级别.MVCC.锁,由于太长,只好拆分成上下两篇: 上:并发问题与隔离级别 主要讲事务所要解决的问题.思路,先理解 ...

  3. 支持串行隔离级别_从0到1理解数据库事务(上):并发问题与隔离级别

    最近准备写一篇关于Spanner事务的分享,所以先分享一些基础知识,涉及ACID.隔离级别.MVCC.锁,由于太长,只好拆分成上下两篇: 上:并发问题与隔离级别 主要讲事务所要解决的问题.思路,先理解 ...

  4. 事务隔离级别——未提交读、已提交读、可重复读、串行

    事务隔离级别--未提交读.已提交读.可重复读.串行 事务隔离级别是指多个事务之间,不同事务中涉及的读写操作互相影响的隔离.其中多个事务中同时对同一条数据或者表进行写操作(insert.update.d ...

  5. 第七周 Java语法总结之数据库大全_DDL_DML_DQL_约束_备份与还原_表的关系_三大范式_多表查询(内连接_外连接_子查询)_musql事务_隔离级别

    文章目录 数据库 DDL语句:数据库定义语句 1.库的增删查改 1.查询当前mysql下所有的数据库 2.创建数据库 3.查看创建数据库的默认的字符集(了解) 4.修改数据库的字符集(了解) 5.删除 ...

  6. mybatis 源码系列(七) Java基础之数据库事务隔离级别

    更多mybatis 源码系列文章可关注我的博客,点击前往 正确设置数据库的事务访问级别,有助于我们的应用程序达到预期的效果 在mybatis中,提供了事务隔离级别的枚举类:org.apache.iba ...

  7. 隔离区别对待?如何捆绑?Java中的jdbc数据库事务及其隔离级别

    文章目录 一.数据库事务简介 二.JDBC事务处理 三.事务的ACID属性 四.数据库的隔离级别 五.设置隔离级别 一.数据库事务简介 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态. 事务 ...

  8. java innodb存储引擎_MySQL InnoDB存储引擎的事务隔离级别

    我们知道,在关系数据库标准中有四个事务隔离级别:未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 提交读(Read Committed):只能读取 ...

  9. Java事务的ACID属性和四种隔离级别和传播机制

    事务的ACID属性 数据库管理系统中事务(transaction)的四个特性(分析时根据首字母缩写依次解释):原子性(Atomicity).一致性(Consistency).隔离性(Isolation ...

最新文章

  1. ecplise 安装subclipse
  2. python正则表达式操作指南_Python正则表达式操作指南
  3. 2017.5.5-afternoon
  4. EF Core 2.1路线图:视图、GROUP BY和惰性加载
  5. apache-commons pool使用
  6. read实现交互输入自动化(笔记)
  7. 在原生js中的,table表格,display:block之后,样式混乱
  8. [转]Flex是什么?flex和flash是什么关系 ?
  9. FHJ学长的心愿 QDUOJ 数论
  10. 《Java设计模式》刘伟 超清晰版本 下载链接
  11. 【js】pagination分页(支持首页,末页,跳转)
  12. greenDao的使用与封装
  13. .net6智能提示设置为中文
  14. 数字孪生技术实现和案例
  15. 推荐四个Flutter重磅开源APP项目!
  16. 分布式数字身份 —— 从创建一个Weidentity数字身份开始
  17. 微信小程序 ECharts 水球图
  18. 手机运行慢可以刷机吗_安卓手机反应慢怎么处理刷机有用吗(一个“动作”就能轻松解决,比新买的速度还快)...
  19. 求答案 ? 一筐鸡蛋: 1个1个拿,正好拿完。 2个2个拿,还剩1个。 3个3个拿,正好拿完。 4个4个拿,还剩1个。 5个5个拿,还差1个。 6个6个拿,还剩3个。 7个7个拿,还剩4个。 8个8个
  20. 刷脸支付未来出门只要一张脸就能走天下

热门文章

  1. arcgis server认证失败
  2. 湖北师范大学计算机考研资料汇总
  3. 童牧野中国十年股市十大名人 主要书籍著作及论宝塔线
  4. 关于罗永浩将要进军AR/VRMR领域,你又有什么评价呢?
  5. 微信小程序打开微信公众号中的文章实战教程
  6. 主成分分析碎石图_主成分分析(PCA)基本原理及分析实例
  7. 学3D建模能作为副业吗?
  8. 马科维茨投资组合理论(均方模型)学习笔记——基于Matlab(二)
  9. uni-app学习(一)
  10. SQL汇总显示各个省包所含的城市及县区