ACID 原则是在 1970年 被 Jim Gray 定义,用以表示事务操作:一个事务是指对数据库状态进行改变的一系列操作变成一个单个序列逻辑元操作,数据库一般在启动时会提供事务机制,包括事务启动 停止 取消或回滚。 但是上述事务机制并不真的实现“事务”,一个真正事务应该遵循 ACID 属性,ACID 事务才真正解决事务,包括并发用户访问同一个数据表记录的头疼问题。ACID事务解决了很多问题,但是仍然需要和性能做平衡协调,事务越强,性能可能越低,安全可靠性和高性能是一对矛盾。 本篇内容主要包括:ACID 理论概述、2PC 协议、3PC 协议
ACID 原则是在 1970年 被 Jim Gray 定义,用以表示事务操作:一个事务是指对数据库状态进行改变的一系列操作变成一个单个序列逻辑元操作,数据库一般在启动时会提供事务机制,包括事务启动 停止 取消或回滚。
但是上述事务机制并不真的实现“事务”,一个真正事务应该遵循 ACID 属性,ACID 事务才真正解决事务,包括并发用户访问同一个数据表记录的头疼问题。ACID事务解决了很多问题,但是仍然需要和性能做平衡协调,事务越强,性能可能越低,安全可靠性和高性能是一对矛盾。
ACID 可以理解为 ACID 最重要的含义,就是 Atomicity 和 Isolation ,即强制一致性,要么全做要么不做,所有用户看到的数据一致。强调数据的可靠性, 一致性和可用性。
ACID 为 Atomicity、Consistency、Isolation and Durability,其中 ACID 分别表示为:
保证 ACID 是传统关系型数据库中事务管理的重要任务,几种事务类型为:未提交读、可提交读、可重复读、可序列化。
ACID 一致性是有关数据库规则,如果数据表结构定义一个字段值是唯一的,那么一致性系统将解决所有操作中导致这个字段值非唯一性的情况,如果带有一个外键的一行记录被删除,那么其外键相关记录也应该被删除,这就是 ACID 一致性意思。
CAP 理论的一致性是保证同样一个数据在所有不同服务器上的拷贝都是相同的,这是一种逻辑保证,而不是物理,因为光速限制,在不同服务器上这种复制是需要时间的,集群通过阻止客户端查看不同节点上还未同步的数据维持逻辑视图。
当跨分布式系统提供 ACID 时,这两个概念会混淆在一起,Google’s Spanner system 能够提供分布式系统的ACID,其包含 ACID+CAP 设计:
分布式系统下类比 ACID 的强一致性协议有 2PC、3PC、Paxos、Raft、Quorum NWR …
在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的结果。所以需要引入一个作为协调者,统一掌控所有节点(称作参与者)的操作结果,并决定最终结果。因此,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。
所谓的两个阶段分别是:
事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事务,并写本地的Undo/Redo
日志,此时事务没有提交。 (Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)
如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息; 参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的锁资源。
三段提交(3PC)是对两段提交(2PC)的一种升级优化,主要是为了解决两阶段提交协议的阻塞问题,2PC 存在的问题是当协作者崩溃时,参与者不能做出最后的选择。因此参与者可能在协作者恢复之前保持阻塞。三阶段提交(Three-phase commit),是二阶段提交(2PC)的改进版本。
与两阶段提交不同的是,三阶段提交有两个改动点。
但 3PC 还是没能从根本上解决数据一致性的问题。3PC 的三个阶段分别是 CanCommit、PreCommit、DoCommit。
协调者在得到所有参与者的响应之后,参与者在 CanCommit 反馈的是 Yes,执行事务预提交:
协调者在得到所有参与者的响应之后,参与者在 CanCommit 反馈的是 No**,**中断事务:
DoCommit阶段完成真正的事务提交或者完成事务回滚。
在第二阶段 PreCommit 阶段收到ACK确认消息,则完成事务提交:
在第二阶段PreCommit阶段超时中断没有收到 ACK 确认消息,则完成事务中断:
注意:在 DoCommit 阶段可能出现协调者宕机、协调者与参与者出现网络故障;导致参与者接收不到协调者的 DoCommit 请求或 Abort 请求, 参与者会在请求超时后,继续进行事务提交。
优点:相对于 2PC,3PC 主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit(因为理论上来说,如果第一阶段所有的结点返回成功,那么有理由相信成功提交的概率很大)。而不会一直持有事务资源并处于阻塞状态。
缺点:但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的中断响应没有及时被参与者接收到,那么参与者在等待超时之后执行了 commit 操作。这样就和其他接到 abort 命令并执行回滚的参与者之间存在数据不一致的情况。
总结:
简单来说 2PC 是一个数据强一致性协议,而 3PC 通过弱化数据的一致性来解决阻塞的问题。