postgreSQL WAL简介

PostgreSQL通过预写式日志(wal日志)来保证数据不丢失

没有WAL机制的场景

没有 WAL 的数据库容易受到系统故障的影响,如下图,如果操作系统或 PostgreSQL 服务器发生故障,则所有插入的数据都可能丢失
postgreSQL WAL简介_第1张图片
(1) 发出第一条 INSERT 语句,PostgreSQL 将 TABLE_A 的页面从数据库集群加载到内存共享缓冲池中,并在页面中插入一个元组。此页面不会立即写入数据库。

(2) 发出第二条 INSERT 语句,PostgreSQL 在缓冲池上的页中插入一个新的元组。此页尚未写入存储。

(3) 如果操作系统或PostgreSQL服务器因停电等任何原因出现故障,所有插入的数据都将丢失。

引入WAL机制后

XLOG 将更改操作(例如插入、删除或提交操作)写入内存中的WAL 缓冲区。当事务提交/中止时,它们会立即写入存储上的WAL 段文件

XLOG 记录的LSN(日志序列号)表示其记录在事务日志上的写入位置。记录的 LSN 用作 XLOG 记录的唯一 ID。

在崩溃发生后重新启动数据库,PG会从redo point开始恢复
下图为使用 WAL 进行插入操作
postgreSQL WAL简介_第2张图片
(1) checkpointe是一个后台进程,周期性地执行checkpoint。每当检查点启动时,它都会将一个名为检查点记录的 XLOG 记录写入当前 WAL 段。此记录包含最新REDO 点的位置。

(2) 发出第一条INSERT语句,PostgreSQL将TABLE_A的页面加载到共享缓冲池中,在页面中插入元组,在位置LSN_1处创建并写入该语句的XLOG记录到WAL缓冲区中,并更新TABLE_A的LSN从LSN_0到LSN_1。
(3) 当这个事务提交时,PostgreSQL 会创建这个提交操作的 XLOG 记录并将其写入 WAL 缓冲区,然后,将 WAL 缓冲区上的所有 XLOG 记录写入并刷新到 WAL 段文件,更新LSN_0为LSN_1。

(4) 发出第二条 INSERT 语句,PostgreSQL 在页面中插入一个新的元组,创建并写入这个元组的 XLOG 记录到LSN_2处的 WAL 缓冲区,并将 TABLE_A 的 LSN 从LSN_1更新为LSN_2。

(5) 当这条语句的事务提交时,PostgreSQL 的操作方式与步骤 (3) 中相同。

(6) 此时即使共享缓冲池上的所有数据都丢失了,页面的所有修改也已作为历史数据写入 WAL 段文件。

下图为使用 WAL 进行数据库恢复
postgreSQL WAL简介_第3张图片
(1) PostgreSQL 从相应的 WAL 段文件中读取第一个 INSERT 语句的 XLOG 记录,将 TABLE_A 的页面加载到共享缓冲池中。

(2) 在尝试重放XLOG 记录之前,PostgreSQL 会比较XLOG 记录的LSN 与对应页面的LSN

  1. 如果 XLOG 记录的 LSN 大于页面的 LSN,则将 XLOG 记录的数据部分插入到页面中,并将页面的 LSN 更新为 XLOG
    记录的 LSN
  2. 如果 XLOG 记录的 LSN 较小,则只能读取下一个 WAL 数据

在此示例中,由于XLOG记录的 LSN ( LSN_1 ) 大于 TABLE_A 的 LSN ( LSN_0 ),因此重放 XLOG 记录;

(3) PostgreSQL 以同样的方式重放剩余的 XLOG 记录。

整页写入

上面的恢复是基于从存储中拿到的页面是未被破坏的场景,WAL机制当前无法在损坏的页面上重放 XLOG 记录

为了支持这一能力,PG引入了整页写入(full-page writes )的功能来处理此类故障。如果启用,PostgreSQL在每个检查点后每个页面的第一次更改期间写入一对 header-data 和整个页面作为 XLOG 记录;
postgreSQL WAL简介_第4张图片
(1) checkpointer启动一个checkpoint进程。
(2) 在第一条INSERT语句的插入中,虽然PostgreSQL的操作方式与上一小节几乎相同,但这条XLOG记录是该页的备份块(即它包含了整个页),因为这是在最新的检查点之后首次写入此页面。
(3) 当这个事务提交时,PostgreSQL 以与上一小节相同的方式运行。
(4) 在第二条INSERT语句的插入中,由于这条XLOG记录不是备份块,PostgreSQL的操作方式与上一小节相同。
(5) 当这条语句的事务提交时,PostgreSQL 以与上一小节相同的方式运行。
(6) 为了证明整页写入的有效性,这里我们考虑在后台写入器一直在将其写入硬盘时,由于操作系统发生故障,存储上的TABLE_A页面已损坏的情况。

使用备份块进行数据库恢复
postgreSQL WAL简介_第5张图片
(1) PostgreSQL 读取第一个 INSERT 语句的 XLOG 记录,并将损坏的 TABLE_A 页面从数据库集群加载到共享缓冲池中。在这个例子中,XLOG记录是一个备份块,因为按照整页写的写规则,每页的第一个XLOG记录总是它的备份块。

(2) 当 XLOG 记录是它的备份块时,应用另一个重放规则:

无论两个 LSN 的值如何,记录的数据部分(即页面本身)都将被覆盖到页面上,并且页面的 LSN 更新到 XLOG 记录的 LSN。

在此示例中,PostgreSQL 将记录的数据部分覆盖到损坏的页面,并将 TABLE_A 的 LSN 更新为LSN_1。通过这种方式,损坏的页面由其备份块恢复。

(3) 由于第二条 XLOG 记录是一个非备份块,PostgreSQL 的操作方式与上一小节中的指令相同。

你可能感兴趣的:(postgresql,数据库,服务器)