OceanBase0的分布式事务剖析

上传人:新** 文档编号:498468089 上传时间:2023-08-12 格式:DOC 页数:8 大小:214.50KB
返回 下载 相关 举报
OceanBase0的分布式事务剖析_第1页
第1页 / 共8页
OceanBase0的分布式事务剖析_第2页
第2页 / 共8页
OceanBase0的分布式事务剖析_第3页
第3页 / 共8页
OceanBase0的分布式事务剖析_第4页
第4页 / 共8页
OceanBase0的分布式事务剖析_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《OceanBase0的分布式事务剖析》由会员分享,可在线阅读,更多相关《OceanBase0的分布式事务剖析(8页珍藏版)》请在金锄头文库上搜索。

1、OceanBase1.0的分布式事务数据库的功能强大而繁杂,其中,事务(Transaction)”是使用者不自觉就会用到的功能。作为开发数据库的工程师,我们是倾注了大量的精力和时间在事务这个功能上,并且深知数据库系统实现事务是付出了很大代价的。这代价不仅包括数据库软件开发的工作,而且还包括数据库运行过程中的代价。换句话说,在其他情况不变的时候,如果数据库放弃事务功能,能获得更好的性能。在数据库软件刚出现时,并没有事务这个功能,但这种情况下,使用数据库开发软件很多时候无法保证数据的正确性和一致性,或者把软件搞得很复杂。所以,数据库支持了事务功能,提供给使用者一个将许多数据库的操作打包在一起的功能

2、,例如Atomic(原子性),保证事务内对数据的多次修改操作,要么全部完成要么全部回滚。虽然付出了很多代价,但是用户的应用程序会因此大大简化。而且,用户操作数据的流程越来越复杂,如果没有事务特性的保证,使用者更加无法确切知道数据在数据库中是否保持正确。事务重要的4个特性ACID分别代表Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)。 Atomicity(原子性)表示事务中的多个操作要么全部完成,要么全部没有生效,不会出现中间状态; Consistency(一致性)表示事务操作不会违反数据库的一致性约束; Isolat

3、ion(隔离性)表示多个并发事务之间不互相影响; Durability(持久性)表示事务一旦成功就不会丢失。数据库系统有很多工程化方法来实现这些事务特性。其中,保证所有数据都存储在持久化设备中,就可以保证数据的Durability(持久性)。常用的持久化设备有磁盘和SSD,这种设备保证在断电的时候数据都不会丢失。事务的一致性是数据库系统对于数据的约束,常见的约束有数据库的外键(ForeignKey),数据库系统保证事务执行后这些约束都不会被破环。这两个功能点,在有原子性(Atomicity)和隔离性(Isolation)的基础上,系统实现起来相对简单。所以,在这篇文章中,我们只详细描述原子性(

4、Atomicity)和隔离性(Isolation)两个特性。原子性(Atomicity)原子性(Atomicity)是事务中最重要的特性,如果一切操作正常,保证原子性(Atomicity)并不复杂。保证事务原子性(Atomicity)的复杂性多出自异常处理,例如宕机恢复、主备切换等。以一个事务修改两行数据为例,如果在修改完第一行之后、修改第二行之前机器宕机了,如果没有其他机制保证,待机器重新恢复服务,就只有第一行的修改存留在系统中,违反了原子性(Atomicity)的要求。什么是原子性(Atomicity)实现原子性(Atomicity)的一种方法是将多个操作的生效时机放在一个原子操作上。计算

5、机系统在内存操作上可以做到原子性的操作有给一个内存变量赋值、CAS操作等。硬盘的原子性操作和硬件本身有关,磁盘一般是一个512字节的块写入是原子的,SSD一般是4KB的块写入是原子的。用一个数据结构的例子说明这种原子性实现机制。structBalanceintaccountA;intaccountB;Balance*x=Balance();上面是C+的结构体,表示了两个账户A和B的余额。如果从A转账5元给B,对应的C+代码如下:x-accountA-=5;x-accountB+=5;上面的代码不是原子的,在两条语句中间,如果另一个线程读取accountA和accountB的值,会发现转账操作只

6、执行了一半。如果使用下面的代码,就可以保证无论什么时候读取,都不会读到转账执行了一半的情况:Balance*tmp=newBalance();tmp-accountA=x-accountA-5;tmp-accountB=x-accountB+5;x=tmp;操作的生效时间是x=tmp;语句,单一变量的赋值操作是原子的,保证了整个转账操作是原子的。使用日志实现原子性(Atomicity)上面基于原子性操作的实现方法在数据结构中很常用,但是现在数据库系统都是使用日志技术(log)实现原子性(Atomicity),因为日志技术解决原子性的方法更灵活,还能同时解决了事务的持久性(Durability)

7、需求,而且比直接持久化数据有更好的性能,所以几乎所有的数据库系统都采用了日志技术(log),甚至还包括文件系统、队列系统等。使用10g时,先把整个事务的操作编码成连续的日志信息,再把日志信息写入持久化设备,当日志成功写入后,就是保证事务原子性成功的时机。以上面的转账操作为例,编码出的日志信息如下:,当上面的信息持久化成功后,数据库系统再会修改两个帐户的数据,而且帐户数据本身持久化到硬盘的时机可以延后到任意时刻,因为即使数据没有持久化前就宕机了,系统重启后还是可以从10g中将上面的转账操作恢复出来。所以,转账事务的原子性(Atomicity)成功的时机就是log持久化成功的时间点。对于一次数据库

8、事务,如果只有这么一条日志并且长度小于硬盘的一次原子写入操作,例如磁盘的512字节,那么原子性很容易保证,这次写入成功了,事务就成功了;如果写入失败了,那么事务就没有完成。如果事务只需要写一条日志但是日志长度大于一次原子写入的大小,就需要附加的手段来保证log写入的原子性。一种常见方法是用长度加上校验值(checksum),在这条日志的头部包含整条日志的长度和校验值(checksum)。从日志文件里读取日志时,首先读到日志头部,获取日志长度和校验值(checksum),然后根据日志长度将整条日志内容读取出,并且和校验值(checksum)比对,如果一致,那么既认为日志时完整的,对应的事务也是成

9、功提交的;如果校验值(checksum)不一致,那么认为事务失败。如果事务的信息会分成多次写入硬盘,即事务包含多条日志。在这多条日志中,每条日志的处理方法都与前面描述的一样,但是事务最终是否保证了原子性需要依赖这多条日志都持久化成功,所以数据库系统会在所有日志都持久化成功后再写最后一条确认日志,只有最后一条日志写成功了,事务才算成功,否则,事务还是会被回滚。分布式事务原理上面这种方法适用的前提是事务的所有日志都在一个日志序列中。当数据库是由多台机器组成时,每台机器都会有自己的日志,一个事务如果涉及多台机器,那么就会将日志写到多台机器上,我们称这种事务为分布式事务。理论上,即使事务的日志分散在多

10、台机器上,事务提交时,如果所有机器都持久化日志成功,那么事务就算提交成功,并且可以保证原子性(Atomicity)。比较麻烦的是,如果机器重启,从日志中恢复事务状态时,同样需要询问所有机器来确认是否事务的所有日志都持久化成功了。但是实际的系统中无法承受每次需要恢复事务状态时,都要对每个事务进行多机通讯。所以,分布式事务采用两阶段提交的方式,对于单机写日志的流程进行扩展,来适应分布式事务。左侧(a)是协调者状态机,右侧(b)是参与者状态机。协调者是驱动整个事务提交流程的主体,实现中它可以在任意机器上,当然也可以和其中一个参与者在一台机器上。参与者是真正做事务操作的执行者。协调者首先通知所有的参与

11、者持久化(图中的prepare命令),当参与者将事务的日志持久化成功后会回复prepareok,当所有参与者都回复prepareok后,意味着整个事务完成了,然后协调者会写下事务commit的日志,并且发送commit给所有参与者,如果其中任何一个参与者返回失败(即abortok),那么协调者就会认为事务是失败的,记下事务回滚的日志,并且发送abort给所有参与者。在这个流程下,分布式事务提交的延迟是2次写日志(参与者写prepare日志+协调者写commit日志)的延迟和2次通讯(协调者通知参与者prepare+协调者通知参与者commit)的延迟。OceanBase对于分布式事务的优化Oc

12、eanBase的两阶段提交协议对这个流程做了优化,事务是否提交本质上取决于是否事务的所有日志都持久化到硬盘中,不依赖协调者的日志,日志全部持久化的状态也是确定的。所以,OceanBase的两阶段提交流程取消了协调者写日志的过程,将协调者变成一个无持久化状态的状态机,状态机如下:看起来很复杂,是因为实际的工程项目中还需要处理各种异常情况,还有各种优化。参与者状态机如下:在上面的协调者和参与者的状态机中,与经典状态机除了多了很多异常和优化的处理,还有一个最大的不同是多了一个CLEAR阶段,理论上协调者完成commit操作后整个事务流程就结束了,但是在实际实现中,虽然事务状态确定了,但是协调者和参与

13、者之间还可能因为网络丢包或者机器异常等导致信息传输不确定的状况,需要互相查询状态或者重试,这时CLEAR状态的意义就是保证所有状态机都达到确定状态了,才对状态机对应的数据结构进行清理。OceanBase对于协调者的优化前文描述过,在单机事务的场景中,如果一个事务需要写多条日志,在确认所有日志写成功后,会写下最后一条日志表示整个事务确认完成提交。这最后一条日志的信息是可以和正常事务日志的最后一条合并在一起的。但是在分布式事务中,两阶段提交的协调者在确认所有参与者上的日志都写成功后写下的commit日志是无法从工程上与任何参与者的日志合并在一起的。但是,事务是否提交本身是在所有参与者的日志都成功持

14、久化的时候就确定了的。所以,OceanBase做的一个重大优化就是省去协调者的commit日志。调者接收到所有参与者的prepareok消息后,不写本地的commit日志,直接给所有参与者发送commit请求。当参与者收到commit请求后会写下commit日志,这条日志是原始的协议中也会有的操作。在这个模式下,极端的情况是当所有参与者都成功写下prepare日志,但是在协调者发送commit消息之前,系统出现宕机,如何恢复这个本应该成功的事务。宕机重启后,参与者发现事务处于PREPARED犬态,则会询问协调者事务的状态。因为协调者也是宕机重启了并且协调者不持久化任何信息,所以并没有任何协调者

15、的状态。但是协调者会在收到参与者的询问请求后,构建出协调者状态机,并询问其他所有参与者的事务状态,当发现所有参与者都是PREPARED犬态,就能确定这个事务是最终成功commit的,然后会给所有参与者发送commit请求,状态机就正常运转下去了。OceanBase对于单机多partition事务的优化OceanBase的部署是以partition为单位,一台机器上的多个partition分别有各自独立的paxosgroup,所以即使是一台机器上的事务,如果涉及多个partition,也是分布式事务。多机的分布式事务应答用户的时机是在所有参与者应答协调者commitok之后,OceanBase使用了MVCC机制进行并发控制,参与者在事务提交时需要进行修改全局版本号的操作(下面章节会描述),所以参与者在收到commit请求时,可以先修改全局版本号并且回复协调者,再持久化commit日志。但是commit操作在网络上的roundtrip时间还是需要消耗的。对于单机多partition事务,多个partition需要修改的全局版本号其实是一个,所以协调者在收到所有参与者回复的prepareok请求后,认为事务可以提交时,就可以帮助

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 演讲稿/致辞

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号