《postgresql指南--内幕探索》第九章 预写式日志(WAL)

事务日志是数据库的重要组成部分,存储了数据库系统中所有更改和操作的历史,以确保数据库不会因为故障(例如掉电或其他导致服务器崩溃的故障)而丢失数据。在PostgreSQL(以下简称PG)中,事务日志文件称为Write Ahead Log(以下简称WAL)。

使用WAL不仅可以保证数据库事务操作的持久性,也可以显著地减少写磁盘的次数,因为只需要把日志文件刷新到磁盘就可以保证事务被提交,而不需要把事务改动过的每一个数据文件都刷新到磁盘。日志文件是连续写的,所以同步log的花销远小于刷新数据页的花销。特别是服务器要处理涉及数据存储不同部分的大量小事务时更是这样。

WAL还使得在线备份和时间点恢复成为可能。通过归档WAL数据,我们可以恢复到WAL数据覆盖范围内的任何时间点:只需install一份数据库的物理备份,并恢复WAL日志到所需时间即可。更重要的是,这个物理备份并不必须是一个数据库状态的瞬时快照。

WAL 步骤简介

WAL机制实际是在这个写数据的过程中加入了对应的写wal log的过程,步骤一样是先到Buffer,再刷新到Disk。

  • Change发生时:
    • 先将变更后内容记入WAL Buffer
    • 再将更新后的数据写入Data Buffer
  • Commit发生时:
    • WAL Buffer刷新到Disk
    • Data Buffer写磁盘推迟
  • Checkpoint发生时:
    • 将所有Data Buffer刷新到磁盘

如下图所示:
图1:change 发生时
在这里插入图片描述
图2:commit及checkpoint发生时
在这里插入图片描述

WAL术语介绍

为方便理解下文内容,先介绍以下WAL术语:

1、 REDO log

Redo log通常称为重做日志,在写入数据文件前,每个变更都会先行写入到Redo log中。其用途和意义在于存储数据库的所有修改历史,用于数据库故障恢复(Recovery)、增量备份(Incremental Backup)、PITR(Point In Time Recovery)和复制(Replication)。

2、 WAL segment file

为了便于管理,PG把事务日志文件划分为N个segment,每个segment称为WAL segment file,每个WAL segment file大小默认为16MB。

3、 XLOG Record

这是一个逻辑概念,可以理解为PG中的每一个变更都对应一条XLOG Record,这些XLOG Record存储在WAL segment file中。PG读取这些XLOG Record进行故障恢复/PITR等操作。

4、 WAL buffer

WAL缓冲区,不管是WAL segment file的header还是XLOG Record都会先行写入到WAL缓冲区中,在"合适的时候"再通过WAL writer写入到WAL segment file中。

5、 LSN

LSN即日志序列号Log Sequence Number。表示XLOG record记录写入到事务日志中位置。LSN的值为无符号64位整型(uint64)。在事务日志中,LSN单调递增且唯一。

6、 checkpointer

checkpointer是PG中的一个后台进程,该进程周期性地执行checkpoint。当执行checkpoint时,该进程会把包含checkpoint信息的XLOG Record写入到当前的WAL segment file中,该XLOG Record记录包含了最新Redo point的位置。

7、 checkpoint

检查点checkpoint由checkpointer进程执行,主要的处理流程如下:

(1) 获取Redo point,构造包含此Redo point检查点(详细请参考Checkpoint结构体)信息的XLOG Record并写入到WAL segment file中;

(2) 刷新Dirty Page到磁盘上;

(3) 更新Redo point等信息到pg_control文件中。

8、 REDO point

REDO point是PG启动恢复的起始点,是最后一次checkpoint启动时事务日志文件的末尾亦即写入Checkpoint XLOG Record时的位置(这里的位置可以理解为事务日志文件中偏移量)。

9、 pg_control

pg_control是磁盘上的物理文件,保存检查点的基本信息,在数据库恢复中使用,可通过命令pg_controldata查看该文件中的内容。

WAL机制介绍

下文描述了在不同情况下,不使用WAL和使用WAL机制对数据库数据持续性和恢复的影响。为了简化描述,仅使用了只包含一页的表TABLE_A。

无 WAL 的插入操作

如第8 章所述,为了高效访问关系页面,每个 DBMS 都实现了共享缓冲池。
假设我们在不执行 WAL 功能的 PostgresQL 上将一些数据图块插入到TABLE_A中:
在这里插入图片描述
如上图所示:

  1. 发布第一个插入语句,PostgreSQL 将TABLE_A的页面从数据库集群加载到内存共享缓冲池中,并将一个 tuple 插入页面。此页面不会立即写入数据库集群。(如第 8 章所述,修改后的页面通常称为脏页)
  2. 发布第二个插入语句,PostgreSQL 在缓冲池上的页面中插入一个新的 Tuple。此页面尚未写入存储。
  3. 如果操作系统或 PostgreSQL 服务器因任何原因(如电源故障)而发生故障,则所有插入的数据都将丢失。

因此,没有 WAL 的数据库容易受到系统故障的影响。

插入操作和数据库恢复

为了在不影响性能的情况下处理上述系统故障,PostgreSQL 支持 WAL。此子节中的一些关键字和关键概念,请参考前文。

PostgreSQL 将所有修改作为历史数据写入持久存储,以便为失败做好准备。在PG中,历史数据称为XLOG记录或WAL数据。

XLOG 记录通过插入、删除或提交操作等操作将更改写入内存WAL 缓冲区。当事务提交/中止时,它们会立即写入存储中的WAL segment文件。
XLOG 记录的LSN(日志序列号)表示其记录写在事务日志上的位置。XLOG 记录的 LSN 用作 XLOG 记录的特有ID。

顺便说一句,当我们考虑数据库系统如何恢复时,可能有一个问题:PG从什么位置开始恢复?答案是redo point:即在启动最新检查点时编写 XLOG 记录的位置。事实上,数据库恢复处理与检查点处理紧密相连,这两种处理都是不可分割的。

下图为带WAL日志的插入:
在这里插入图片描述

  1. checkpointer、后台进程定期执行检查。每当检查点进程启动时,它都会向当前的 WAL segment编写称为checkpoint记录的 XLOG 记录。此记录包含最新REDO point的位置。
  2. 发布第一个插入语句,PostgreSQL 将TABLE_A的页面加载到共享缓冲池中,将tuple插入页面,在LSN_1位置的 WAL 缓冲器中创建并写入此语句的 XLOG 记录,并将TABLE_A LSN 从LSN_0更新到LSN_1。

在此示例中,此 XLOG 记录是一组头数据和整个tuple。

  1. 当此事务提交时,PostgreSQL 创建并将此提交操作的 XLOG 记录创建并写入 WAL 缓冲区,然后从LSN_1将 WAL 缓冲器上的所有 XLOG 记录写入并冲洗到 WAL 段文件中。
  2. 发布第二个插入声明,PostgreSQL 将一个新的 tuple 插入页面,创建并将此 tuple 的 XLOG 记录写到LSN_2的 WAL 缓冲器中,并将TABLE_A LSN 从LSN_1更新到LSN_2。
  3. 当本声明的事务提交时,PostgreSQL 的操作方式与步骤 3 相同。
  4. 想象操作系统此时发生故障。尽管共享缓冲池上的所有数据都丢失了,但页面的所有修改都已作为历史数据写入 WAL 段文件。

以下说明显示了如何立即将数据库集群恢复到崩溃前状态。无需做任何特别的事情,因为 PostgreSQL 将通过重新启动自动进入恢复模式。PG将依次从REDO点在适当的WAL段文件中读取和重放XLOG记录。
在这里插入图片描述

  1. PostgreSQL 从适当的 WAL 段文件中读取第一个插入语句的 XLOG 记录,将数据库集群中的TABLE_A页面加载到共享缓冲池中。
  2. 在尝试重放XLOG 记录之前,PostgreSQL 应将 XLOG 记录的 LSN 与相应页面的 LSN 进行比较,重放XLOG 记录的规则如下所示。
    如果 XLOG 记录的 LSN 大于页面的 LSN,则 XLOG 记录的数据部分将插入页面,页面的 LSN 将更新为 XLOG 记录的 LSN。另一方面,如果 XLOG 记录的 LSN 较小,则阅读下一个 WAL 数据。
    在此示例中,XLOG 记录被重放,因为 XLOG 记录的 LSN(LSN_1) 大于TABLE_ALSN(LSN_0)。然后,TABLE_A的LSN从LSN_0更新到LSN_1。
  3. PG以同样的方式重放剩余的XLOG记录。

PostgreSQL 可以通过按时间顺序重放 WAL 段文件中编写的 XLOG 记录来恢复自身。因此,PG的XLOG记录显然是REDO日志。

整页写

假设因为操作系统在编写脏页的过程中出现故障,导致TABLE_A存储上的页面数据损坏。由于 XLOG 记录无法在损坏的页面上重放,因此我们需要额外的操作。

PostgreSQL 支持一项称为整页写的功能,以处理此类故障。如果启用,PostgreSQL 将在每个检查点后每个页面的第一次更改中将一对头数据和整个页面作为 XLOG 记录写入。PG默认已启用整页写。在 PostgreSQL 中,包含整个页面的此类 XLOG 记录称

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值