Write-Ahead Log(PostgreSQL 14 Internals翻译版)

news2024/11/17 19:31:13

日志

如果发生停电、操作系统错误或数据库服务器崩溃等故障,RAM中的所有内容都将丢失;只有写入磁盘的数据才会被保留。要在故障后启动服务器,必须恢复数据一致性。如果磁盘本身已损坏,则必须通过备份恢复来解决相同的问题。

理论上,您可以始终保持磁盘上的数据一致性。但在实践中,这意味着服务器必须不断地将随机页面写入磁盘(尽管顺序写入更便宜),而且这种写入的顺序必须保证在任何特定时刻都不会损害一致性(这很难实现,特别是在处理复杂的索引结构时)。

就像大多数数据库系统一样,PostgreSQL使用了不同的方法。

当服务器运行时,一些当前数据仅在RAM中可用,将其写入永久存储器被推迟。因此,在服务器操作期间,存储在磁盘上的数据总是不一致的,因为页面永远不会一次刷新。但是在RAM中发生的每个更改(例如在缓冲区缓存中执行的页面更新)都被记录下来:PostgreSQL创建一个日志条目,其中包含在需要时重复此操作所需的所有基本信息

与页面修改相关的日志条目必须在被修改的页面本身之前写入磁盘。因此,该日志的名称为:预写日志(write-ahead log)或WAL。这个要求保证了在发生故障的情况下,PostgreSQL可以从磁盘读取WAL条目并重放它们以重复已经完成的操作,这些操作的结果仍然在RAM中,并且在崩溃之前没有将其保存到磁盘中。

保持预写日志通常比将随机页面写入磁盘更有效。WAL条目构成连续的数据流,甚至可以由HDD处理。此外,WAL条目通常小于页面大小。

在发生故障时,需要记录所有可能破坏数据一致性的操作。具体来说,在WAL中记录了以下动作:

  • 在缓冲缓存中执行的页面修改——因为写操作被延迟
  • 事务提交和回滚—因为状态更改发生在CLOG缓冲区中,而不会立即将其转移到磁盘
  • 文件操作(比如在添加或删除表时创建和删除文件和目录)——因为这些操作必须与数据更改同步

以下操作不被记录:

  • UNLOGGED表的操作
  • 对临时表的操作——因为它们的生命周期受到生成它们的会话的限制

在PostgreSQL 10之前,哈希索引也不被记录。它们的唯一目的是将哈希函数与不同的数据类型相匹配。

除了崩溃恢复之外,WAL还可以用于从备份和复制中进行时间点恢复

WAL结构

逻辑结构

谈到它的逻辑结构,我们可以将WAL描述为可变长度的日志条目流。每个条目包含一些关于特定操作的数据,前面有一个标准头。除其他事项外,头文件提供以下信息:

  • 和条目有关于的事务ID
  • 解释条目的资源管理器
  • 检测数据损坏的校验和
  • 条目长度
  • 对前一个WAL条目的引用

WAL通常是向前读取的,但是一些实用程序(如pg_rewind)可能会向后扫描它。

WAL数据本身可以具有不同的格式和含义。例如,它可以是一个页片段,它必须在指定的偏移量处替换页的某些部分。相应的资源管理器必须知道如何解释和重放特定的条目。表、各种索引类型、事务状态和其他实体都有单独的管理器。

WAL文件占用服务器共享内存中的特殊缓冲区。WAL使用的缓存大小由wal_buffers参数定义。默认情况下,自动选择该大小为总缓冲区缓存大小的1/32。

WAL缓存与缓冲区缓存非常相似,但它通常以环形缓冲区模式运行:新条目添加到其头部,而旧条目从尾部开始保存到磁盘。 如果WAL缓存太小,则执行磁盘同步的频率将超出必要的范围。

在低负载情况下,插入位置(缓冲区的头部)几乎总是与已经保存到磁盘的条目的位置(缓冲区的尾部)相同:

在这里插入图片描述
在PostgreSQL之前,所有函数名都包含XLOG缩写而不是WAL。

为了引用一个特定的条目,PostgreSQL使用一个特殊的数据类型:pg_lsn(日志序列号,LSN)。它表示从WAL开始到条目的64位字节偏移量。LSN表示为两个32位的十六进制数,中间用斜杠分隔。

创建一个表:
在这里插入图片描述
启动一个事务并记录WAL插入位置的LSN:
在这里插入图片描述
现在运行一些任意命令,例如,更新一行:
在这里插入图片描述
页面修改在RAM中的缓冲缓存中执行。此更改记录在WAL页面中,也记录在RAM中。因此,插入LSN被提前:
在这里插入图片描述
为了确保修改后的数据页严格在相应的WAL条目之后被刷新到磁盘,页头存储了与该页相关的最新WAL条目的LSN。你可以使用pageinspect查看LSN:

在这里插入图片描述
整个数据库集群只有一个WAL,并且不断向其添加新条目。由于这个原因,存储在页面中的LSN可能比前一段时间pg_current_wal_insert_lsn函数返回的LSN要小。但是如果系统中什么都没有发生,这些数字将是相同的。

现在提交事务:
在这里插入图片描述
提交操作也被记录,插入LSN再次更改:

在这里插入图片描述
提交更新CLOG页面中的事务状态,这些页面保存在它们自己的缓存中。CLOG缓存通常在共享内存中占用128页。为了确保在相应的WAL条目之前不会将CLOG页面刷新到磁盘,还必须跟踪CLOG页面的最新WAL条目的LSN。但是这些信息存储在RAM中,而不是页面本身。

在某个时刻,WAL条目将被写入磁盘;然后就可以从缓存中驱逐CLOG和数据页。如果必须更早地驱逐它们,则会发现它,并且会先将WAL条目强制写入磁盘。

如果您知道两个LSN位置,则可以通过简单地从一个位置减去另一个位置来计算它们之间的WAL条目的大小(以字节为单位)。你只需要将它们强制转换为pg_lsn类型:

在这里插入图片描述
在本例中,与UPDATE和COMMIT操作相关的WAL条目占用了大约100个字节。

您可以使用相同的方法来估计特定工作负载在单位时间内生成的WAL条目的数量。检查点设置将需要这些信息。

物理结构

在磁盘上,WAL作为单独的文件或段存储在PGDATA/pg_wal目录中。它们的大小由只读的wal_segment_size参数显示。

对于高负载系统,增加段大小是有意义的,因为它可以减少开销,但是这个设置只能在集群初始化期间修改(initdb --wal-segsize)。

WAL条目进入当前文件,直到空间用完;然后,PostgreSQL启动一个新文件。

我们可以知道一个特定的条目位于哪个文件中,以及从文件开始的偏移量:

在这里插入图片描述
文件名由两部分组成。最高的8个十六进制数字定义了用于从备份中恢复的时间线,而其余的数字表示最高的LSN位(最低的LSN位显示在file_offset字段中)。

要查看当前的WAL文件,可以调用以下函数:
在这里插入图片描述
在这里插入图片描述
现在,让我们使用pg_waldump实用程序查看新创建的WAL条目的头,该实用程序可以根据LSN范围(如本例中所示)和特定事务ID过滤WAL条目。

应该使用postgres操作系统用户启动pg_waldump实用程序,因为它需要访问磁盘上的WAL文件。

在这里插入图片描述
这里我们可以看到两个条目的标题。

第一个是由Heap资源管理器处理的HOT_UPDATE操作。blkref字段显示了更新后的堆页的文件名和页ID:

在这里插入图片描述

第二个条目是由事务资源管理器监督的COMMIT操作。

检查点

在失败后恢复数据一致性(即执行恢复),PostgreSQL必须往前重放WAL,并将代表丢失的更改的条目应用到相应的页面。为了找出丢失的内容,将存储在磁盘上的页面的LSN与WAL条目的LSN进行比较。但我们应该从什么时候开始复苏呢?如果我们开始得太晚,在此之前写入磁盘的页面将无法接收到所有更改,这将导致不可逆转的数据损坏。从头开始是不现实的:不可能存储如此庞大的潜在数据量,也不可能接受如此长的恢复时间。我们需要一个逐渐向前移动的检查点,这样可以安全地从该点开始恢复并删除所有以前的WAL条目。

创建检查点最直接的方法是定期挂起所有系统操作,并将所有脏页强制放到磁盘上。这种方法当然是不可接受的,因为系统将挂起一段不确定但相当重要的时间。

由于这个原因,检查点随着时间的推移而分散,实际上构成了一个间隔。检查点的执行是由一个叫做checkpointer的特殊后台进程执行的。

  • 检查点开始。 checkpointer进程将可以立即写入的所有内容刷新到磁盘:CLOG事务状态、子事务的元数据和一些其他结构。

  • 检查点执行。 检查点执行的大部分时间都花在将脏页刷新到磁盘上。首先,在检查点开始时已脏的所有缓冲区的标头中设置一个特殊标记。由于不涉及I/O操作,因此它发生得非常快。然后checkpointer进程遍历所有缓冲区并将标记的缓冲区写入磁盘。它们的页面不会从缓存中被驱逐:它们只是被写下来,因此使用量和pin计数可以忽略。页面按照其ID的顺序进行处理,以尽可能避免随机写入。为了更好地实现负载平衡,PostgreSQL 在不同的表空间之间进行切换 (因为它们可能位于不同的物理设备上)。后端也可以将带标签的缓冲区写入磁盘——如果它们先到达的话。在任何情况下,缓冲区标记都在此阶段被删除,因此出于检查点的目的,每个缓冲区将只被写入一次。当然,当检查点正在进行时,仍然可以在缓冲缓存中修改页面。但是由于新的脏缓冲区没有标记,checkpointer将忽略它们。

  • 检查点完成。 当检查点开始时所有脏的缓冲区都被写入磁盘时,就认为检查点完成了。从现在开始(但不是更早!),检查点的起点将被用作恢复的新起点。不再需要在此之前编写的所有WAL条目。

在这里插入图片描述
最后,checkpointer创建一个与检查点完成相对应的WAL条目,指定检查点的起始LSN。 由于检查点在启动时不记录任何日志,因此该LSN可以属于任何类型的WAL条目。

PGDATA/global/pg_control文件也得到更新,以引用最新完成的检查点。 (在此过程结束之前,pg_control将保留前一个检查点。)

在这里插入图片描述
为了一劳永逸地弄清楚哪些点在哪里,让我们看一个简单的例子。我们将使几个缓存页面变脏:
在这里插入图片描述
现在让我们手动完成检查点。所有脏页都将刷新到磁盘;由于系统中没有发生任何事情,因此不会出现新的脏页:

在这里插入图片描述
让我们看看检查点是如何反映在WAL中的:
在这里插入图片描述
最新的WAL条目与检查点完成(CHECKPOINT_ONLINE)有关。 这个检查点的起始LSN在redo后面指定;这个位置对应于检查点开始时最近插入的WAL条目。

同样的信息也可以在pg_control文件中找到:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1106291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ 类和对象(上)------超详细解析,小白必看系列

目录 一、前言 二、面向过程和面向对象初步认识 三、类的引入 三、类的定义 四、类的访问限定符及封装 💦访问限定符 (重点!!!!) 💦封装 五、类的作用域 六、类的实例化 …

算法--排序算法效率比较

《算法设计与分析》课程实验报告 ( 实验一) 实验名称:排序算法效率比较 实验地点: 所使用的开发工具及环境: PC机,DEV 一、实验目的: 比较至少 4 种排序(从小到大排&#xff09…

从十月稻田,看大米为何能卖出200亿市值?

国无农不稳,民无粮不安。新时代的农村农民,需要现代化的农业作依托,而在农业现代化的过程中,品牌化、数字化成为至关重要的一环。 金秋十月,从南到北,从东到西,中国农村的每一块土地都洋溢着丰…

【运筹优化】运筹学导论:线性规划导论

文章目录 一、原形范例(Wyndor Glass 公司)1.1 线性规划模型构建1.2 图解法1.3 结论 二、线性规划模型2.1 线性规划模型的标准形式2.2 其他形式2.3 模型解的术语 三、有关线性规划的假设3.1 比例性3.2 可加性3.3 可分割性3.4 确定性 四、补充例子4.1 放射…

ant的basedir内置属性

basedir是ant的内置属性,代表项目基础路径的绝对路径。它的默认值等于build文件的父目录。当然,可以通过project 的basedir 属性、或者单独的basedir 属性来覆盖。 例如,在工程的根目录下有个build.xml文件: build.xml文件的内…

java springboot 实现 对象或对象数组 转为 前端可解析的JSON字符串格式

这是我的接口代码 逻辑就是 通过 IBookService对象中的 list 函数获取数据列表 然后定义 state(响应状态) message(提示信息) 最后将这三个信息 做成对象返回给前端 接口访问结果 但是这种对象数组对存储空间消耗肯定是比字符串大很多的 所以 我们来尝试 将json数组转成字符…

JOSEF约瑟 漏电继电器 JHOK-ZBG1 φ25mm AC220V 0.1A/0.1S 分体式

系列型号 JHOK-ZBG1 φ25mm漏电(剩余)继电器 JHOK-ZBG2 φ25mm漏电(剩余)继电器 JHOK-ZBG1 φ45mm漏电(剩余)继电器 JHOK-ZBG2 φ45mm 漏电(剩余)继电器 JHOK-ZBG1 φ100mm漏电&a…

广西建筑模板厂家批发——能强优品木业

随着建筑业的蓬勃发展,建筑模板作为不可或缺的基础材料,在工程施工中扮演着重要的角色。在广西,能强优品木业有限公司作为一家备受瞩目的建筑模板厂家批发商,以其卓越的产品品质和优质的服务在行业中脱颖而出。 实力厂家扎根广西 …

电影《前任4:英年早婚》观后感

刚刚国庆节后,没有什么上新电影,只能看国庆节时的电影了,于是选择了这部《前任4:英年早婚》,原本是非常抗拒看这样的电影了,毕竟自己作为单身狗,还是不喜欢吃狗粮的,不过从另一方面讲…

JOSEF约瑟 轨道继电器 CSN-11 DC220V 二转换 35mm导轨安装 大功率启动大于5W

CSN-11轨道继电器 一、用途 该继电器用于电力系统接口设备可与保护装置,安全自动装置等设备接口实现开入隔离,开出重动功能,用于开关量的隔离及转换。CSN-11继电器特点是启动功率大抗力强。采用标准35mm导轨安装。 二、技术参数 1.额定电…

C++算法:给表达式添加运算符

题目 给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target ,在 num 的数字之间添加 二元 运算符(不是一元)、- 或 * ,返回 所有 能够得到 target 的表达式。 注意,返回表达式中的操作数 不应该 包含前导零。…

行情分析——加密货币市场大盘走势(10.18)

大饼昨日小幅度的下跌回调了,很快又上涨。目前看下来震荡向下刚刚开始,可以关注后续情况。大饼依然保持看空不做空,目前除了独立行情的币,就大饼非常强势。目前从MACD日线来看,还是保持多头趋势,预计明后两…

6-2 进制转换 分数 10

Status SPush(SqStack& s, ElemType x) {if (s.top s.stacksize) //栈满return ERROR;s.data[s.top] x;s.top;//1条或2条语句均可return OK; } Status SPop(SqStack& s, int& e) {if (s.top 0) //栈空return ERROR;s.top--; //S.top下移e s.data[s.top]; //把…

WhatsApp 私域营销指南

当涉及到WhatsApp私域营销时,企业正逐渐意识到这个强大工具的潜力,为建立与用户之间更紧密的关系、提供个性化的服务和推广,以及增加用户忠诚度, WhatsApp已成为一个不可或缺的营销渠道。在如今竞争激烈的市场中,私域营…

SSTI模板注入(flask) 学习总结

文章目录 Flask-jinja2 SSTI 一般利用姿势SSTI 中常用的魔术方法内建函数 利用 SSTI 读取文件Python 2Python 3 利用 SSTI 执行命令寻找内建函数 eval 执行命令寻找 os 模块执行命令寻找 popen 函数执行命令寻找 importlib 类执行命令寻找 linecache 函数执行命令寻找 subproce…

腾讯待办将全面停止运营?关停后有什么其他的好用待办软件推荐

微信是很多用户的手机上必下载的软件。在微信中,可以使用各种各样的功能,其中就包括小程序。在微信小程序中,有不少用户都在使用腾讯待办这款工具,它可以记录待办事项,打钩标记完成,还能通过公众号接收待办…

LeetCode26——删除有序数组中的重复项

LeetCode26——删除有序数组中的重复项 自己的暴力解(假设可以使用额外的空间): 时间复杂度:O(N) 空间复杂度:O(N) package keepcoding.leetcode.leetcode26; /*给你一个 非严格递增排列 的数组 nums ,请…

MySql 数据库基础概念,基本简单操作及数据类型介绍

文章目录 数据库基础为什么需要数据库?创建数据库mysql架构SQL语句分类编码集修改数据库属性数据库备份 表的基本操作存在时更新,不存在时插入 数据类型日期类型enum和set 数据库基础 以特定的格式保存文件,叫做数据库,这是狭义上…

水浸监测新方法,简单实用,你值得拥有!

随着科技的不断进步,监控系统已成为我们生活中不可或缺的一部分。然而,许多监控系统在面临水浸等自然灾害时显得无能为力,这可能导致严重的损失和危险。 因此,水浸监控系统的需求不断增加,以保护我们的财产和安全。 客…