02-探讨事务一致性
0x-wen

1.事务的ACID特性

在数据库中,“事务”是由多个操作构成的序列。广义上的事务一致性具化到了原子性、一致性、隔离性和持久性这4个方面。

  1. 原子性(Atomicity):指事务是一个不可分割的操作单元,要么全部执行成功,要么全部失败回滚。如果事务中的任何一个操作失败,整个事务将回滚到最初的状态。
  2. 一致性(Consistency):指事务将数据库从一个一致状态转变为另一个一致状态。在事务开始和结束时,数据库必须满足预定义的一致性规则,以保持数据的有效性和完整性。
  3. 隔离性(Isolation):指每个事务的执行应该与其他事务的执行相互隔离,以防止彼此干扰。隔离级别定义了事务之间的隔离程度,包括已提交读、可重复读、快照隔离和可串行化。
  4. 持久性(Durability):指一旦事务提交,其结果就应该永久保存在数据库中,即使系统发生故障也不会丢失。数据库通过将事务日志持久化到磁盘来实现持久性。

image

1.1 原子性和一致性的差异

原子性关注事务内部状态,要不全部成功,要不全部失败

一致性关注数据可见性,中间状态的数据对外不可见,只有最初状态和最终状态的数据对外可见

1.2 持久性核心思想即应对系统故障

目的都是保证在本地节点之外,至少有一份完整的日志可用于数据恢复。

存储硬件无损、可恢复故障: 主要依托于预写日志(Write Ahead Log, WAL)保证第一时间存储数据。WAL采用顺序写入的方式,可以保证数据库的低延时响应。

存储硬件损坏、不可恢复的故障: 需要用到日志复制技术,将本地日志及时同步到其他节点。

  • 单体数据库自带的同步或半同步的方式,其中半同步方式具有一定的容错能力
  • 日志存储到共享存储系统上,后者会通过冗余存储保证日志的安全性
  • 基于Paxos/Raft的共识算法同步日志数据,在分布式数据库中被广泛使用

1.3 隔离性分为多个隔离级别

较低的隔离级别就是在正确性上做妥协,将一些异常现象交给应用系统的开发人员去解决,从而获得更好的性能。

最早、最正式的对隔离级别的定义,是ANSI SQL-92(简称SQL-92),它定义的隔离级别和异常现象如下所示:

image

1.4 更严谨的隔离级别

参考论文“A Critique of ANSI SQL Isolation Levels”(简称Critique)

定义了六种隔离级别和八种异常现象

image

  • SQL-92中可重复读与可串行化两个隔离级别的主要差别是对幻读的处理,是不是解决了幻读就是可串行化
  • Critique的发表,快照隔离能解决幻读的问题,但却无法处理写倾斜(Write Skew)问题,也不符合可串行化要求

对比总结到今天,使用最广泛的隔离级别为四种:已提交读可重复读快照隔离可串行化

1.5 异常现象不可重复读幻读的差异

在语义上接近:都是在一个事务内用相同的条件查询两次,但两次的结果不一样

不可重复读:第二次的结果集相对第一次,有些记录被修改(Update)或删除(Delete)了

幻读: 第二次结果集里出现了第一次结果集没有的记录(Insert),幻读是在第一次结果集的记录“间隙”中增加了新的记录

1.6 快照隔离 && 可重复读

两者在强度上并列,已提交读弱于这两者,大多数数据库支持的隔离级别就在这三者之中

快照隔离的实现基础则是多版本并发控制(MVCC),用于更高效地实现乐观或悲观并发控制。

快照隔离存在写倾斜的问题:

  • 两个事务T1、T2同时针对10个变量赋值
  • T1将10个变量赋值A,T2将10个变量赋值B,在多事务并行下得到结果将是5个A和B

根据可串行化的定义,“多事务并行执行所得到的结果,与串行执行(一个接一个)完全相同”。

实现可串行化:先执行T1再执行T2,10个变量都会变成A;调换T1与T2的顺序,则10个变量都是B。

1.7 数据一致性和事务一致性

  • 数据一致性关注的是单对象、单操作在多副本上的一致性
  • 事务一致性则是关注多对象、多操作在单副本上的一致性

分布式数据库的一致性是数据一致性与事务一致性的融合。

分布式数据“强一致性”的含义,意味着要实现严格串行化,同时也带来性能上的损失。

降低隔离级别则是在正确性上做妥协,将异常给应用开发处理,从而获得更好的性能。

由 Hexo 驱动 & 主题 Keep
总字数 41.7k