Transaction Anomalies

Non-Repeatable Read A non-repeatable read occurs, when during the course of a transaction, a row is retrieved twice and the values within the row differ between reads. Phantom Read A phantom read occurs when, in the course of a transaction, two identical queries are executed, and the collection of rows returned by the second query is different from the first. Read Skew Read skew is that with two different queries, a transaction reads inconsistent data because between the 1st and 2nd queries, other transactions insert, update or delete data and commit. Finally, an inconsistent result is produced by the inconsistent data. ...

March 31, 2024 · 2 min · KKKZOZ

Talk about Postgres Visibility Check Rules

Background 最近在看分布式事务相关的论文,很多论文设计的系统中都实现的是快照隔离这一层次的机制,其中 Epoxy 最为典型,直接把 Postgres 的快照隔离机制在中间层重新实现了一遍。 之前看关于 Postgres 快照隔离机制的文章,找到了这个:PostgreSQL并发控制,讲得非常好,逻辑非常清晰,理论和实际例子相结合。 这篇文章中关于 Visibility Check Rules 的部分讲的非常详细,但是没啥规律,可归纳性不强,我时不时就会回来看看这一段,但每次看的时候好像都要从头再重新理解一遍,于是最近我整理了一下这十条规则,力求达到清晰有序。 Rules 我先把原文中提到的十条规则列出来,方便下文做参考。 可以把这些规则简单地按照 t_xmin 的状态分为三部分: Status of t_xmin is ABORTED: Rule 1: If Status (t_xmin) = ABORTED ⇒ Invisible Status of t_xmin is IN_PROGRESS: Rule 2: If Status (t_xmin) = IN_PROGRESS ∧ t_xmin = current_txid ∧ t_xmax = INVAILD ⇒ Visible Rule 3: If Status (t_xmin) = IN_PROGRESS ∧ t_xmin = current_txid ∧ t_xmax ≠ INVAILD ⇒ Invisible Rule 4: If Status (t_xmin) = IN_PROGRESS ∧ t_xmin ≠ current_txid ⇒ Invisible Status of t_xmin is COMMITTED: ...

December 4, 2023 · 2 min · KKKZOZ

Talk about Consistency and Consensus

ACID 中的一致性 我们现在关注的是其中的 C,即一致性 Consistency。它是什么意思呢?通俗地说,它指的是任何一个数据库事务的执行,都应该让整个数据库保持在「一致」的状态: ACID 中的「一致性」,是对于整个数据库的「一致」状态的维持。抽象来看,对数据库每进行一次事务操作,它的状态就发生一次变化。这相当于把数据库看成了状态机,只要数据库的起始状态是「一致」的,并且每次事务操作都能保持「一致性」,那么数据库就能始终保持在「一致」的状态上 (Consistency Preservation)。 所谓状态是不是「一致」,其实是由业务层规定的。比如转账的例子,“转账前后账户总额保持不变”,这个规定只对于「转账」这个特定的业务场景有效。如果换一个业务场景,「一致」的概念就不是这样规定了。所以说,ACID 中的「一致性」,其实是体现了业务逻辑上的合理性,并不是由数据库本身的技术特性所决定的。 为了让事务总是能保持 ACID 的一致性,我们需要在实现上考虑哪些因素呢? 出错情况 (failure/error) 事务本身的实现逻辑可能存在错误,这需要应用层进行恰当的编码来保证。 需要 ACID 中的 A(原子性)来保障。简言之,原子性保障了事务的执行要么全部成功,要么全部失败,而不允许出现“只执行了一半”这种“部分成功”的情况。 并发行为 需要 ACID 中的 I(隔离性)来保障了。什么是隔离性呢?它对于并发执行的多个事务进行合理的排序,保障了不同事务的执行互不干扰。换言之,隔离性这种特性,能够让并发执行的多个事务就好像是按照「先后顺序」执行的一样。 Summary ACID 中的一致性,是个很偏应用层的概念。这跟 ACID 中的原子性、隔离性和持久性有很大的不同。原子性、隔离性和持久性,都是数据库本身所提供的技术特性;而一致性,则是由特定的业务场景规定的。 要真正做到 ACID 中的一致性,它是要依赖数据库的原子性和隔离性的(应对错误和并发)。 最后,ACID 中的一致性,甚至跟分布式都没什么直接关系。它跟分布式的唯一关联在于,在分布式环境下,它所依赖的数据库原子性和隔离性更难实现。 总之,ACID中的一致性,是一个非常特殊的概念。除了数据库事务处理,它很难扩展到其它场景,也跟分布式理论中的其它「一致性」概念没有什么关系。 分布式事务与共识算法的关系 共识问题 (consensus problem)。这是分布式系统中的一个十分基础而核心的问题,它表示如何在分布式系统中的多个节点之间就某事达成共识。 网上通常提到的「分布式一致性协议」,或者「分布式一致性算法」,一般来说就是解决这里的共识问题的算法。 这些算法或协议,经常包含 Paxos 之类,但也可能包括两阶段提交协议 (2 PC)或三阶段提交协议 (3 PC)。 ACID 中的原子性,要求事务的执行要么全部成功,要么全部失败,而不允许出现“部分成功”的情况。在分布式事务中,这要求参与事务的所有节点,要么全部执行 Commit 操作,要么全部执行 Abort 操作。换句话说,参与事务的所有节点,需要在“执行 Commit 还是 Abort”这一点上达成一致(其实就是共识)。这个问题在学术界被称为原子提交问题(Atomic Commitment Problem),而能够解决原子提交问题的算法,则被称为原子提交协议(Atomic Commitment Protocal,简称ACP)。2PC 和3PC,属于原子提交协议两种不同的具体实现。 我们可以发现原子提交问题和共识问题的关联: 共识问题,解决的是如何在分布式系统中的多个节点之间就某个提议达成共识。 原子提交问题,解决的是参与分布式事务的所有节点在“执行 Commit 还是 Abort”这一点上达成共识。 所以,原子提交问题是共识问题的一个特例。(?) 一些细节的不同,可能导致非常大的差异。当我们描述共识问题的时候,我们说的是在多个节点之间达成共识;而当我们描述原子提交问题的时候,我们说的是在所有节点之间达成共识。这个细微的差别,让这两类问题,几乎变成了完全不同的问题(谁也替代不了谁): ...

November 7, 2023 · 2 min · KKKZOZ

About CAP

What is CAP Consistency: 数据一致性 Availability: 可用性 Partition Tolerance: 分区容忍性 Consistency 指的是系统能够返回一致性的数据。 Gilbert 和 Lynch 的论文中是这样描述一致性的: Any read operation that begins after a write operation completes must return that value, or the result of a later write operation. 在某个写操作完成之后的任何读操作都必须返回该写操作写入的值,或者再之后的写操作写入的值。 在一个一致性的系统中,如果一个客户端写入了某个值到任意一个服务端上,并且得到了服务端的确认,那么客户端再去读的时候,不管是读的哪个服务,都期望拿到写入后的值或者是更新的值。 Available 指的是系统能保持在可用的状态。 Gilbert 和 Lynch 的论文对可用性的描述如下: Every request received by a non-failing node in the system must result in a response. 任何一个在线的节点收到的请求必须都做出相应。 在保证可用性的系统中,如果客户端向某个没有宕机的服务端发送了请求,服务端必须响应客户端的请求,不能选择忽略掉客户端的请求。 它要求系统内的节点们接收到了无论是写请求还是读请求,都要能处理并给回响应结果。只是它有两点必须满足的条件: 返回结果必须在合理的时间以内,这个合理的时间是根据业务来定的。 需要系统内能正常接收请求的所有节点都返回结果。 如果节点不能正常接收请求了,比如宕机了,系统崩溃了,而其他节点依然能正常接收请求,那么,我们说系统依然是可用的,也就是说,部分宕机没事儿,不影响可用性指标。 如果节点能正常接收请求,但是发现节点内部数据有问题,那么也必须返回结果,哪怕返回的结果是有问题的。 Partition Tolerance 指的是系统能够容忍分区问题。 ...

November 6, 2023 · 1 min · KKKZOZ

Talk about Redlock

最近看了下之前业界关于 Redlock 的争论,发现还是挺有意思的,正好把自己最近学的知识串了起来,这里就简单总结一下。 Martin 的观点 使用分布式锁的目的 Martin 表示,你必须先清楚你在使用分布式锁的目的是什么? 他认为有两个目的。 第一,效率。 使用分布式锁的互斥能力,是避免不必要地做同样的两次工作(例如一些昂贵的计算任务)。如果锁失效,并不会带来「恶性」的后果,例如发了 2 次邮件等,无伤大雅。 第二,正确性。 使用锁用来防止并发进程互相干扰。如果锁失效,会造成多个进程同时操作同一条数据,产生的后果是数据严重错误、永久性不一致、数据丢失等恶性问题,就像给患者服用了重复剂量的药物,后果很严重。 他认为,如果你是为了前者——效率,那么使用单机版 Redis 就可以了,即使偶尔发生锁失效(宕机、主从切换),都不会产生严重的后果。而使用 Redlock 太重了,没必要。 而如果是为了正确性,Martin 认为 Redlock 根本达不到安全性的要求,也依旧存在锁失效的问题。 NPC 问题 这些异常场景主要包括三大块,这也是分布式系统会遇到的三座大山:NPC。 N:Network Delay,网络延迟 P:Process Pause,进程暂停(GC) C:Clock Drift,时钟漂移 Martin 用一个进程暂停(GC)的例子,指出了 Redlock 安全性问题: 客户端 1 请求锁定节点 A、B、C、D、E 客户端 1 的拿到锁后,进入 GC(时间比较久) 所有 Redis 节点上的锁都过期了 客户端 2 获取到了 A、B、C、D、E 上的锁 客户端 1 GC 结束,认为成功获取锁 客户端 2 也认为获取到了锁,发生「冲突」 ...

November 2, 2023 · 5 min · KKKZOZ