OceanBase分布式事务以及两阶段提交实现详细设计

目前OceanBase中还存在updaeserver单点,下一步的开发任务是使得OB支持多点写入,支持多个UPS(及updateserver)。

其中难点是如何设计两阶段提交的失败恢复以及多机的快照读写,和同事讨论后,形成一个可以work的简单设计版本,记录在此。

为分布式事务的两阶段提交细化具体流程,拟采用primary record方式实现失败恢复,即在进入commit阶段之前,先写入primary record 记录当前事务的状态(commit/rollback)。Primary record起到一个全局日志的作用,可供所有参与者读取。需要注意的是,为了保证一致性,读写primary record 都需要加锁,需要使用select update语句。

采用primary record 方式的优势是,协调者在整个事务处理过程中可以是无状态的,不需要记录操作日志,宕机重启后不需要做失败处理;而参与者宕机重启或超时失败后,可以无需与协调者以及其他参与者通信,实现独立恢复,实现简单。其缺点是每次分布式事务中都会记录一次primary record,会增加写入数据量以及事务延迟。

将两阶段提交的流程分为以下子流程描述:

?  协调者处理流程

?  参与者处理流程

?  未决事务处理流程

为支持长事务、长事务中长语句以及两阶段提交,文档还简单描述了对UPS日志的修改目标。

最后,文档简单记录了组内讨论实现多UPS快照读写的一些讨论结果。

1.  两阶段提交详细流程

协调者处理流程

协调者处理流程指的是开始一个分布式事务直到事务结束或者失败。处理期间,协调者需要维护分布式事务的相关状态和信息,如参与者列表,事务执行计划,事务提交的时间戳,事务的primary
record 主键等等,这些信息不需要持久化存储,协调者宕机后,也不需要执行失败恢复。

具体流程如下图所示:

在上图中,当准备写入rollbackprimary record时候,如果已经存在相同的记录,即有可能参与者写入了rollback primary record,是正常情况,具体看后面参与者的处理流程;但如果准备写下commit primary record时候发现已经存在rollback primary record,或者准备写下rollback时候发现存在commitprimary record,这是有问题的,需要报警,人工干预。

参与者处理流程

参与者处理流程指的是收到协调者发来的start session 请求直到收到end session请求或者失败。

协调者发送startsession时候需要携带primary record 的rowkey,参与者需要将其记录到prepared日志和commit日中,用于失败恢复时候查验primary record和日志回放时候串接prepare日志和commit日志。

由于协调者在开始期间无法得知哪些参与者需要写入数据,哪些参与者只需要读取数据,因此参与者最初的session都是READ ONLY,当收到写入请求后,原先的ROSession升级为RWSession。同时,协调者需要记录相关信息,用于发送prepare消息。

对于开启ROSession的参与者,没有两阶段提交的问题,处理流程和UPS现有逻辑保持一致;对于开启了RWSession的参与者,两阶段提交流程如下:

在上述流程中,参与者出现消息超时或者写入失败后,是有权限写rollback primary  record的。这样的好处是,如果协调者在写primary record前宕机,而参与者在写入prepare日志也宕机,在参与者重启处理未决事务时候可以查primary record判定事务状态,无需等到超时即可终止未决事务,及时完成回放。

参与者只能写rollbackprimary record,不能写commit primary record。当写rollback primary record时候,可以允许已经存在rollbackprimary record的情况出现,而不应该存在commit primary record。

另外,还有一种情况没有在图中画出来,读写事务开始后,必须沿着一下顺序进行:

处理读写请求->处理prepared请求->处理commit/rollback请求。对于错序请求(即未prepare前收到commit请求),需要异常处理。

未决事务的处理流程

未决事务来源于以下两种情况:

l  参与者在处理事务请求的过程中出现等待超时;

l  宕机重启后回放日志,回放完毕所有日志后,还有未提交事务。

对于这两种情况,都采用以下的处理流程:

宕机重启后,回放日志时如果出现未决事务(即只有prepare 日志,没有commit日志),并且未读到primary record,则需要等到此事务超时后,再去尝试写rollback primary record ,其原因是为了防止这样情况的出现:

在一个分布式事务中,一个参与者写下prepared并回应协调者后宕机,但迅速重启,重启后这个分布式事务还在prepare阶段,在这种情况下,这个分布式事务还是可以正确提交的。需要注意的时候,超时时间需要将记录在prepare日志中

每个参与者尝试结束未决事务时,先要读取或写primary record成功primary,如果出错,是会阻塞未决事务的提交或者回滚的,此时需要报警,并保持重试。

在两阶段提交协议中,一旦所有参与者都prepare成功,则要求这个事务一定能提交,但在这个文档所描述的方案中是存在反例的:协调者如果在写commit primary record前宕机,所有参与者超时后走恢复流程,是会将这个事务回滚的。

2.  UPS日志改造目标

目前受限于2MB的网络包最大长度,UPS不支持日志大于2MB的长事务。在两阶段提交的流程中,对于一次分布式事务,至少需要写入两条日志,在这个驱动下,准备修改UPS写入和回放日志的方式,使得其支持长事务以及两阶段提交对日志的要求。

基本想法如下:

?  UPS在执行事务的过程中,如果日志内容超过一定阈值,则异步提交一次日志任务,同一个事务的多条日志之间,使用唯一的事务ID进行关联

?  在事务中,UPS支持一条语句写多条日志,使用唯一的语句ID进行关联

?  ups支持事务内部,单条语句级别的提交和回滚需要记录提交或回滚的日志

对于两阶段提交的日志:

?  协调者收到prepare请求时,无需写专用的prepare日志,但是要阻塞等待确认prepare之前执行的语句日志都已经刷盘。

?  事务commit/rollback要记录日志,但异步执行,不阻塞协调者,即收到commit请求后,可直接回复协调者,无需等待commit日志落盘。这是因为即便此时commit日志写入失败,也可通过读取primary record重新完成提交或者回滚操作。

3.  多UPS快照读和写

多UPS进行分布式事务时,在没有全局时钟的情况下,每个UPS使用本地时钟独立维护自己的多版本数据。当一次读写事务涉及多个UPS时候,需要协调者在prepare阶段获取到每个参与者的本地prepare时间戳,然后使用其中的最大值作为此次分布式事务的时间戳,在commit阶段发给所有参与者,每个参与者都使用此时间戳作为此次事务写入数据的版本时间戳。

执行快照读时候,协调者需要使用所涉及的多UPS中时间戳最小作为统一的时间戳,以免读到未提交数据,出现幻读。讨论中,针对快照读,提出一下优化方式:

?  每个UPS中,本地最大事务版本号(CV)是在有读写事务提交时后才会更新的,为了避免有的UPS在长时间没有读写事务提交的情况下,CV得不到更新,导致其值远远落后其他UPS,采取定时写入NOP日志的方式,随着时间推移,不断更新CV。

?  快照读时,需要使用所有参与者中最小版本号(即时间戳)作为本次快照读的时间戳,而由于事务的交互性,无法预知参与者有哪些。为了避免全局广播获取所有机器版本号,可以采用下面做法:

快照读的发起者,采用本地版本号V作为此次读的版本号,发送读请求给其他参与者S,如果S本地的版本号小于V,则阻塞等待,直到S的版本号大于V后再进行读取。另外,如果S上存在状态为prepare的分布式事务,且这些事务prepare的版本号小于S, 则需要等待这些分布式事务进入commit状态,才能继续读取。这是因为这些状态为prepare的分布式事务转变为commit状态后,其版本号既可能大于V也可能小于V。

OceanBase分布式事务以及两阶段提交实现详细设计

时间: 2025-01-13 00:52:12

OceanBase分布式事务以及两阶段提交实现详细设计的相关文章

MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布式事务,将事务的提交分成了两个阶段:也就是2PC (tow phase commit),XA协议就是通过将事务的提交分为两个阶段来实现分布式事务. 两阶段: 1)prepare 阶段 事务管理器向所有涉及到的数据库服务器发出prepare"准备提交"请求,数据库收到请求后执行数据修改和日志

关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究[转]

1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口.XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁.XA之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲(参考Fischer等的论文),两台机器理论上无法达到一致的状态,需要引入一

对分布式事务及两阶段提交、三阶段提交的理解

转载至:http://www.cnblogs.com/binyue/p/3678390.html,最近学习需要,先转载方便用用来强化加深印象 一.分布式数据一致性 在分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上. (1)什么是数据一致性 在数据有多份副本的情况下,如果网络.服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败.这就造成各个副本之间的数据不一致,数据内容冲突. 造成事实上的数据不一致. (2)CAP定

分布式事务(两阶段提交)模型详解

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt369 这一几天一直在回顾事务相关的知识,也准备把以前了解皮毛的知识进行一些深入总结,虽然这一些知识并没有用到,但是了解其实现原理还是很有必要的,因为知道了原理,你也能把它实现出来. 在上一节事务的编程模型里面,主要说明了三种编程模型,一般情况下,我们都接触的是单一资源的事务,也就是单独对一个数据库进行操作.如果需要跨多个资源保证事务一致性 举个例子:在ATM机取钱的时候,需

分布式事务之两阶段提交

一.二阶段提交协议 一般分为协调器C和若干事务执行者Si两种角色:    当执行某一事务T的所有站点Si都通知C事务执行完成,C即启动二阶段提交协议.    (1) 首先C向所有Si发<prepare>消息(C先将<prepare>消息写到本机日志) ,Si收到<prepare>消息后,根据本机T的执行情况,如果成功返回<ready T>,不成功返回<abort T>.(返回前都应把要返回的消息写到日志里)     (2) C收集完所有Si的返回

分布式事务:两段式提交(最终一致性)

[MySQL如何实现分布式事务?] http://www.linuxidc.com/Linux/2013-10/91925.htm Innodb存储引擎支持XA事务,通过XA事务可以支持分布式事务的实现.分布式事务指的是允许多个独立的事务资源(transac tional resources)参与一个全局的事务中.事务资源通常是关系型数据库系统,也可以是其它类型的资源. 全局事务要求在其中所有参与的事务要么全部提交,要么全部回滚,这对于事务原有的ACID要求又有了提高.另外,在使用分布式事务时候

h2database源码浅析:事务、两阶段提交

http://blog.csdn.net/bluejoe2000/article/details/42437633 h2database源码浅析:事务.两阶段提交 2015-01-05 22:54 734人阅读 评论(0) 收藏 举报  分类: 源码故事(18)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] Transaction Isolation Transaction isolation is provided for all data manipulation

分布式事务的两级提交

在项目ITOO2.0之前,分布式事务一直是讨论的主流问题之一.对于什么是事务,以及事务的ACDI特性,我就不在这里费口舌了~ 先简单介绍一下分布式事务:分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上. 其中最经典的例子就是跨行转账问题,各大银行之间的系统一定都是分布式系统,银行之间的业务操作也一定要执行分布式事务.没有分布式事务,谁还敢去银行存钱? 为什么要用它:分布式事务旨在协助在分布式环境中跨异类的事务识别资源的事务.在分布式系统

关于分布式事务、两阶段提交协议、三阶提交协议

随着大型网站的各种高并发访问.海量数据处理等场景越来越多,如何实现网站的高可用.易伸缩.可扩展.安全等目标就显得越来越重要. 为了解决这样一系列问题,大型网站的架构也在不断发展.提高大型网站的高可用架构,不得不提的就是分布式.在<分布式系统的一致性探讨>一文中主要介绍了分布式系统中存在的一致性问题.本文将简单介绍如何有效的解决分布式的一致性问题,其中包括什么是分布式事务,二阶段提交和三阶段提交. 分布式一致性回顾 在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(repli