暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

openGauss中的事务持久性

openGauss小助手 2021-10-27
151

和业界几乎所有的数据库一样,openGauss通过将事务对于数据库的修改写入可以永久(长时间)保存的存储介质中,来保证事务的持久性。这个过程被称为事务的持久化过程。持久化过程是保证事务持久性所必不可少的环节,其效率对于数据库整体性能影响很大,常常成为数据库的性能瓶颈所在。

最常用的存储介质是磁盘。对于磁盘来说,其每次读写操作都有一个“启动”代价,因此在单位时间内(每秒内),一个磁盘可以进行的读写操作次数(Input/Output Operations Per Second,简称IOPS)是有上限的。HDD磁盘的IOPS一般在1000次/秒以下,SSD磁盘的IOPS可以达到10000次/秒左右。另外一方面,如果多个磁盘读写请求的数据在磁盘上是相邻的,那么可以被合并为一次读写操作,这导致磁盘顺序读写的性能通常要远优于随机读写。

一般来说,尤其是在OLTP场景下,用户对于数据库数据的修改是比较分散随机的。如果在持久化过程中,直接将这些分散的数据写入磁盘,那么这个随机写入的性能是比较差的。因此,数据库通常都采用预写日志(Write Ahead Log,简称WAL)来避免持久化过程中的随机IO,如图10-4(a)所示。所谓预写日志,是指在事务提交的时候,先将事务对于数据库的修改写入一个顺序追加的WAL日志文件中。由于WAL日志的写操作是顺序IO,因此其可以达到一个比较高的性能。另一方面,对于真正修改的物理数据文件,再等待合适的时机写入磁盘,以尽可能合并该数据文件上的IO操作。

在一个事务完成日志的下盘操作(即写入磁盘)以后,该事务就可以完成提交动作。如果在此之后数据库发生宕机,那么数据库会首先从已经写入磁盘的WAL文件中恢复出该事务对于数据库的修改操作,从而保证事务一旦提交即具备持久性的特点。

下面结合图10-4(b)中的例子,简单说明数据库故障恢复的原理。假设一个事务需要在表A(对应数据文件A)和表B(对应数据文件B)中各插入一行新的记录,在数据库内部,其执行的顺序如下:(1)记录修改数据文件A的日志,(2)记录修改数据文件B的日志,(3)在数据文件A中写入新的记录,(4)在数据文件B中写入新的记录。在上述过程中,如果在第(4)步执行时数据库发生宕机,那么该事务对于数据文件B的修改可能全部或部分丢失。当数据库再次启动以后,在其能够接受新的业务之前,需要将这些可能丢失的修改从日志中找回来(该操作被称为日志回放操作)。

在日志回放过程中,数据库会根据日志记录的先后顺序,依次读取每个日志的内容,然后判断该日志记录的事务对数据库数据文件的修改是否和当前相关数据文件的内容一致。如果一致,说明上次数据库停机之前修改已经写入数据文件中,该日志修改无需回放;如果不一致,说明上次数据库停机之前修改还未写入数据文件中,上次数据库停机可能是异常宕机导致,该日志对应的事务操作需要重新在相关数据文件中再次执行,才能保证恢复成功。

对于本例,在数据库恢复过程中,首先读取到在数据文件A中插入记录的日志,将数据文件A读取上来之后,发现数据文件A中已经包含该记录,因此该日志无需回放;然后读取到在数据文件B中插入记录的日志,将数据文件B读取上来之后,发现数据文件B中未包含新插入的记录,因此需要将日志中的记录再次写入到数据文件B中,从而完成恢复。最终,该事务对于数据库所有的修改都得以恢复出来,事务的持久性得到了保证。

(a) WAL日志和数据页面的关系示意图

(b)WAL日志和故障恢复示意图

图10-4 WAL日志和事务持久性示意图

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论