GaussDB(DWS)中两阶段事务的故障与恢复
GaussDB(DWS) 是 share nothing 架构,使用分布式事务解决数据的一致性问题。当前 GaussDB(DWS) 使用的是两阶段提交(2PC)协议。2PC 协议有两类节点:协调者和参与者。一个事务会涉及一个协调者和多个参与者。当协调者或者参与者出现故障或者节点间出现网络问题时,2PC 事务就面临着失败或者残留的问题。在 GaussDB(DWS) 中,发起事务的 CN 节点就是协调者,其他参与此事务的 CN 或者 DN 节点就是参与者。
1.1. 2PC 事务失败/残留的原因
1.1.1. 2PC 事务的正常提交流程
首先看一下 2PC 事务的正常提交流程,一般情况下,对于一个事务,至少要经过一个 CN(执行 CN )、一个 DN 和 GTM。
-
如果涉及本地,先在本地进行 PREPARE;
-
在远端其他节点进行 PREPARE。如果任一节点失败,则报告错误并进行 ABORT 操作;
-
到这步时,所有涉及的节点都已经 PREPARE 了,可以进行 COMMIT 了:首先通知 GTM 当前事务已经 PREPARED,并提供一个节点列表给GTM;
-
先在本地 COMMIT PREPARED,然后在其他远端节点 COMMIT;
-
返回并做提交动作的收尾工作
1.1.2. 故障
对于上述流程,在任意执行路径上出错,都可能导致整个分布式事务的状态无法达到终点,最终当前事务整体提交失败。如果事务不能完整结束,那么它所占有的资源就会一直无法释放
1.1.3. 故障处理的总体原则
当故障发生后,通过全局回滚或者是由 gs_clean 工具进行残留事务清理,以保证事务完整结束。
1.1.4. 故障场景
-
在事务运行过程中,或者 prepare 阶段,对于 CN、DN、GTM 实例本身或者网络出现故障,事务都要进行回滚,根据实际情况,执行 CN 没问题的话,CN 提交回滚操作;否则需要由 gs_clean 工具进行清理。
-
在 commit prepared 阶段,CN 向其他 CN 和 DN 发送 commit prepared 命令,并收取返回信息,这时如果实例发生了故障,那么事务会残留,就需要等待 gs_clean 工具清理了。
1.2. gs_clean
上面的故障情况中,对于执行 CN 不能自动进行回滚的的场景,就需要 gs_clean 工具来协助进行清理了。
1.2.1. gs_clean 是干什么的
gs_clean 工具是用于清理 GaussDB(DWS) 集群中残留的两阶段事务的组件。
1.2.2. 为什么需要 gs_clean
由于 GaussDB(DWS) 集群使用多个工作节点一起来支持分布式事务,单个组件的故障会导致分布式事务(2PC)的全局状态产生异常。在某些情况下,异常的事务由于无法判断后续状态进而无法继续下去,这时就需要一个第三方的组件来判断事务状态并将事务圆满的结束。
1.2.3. gs_clean 在哪里
gs_clean 二进制文件跟随内核包一起部署在 $GAUSSHOME/bin 目录下。
1.2.4. 谁来调用 gs_clean
每个 CN 中有一个叫做 TwoPhaseCleanerMain 的辅助线程线程,所有的 gs_clean 调用都是由这个线程自动完成的。
一般情况下,不需要人工调用 gs_clean。
1.2.5. 什么时候调用 gs_clean
-
在 CN 正常运行过程中,每隔 5mins 会调一次 gs_clean 命令,对集群中所有的数据库中的两阶段残留事务进行扫描和清理;
-
如果是进程刚启动,或者上次 gs_clean 调用失败,则 60s 后会再次调用;
-
sync 等待时,如果等待超时,会给这个线程发消息线程调用 gs_clean;
-
如果已经有 gs_clean 进程启动,则不会再调用;
1.2.6. gs_clean的结果与日志
gs_clean 的所有信息都保存在自己的日志文件中,日志文件路径为:$GAUSSLOG/bin/gs_clean/
1.2.7. gs_clean 的主要工作流程
-
连接 CN,做一些前期的信息收集和准备工作:
-
获取要清理的 database 列表
-
连接 CN,设置为维护模式
-
获取自己的 node name 和 所有的 node list
-
扫描两阶段残留信息:
-
去各个节点上执行视图 pg_prepared_xacts
-
获取 prepared 的事务信息,把结果和事务状态记录在链表里
-
遍历链表,查看是否有要进行恢复的 2PC 事务
-
针对每个处于 prepared 阶段的事务,去其他所有节点上查找对应事务是否已经提交,把结果也更新到链表中
-
收集了所有需要的信息后,针对每个 database 中的每一个事务,根据规则判断应该进行提交、回滚还是继续等待,如果需要提交或回滚,那么直接向所有相关节点发起 commit/rollback prepared 动作
1.2.8. 残留事务的处理规则
-
如果有一个节点处于 committed 状态,则标记为提交,并最终提交该事务;
-
如果有一个节点处于 aborted 状态,则标记为回滚,并最终回滚该事务;
-
如果所有节点都处于 prepared 状态,则可选择回滚或者提交(参数),默认是回滚;
-
如果有节点连不上,则不提交也不回滚。
1.2.9. 实际运行过程中的一些事情
-
GUC 参数 gs_clean_timeout 可以用来控制 CN 调用 gs_clean 的周期间隔。默认为 5min。
-
当 CN 上进行事务 sync 等待时,如果超过 transaction_sync_naptime 参数(默认5s),则会触发 gs_clean。
-
CN 自动触发的 gs_clean 命令为: gs_clean -a -p PORT -v -r
1. -a:清理所有数据库
2. -p:CN 端口
3. -v:打印详细信息,包括数据库信息,残留事务信息等
4. -r:将处于 PREPARED 状态的事务进行回滚
5. 其他 gs_clean 参数可以参考 gs_clean --help
- 点赞
- 收藏
- 关注作者
评论(0)