物理/逻辑复制支持从WAL Buffer中读取WAL日志

PolarDB PostgreSQL版的物理/逻辑复制支持从WAL Buffer中读取WAL日志,从而将复制进程的WAL日志读I/O优化为内存拷贝。这将显著减少因多个复制进程引发的WAL日志读I/O放大,节省读取WAL日志所消耗的带宽,并降低WAL日志的读取时延,从而有效减少复制时延。

背景

原生PostgreSQL中,复制可以被分为物理复制逻辑复制

  • 物理复制:通过传递WAL日志的内容实现Primary和Standby节点之间的同步。

  • 逻辑复制:通过传递WAL日志中解码出的逻辑变更,实现发布端和订阅端节点之间的数据同步。

一个运行中的PostgreSQL允许同时存在多个物理复制和逻辑复制链路,每一个链路由一个对应的WAL sender进程负责读取已经持久化到存储上的WAL日志,完成必要的解析后通过网络发送到下游。每条复制链路之间互相独立,复制进度不受彼此影响。

由于复制进度互相独立,因此每个复制进程都需要各自读取全量的WAL日志并做处理和发送。当复制链路数量较多时,WAL日志的读带宽会呈倍数高于WAL日志的写带宽,消耗大量IOPS。当实例I/O压力较大时,大量的WAL日志读I/O和日常业务的读写I/O会互相影响I/O时延,日常业务的运行速度会变慢,复制延时也会变大。

原生PostgreSQL中,WAL日志产生时,会先被写入到WAL Buffer中,然后再被后台进程或普通进程写入存储。WAL Buffer中的空间会被循环复用,因此WAL Buffer中留存了所有最近产生的WAL日志,也是最大概率会被复制进程使用到的部分。

PolarDB PostgreSQL版支持直接从WAL Buffer中消费已经落盘但依旧留存的WAL日志,从而将复制进程的WAL日志读 I/O优化为内存拷贝。该优化不仅能够极大减少因多个复制进程引发的WAL日志读I/O放大,节省读取WAL日志所消耗的带宽,还可以降低WAL日志的读取时延,从而降低复制时延。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

PostgreSQL 14(内核小版本14.13.27.0及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本号:

SELECT version();

使用方法

设置polar_enable_read_from_wal_buffers参数为on使其对复制进程生效。默认值为on。通过控制台设置集群参数详细操作,请参考设置集群参数

通过polar_monitor插件可查看从WAL Buffer中读取WAL日志的命中情况。

  1. 创建polar_monitor插件。

    CREATE EXTENSION IF NOT EXISTS polar_monitor;
  2. 查看从WAL Buffer中读取WAL日志的命中情况。

    SELECT * FROM polar_stat_walsnd_xlog_read();

    返回结果如下:

       pid   | hit  | hit_bytes | prefetched | prefetched_bytes | read | read_bytes
    ---------+------+-----------+------------+------------------+------+------------
     3865685 | 2175 | 251583064 |          0 |                0 |   82 |   10628128
     3865751 | 2173 | 251582792 |          0 |                0 |   82 |   10628400
    (2 rows)

返回字段描述如下:

列名

数据类型

描述

pid

INTEGER

复制进程PID。

hit

BIGINT

直接命中WAL Buffer的读I/O次数。

hit_bytes

BIGINT

直接命中WAL Buffer的读I/O字节数。

prefetched

BIGINT

从存储上批量预读取WAL日志并在内存中缓存后,命中内存缓存的读I/O次数。

prefetched_bytes

BIGINT

从存储上批量预读取WAL日志并在内存中缓存后,命中内存缓存的读I/O字节数。

read

BIGINT

从存储上读取WAL日志的读I/O次数。

read_bytes

BIGINT

从存储上读取WAL日志的读I/O字节数。