我们都是架构师!
关注架构师(JiaGouX),添加“星标”
获取每天技术干货,一起成为牛逼架构师
技术群请加若飞:1321113940 进架构师群
投稿、合作、版权等邮箱:[email protected]
Atomicity: 修改一组元素, 成功, 则所有元素的变更均生效; 失败, 数据库自动撤销部分元素的变更, rollback到之前状态. 用户不必采取额外的操作.
Consistency: 事务执行成功与否, 数据库始终处于一致状态, 事务是将数据库从当前的一致性状态转移到下一个一致性状态的基本操作单位. 用户不必担忧约束遭到破坏.
Isolation: 事务并发执行以提高性能, 同时正确性能够得到保障, 用户不必担忧冲突的事务导致concurrent anomaly.
Durability: 提交的事务对数据库状态的修改具有持久性, 未完成的事务不会修改数据的状态, 即便出现升级重启, 掉电, 故障或者服务崩溃. 数据库能够恢复到正确的状态. 用户不必担忧异常事件造成数据丢失或者状态不一致.
<START T>
日志, 修改数据库元素之前, 先写redo日志
<T elem new_val>
. 如果提交事务, 则写
<COMMIT T>
日志, 当日志落盘后, apply日志, 更新buffer pool中相应的page, dirty page不必及时写会磁盘, 可以延迟落盘. 如果事务失败, 则写
<ABORT T>
日志, 不apply日志. 很显然, 未完成事务或者夭折的事务, 不会修改数据库的状态, 恢复时直接跳过. 已提交的事务, 因为dirty page延迟写回磁盘, 最近一次checkpointing的时间也可能早于dirty page落盘时间, 因此需要redo事务T日志.
Two-Phase Commit Protocol(2PC)[2]
<prepare T>
日志记录, 向事务T所涉及的participant发送消息
prepare T
;收到消息后, participant判断事务T是否可以提交(申请锁, 冲突检测). 如果可以提交, 则追加日志
<ready T>
, 并向coordinator发送消息
ready T
; 如何无法提交, 则追加日志
<no T>
, 向coordinator发现
abort T
.
commit阶段:
ready T
: coordinator追加
<commit T>
日志, apply日志; 然后, coordinator向全体participant发送
commit T
消息, 收到消息后, participant追加
<commit T>
日志, apply日志修改状态.
abort T
或者等待超时: coordinator追加
<abort T>
日志, 向全体participant发送
abort T
消息; 收到信息后, participant追加
<abort T>
日志.
<commit T>
或
<abort T>
后, 向coordinator发送
acknowledge T
消息, coordinator收到所有participant发来的确认后, 写日志
<complete T>
, T结束.
当coordinator写下<commit T>
日志后, 事务已提交(图中绿色区域);
当至少有一个participant写下<no T>
日志后, 事务失败(图中橙色区域).
网络错误: coordinator和participant之间出现networking partitioning, 互不可达. 普遍解决方法是: 重试+幂等+超时.
coordinator/participant宕机崩溃: 服务要做到high availability, 普遍采用一主多备, 在服务崩溃时, 及时地failover. 比如多个coordinator构成RSM, 如Spanner中的Paxos group[5], 其他系统也可能采用Raft group.
只有<prepare T>
记录: 说明事务处于outstanding状态, coordinator终止事务即可, 即从图中C <abort T>
做起.
有<commit T>
但无<complete T>
: 说明事务已经提交, 但可能尚未通知participant, 则从C <commit T>
做起, roll forward, 通知全体participant做commit和apply.
有<abort T>
但无<complete T>
: 说明事务已经失败, 从C <abort T>
做起, rollback, 通知全体participant做终止事务.
有<complete T>
记录: 事务已经完成. 无需处理.
participant扫描日志:
如果有<no T>
或<abort T>
记录: 说明事务已经失败, 则可以单方面rollback.
如果有<commit T>
: 说明事务已经成功提交, 则做本地redo操作即可.
如果只有<ready T>
: coordinator无法判断事务的执行状态, 当前事务处于in-doubt状态. 见下文详细描述.
事务的状态无非outstanding, committed, aborted, complete. 之所以处于in-doubt状态, 是因为故障导致信息缺失, 无法判断事务究竟处于三种状态outstanding, committed, aborted中的哪一种.
在coordinator可用情况下, 首先询问coordinator关于事务T的状态. 如果T处于outstanding或aborted状态, 则终止事务T, rollback.
在coordinator不可用情况下, 询问当前可用的其他participant关于事务T的状态. 如果事务T明确地处于committed或者aborted状态, 则选择roll forward或者rollback即可.
最糟糕的一种情况: coordinator不可用, 并且当前可用的participant日志均只有<ready T>
记录. 此时无法采取行动, 因为:
事务T可能处于committed状态: coordinator不可用, 全体participant都投票<ready T>
.
事务T可能处于aborted状态: coordinator和全体投反对票<no T>
的participant不可用.
事务T可能处于outstanding状态: coordinator不可用, 在崩溃之前, 并未写下<commit T>
或<abort T>
.
这种情况下: 只有当coordinator恢复之后, 才能继续推进. 如果系统中有其他的coordinator, 并且该coordinator上执行的事务和in-doubt事务有冲突; 则要么自杀, 要么等待in-doubt事务恢复后, 才能推进.
in-doubt事务, 充分地说明了coordinator的高可用至关重要.
Three-Phase Commit Protocol(3PC)[2]
<commit T>
写入本地日志中, 还要将提交信息复制到至少k个coordinator上. 如果主coordinator崩溃, 备用coordinator选出新任leader, 由它负责处理后续操作. 比如总共有5个coordinator, k=2. 可以容忍两个coordinator故障.
事务处理层和存储层分离
参考文献
·END·
相关阅读:
来源:https://zhuanlan.zhihu.com/p/34522695
版权申明:内容来源网络,仅供分享学习,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
我们都是架构师!
关注架构师(JiaGouX),添加“星标”
获取每天技术干货,一起成为牛逼架构师
技术群请加若飞:1321113940 进架构师群
投稿、合作、版权等邮箱:[email protected]