读书笔记:数据密集型应用系统设计 事务
数据密集型应用系统设计
事务
弱隔离级别的介绍
读-提交
脏写
写入尚未提交的事务的一部分
读-提交 这个隔离级别,并不能克服下列图所示的,计数器增量竞争的情况
最后的结果就是“更新丢失”。
如何防止脏写
脏读
如何防止脏读
快照级别隔离
不可重复读问题
如下图所示的 case:
在红线处,第一个查询 account1 已经结束,向 account1 转账的的事务还没有提交,所以根据读-提交的性质,此时的查询结果为 500。第二个查询 account2 的发起时机是在 account2 转出 100 元,且事务已经提交,根据读-提交的性质,此时可以查询到 account2 的账户是 400 元。在这两次的查询中,两个账户的总额为 900 元,少了 100 元。查询的结果是不符合数据库预期状态的,在过段时间重新执行这两个查询,能够得到符合预期的结果。这种现象称为不可重复读,或者读倾斜(nonrepeatable read or read skew)。所谓 read skew,个人理解为读的时机不对,在整个数据库的状态中,读-提交这个隔离级别,会有一段时间的数据库状态是 “不一致” 的,如果在此时进行读数据库,就会得到错误的结果。
使用快照隔离解决上述的问题,总体思路如下:
发现错别字了。
如何实现快照隔离
下面的图解释了 PostgreSQL 数据库是如何基于 MVCC 来实现快照级别的隔离的
就是给每一行记录,增加两个字段:
- created_by 字段,其内容为创建该记录的事务号
- deleted_by 字段,其内容为删除该记录的事务号
在事务的执行过程中,通过对这两个字段的进行填充事务号,等到数据库进程进行垃圾回收的时候,真正删除数据。
写倾斜与幻读
写倾斜
如图所示,Alice 和 Bob 执行事务,在事务中,需要修改各自的记录中对应的 on_call 字段的状态,查询语句执行完成后,得到 currently_on_call = 2,两个事务都会进行各自的修改,最后导致 Alice 和 Bob 的 on_call 字段都为 false。
写倾斜是一种更广义的更新丢失问题。如果两个事务读取相同的一组对象,然后更新其中的一部分,不同的事务可能更新不同的对象,则可能会发生写倾斜。
为了自动防止写倾斜,要求“可串行化”的隔离级别。
幻读
如何解决幻读问题:
可重复读
串行化
如何实现串行化:
两阶段锁:
也就是无论读和写,都需要加锁。
两阶段锁的由来,在第一阶段即事务执行之前要获取锁,第二阶段(即事务结束时)则释放锁。
两阶段锁的性能:
在 2PL 模式下数据库的访问延迟具有非常大的不确定性。
谓词锁:
他的作用类似于之前描述的共享/独占锁,而区别在于,它并不属于某个特定的对象,如表的某一行,而是作用于满足某些搜索条件的所有查询对象。有如下例子:
如果事务 A 想要读取某些满足匹配条件的对象,它必须以共享模式获得查询条件的谓词锁。如果另一个事务 B 正在持有任何一个匹配对象的互斥锁,那么 A 必须等到 B 释放锁之后才能继续执行查询。
如果事务 A 想要插入,更新或删除任何对象,则必须首先检查所有旧值和新值是否与现有的任何谓词锁匹配(即冲突)。如果事务 B 持有这样的谓词锁,那么 A 必须等到 B 完成提交(或中止)后才能继续。
本章要点
参考文献
关于事务概念的详细介绍
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了