读书笔记:数据密集型应用系统设计 事务

数据密集型应用系统设计

事务

弱隔离级别的介绍

读-提交

脏写

写入尚未提交的事务的一部分

读-提交 这个隔离级别,并不能克服下列图所示的,计数器增量竞争的情况

img

最后的结果就是“更新丢失”。

如何防止脏写

img

脏读

如何防止脏读

img

快照级别隔离

不可重复读问题

如下图所示的 case:

img

在红线处,第一个查询 account1 已经结束,向 account1 转账的的事务还没有提交,所以根据读-提交的性质,此时的查询结果为 500。第二个查询 account2 的发起时机是在 account2 转出 100 元,且事务已经提交,根据读-提交的性质,此时可以查询到 account2 的账户是 400 元。在这两次的查询中,两个账户的总额为 900 元,少了 100 元。查询的结果是不符合数据库预期状态的,在过段时间重新执行这两个查询,能够得到符合预期的结果。这种现象称为不可重复读,或者读倾斜(nonrepeatable read or read skew)。所谓 read skew,个人理解为读的时机不对,在整个数据库的状态中,读-提交这个隔离级别,会有一段时间的数据库状态是 “不一致” 的,如果在此时进行读数据库,就会得到错误的结果。

使用快照隔离解决上述的问题,总体思路如下:

img

发现错别字了。

如何实现快照隔离

img

下面的图解释了 PostgreSQL 数据库是如何基于 MVCC 来实现快照级别的隔离的

img

就是给每一行记录,增加两个字段:

  1. created_by 字段,其内容为创建该记录的事务号
  2. deleted_by 字段,其内容为删除该记录的事务号

在事务的执行过程中,通过对这两个字段的进行填充事务号,等到数据库进程进行垃圾回收的时候,真正删除数据。

写倾斜与幻读

写倾斜

img

如图所示,Alice 和 Bob 执行事务,在事务中,需要修改各自的记录中对应的 on_call 字段的状态,查询语句执行完成后,得到 currently_on_call = 2,两个事务都会进行各自的修改,最后导致 Alice 和 Bob 的 on_call 字段都为 false。

写倾斜是一种更广义的更新丢失问题。如果两个事务读取相同的一组对象,然后更新其中的一部分,不同的事务可能更新不同的对象,则可能会发生写倾斜。

为了自动防止写倾斜,要求“可串行化”的隔离级别。

幻读

img

如何解决幻读问题:

img

可重复读

串行化

如何实现串行化:

img

两阶段锁:

img

也就是无论读和写,都需要加锁。

两阶段锁的由来,在第一阶段即事务执行之前要获取锁,第二阶段(即事务结束时)则释放锁。

两阶段锁的性能:

在 2PL 模式下数据库的访问延迟具有非常大的不确定性。

谓词锁:

他的作用类似于之前描述的共享/独占锁,而区别在于,它并不属于某个特定的对象,如表的某一行,而是作用于满足某些搜索条件的所有查询对象。有如下例子:

img

如果事务 A 想要读取某些满足匹配条件的对象,它必须以共享模式获得查询条件的谓词锁。如果另一个事务 B 正在持有任何一个匹配对象的互斥锁,那么 A 必须等到 B 释放锁之后才能继续执行查询。

如果事务 A 想要插入,更新或删除任何对象,则必须首先检查所有旧值和新值是否与现有的任何谓词锁匹配(即冲突)。如果事务 B 持有这样的谓词锁,那么 A 必须等到 B 完成提交(或中止)后才能继续。

img

本章要点

img
img

参考文献

关于事务概念的详细介绍

posted on   LambdaQ  阅读(37)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示