WalWriter


难度 中等

预写式日志WAL机制是对数据文件的修改必须是只能发生在这些修改已经记录到日志之后,即先写日志再写数据。

WalWriter进程负责定期从WAL缓冲区写出日志,并确定写出日志的起点和终点来调用XlogWriter将日志写入到磁盘。

参数配置

  • wal_level

    控制wal存储的级别。wal_level确定有多少信息被写入到WAL。默认值是replica,它添加了WAL归档信息,包括只读服务器(流复制)所需的信息。还可以将其设置为minimal,即只写入从崩溃或立即关闭中恢复所需的信息。设置为Logical允许在逻辑解码场景中完成WAL流。

  • fsync

    这个参数直接控制日志是否先写到磁盘。默认值为ON(先写),这意味着系统应该通过发出wal_sync_method设置的fsync指令,来确保更改确实被刷新到磁盘。虽然关闭fsync通常可以提高性能,但在电源故障或系统崩溃时,这会导致不可恢复的数据损坏。因此,只有当您可以轻松地从外部数据重新创建整个数据库时,才建议关闭fsync。

  • synchronous_commit

    此参数用于配置系统是否等待WAL完全完成后再将状态信息返回给用户事务。默认值为ON,表示必须等待WAL完成后才能返回事务状态信息;配置OFF可以更快地反馈事务状态。

  • wal_sync_method

    这个参数控制WAL写入磁盘的fsync方法。默认值是fsync。可用的值包括open_datasync、fdatasync、fsync_writethrough、fsync、以及open_sync.open_datasync和open_sync。

  • full_page_writes

    指示是否将整个页面写入WAL。

  • wal_buffers

    指示了用于存储WAL数据的内存空间量。系统默认值为64K。此参数还受wal_writer_delay和commit_delay这两个参数的影响。

  • wal_writer_delay

    WalWriter进程的写入间隔。默认值是200毫秒。如果时间过长,可能会导致WAL缓冲区内存不足;如果时间太短,会导致WAL不断写入,增加磁盘I/O负担。

  • wal_writer_flush_after

    当脏数据超过这个阈值时,它将被刷新到磁盘。

  • commit_delay

    指示在WAL buffer中存储已提交的数据的时间。默认值为0毫秒,表示没有延迟;

    当它被设置为非零值时,在事务提交后,事务将不会被立即写入到WAL中,但它仍然存储在WAL buffer中,等待WalWriter进程定期写入磁盘。

  • commit_siblings

    当事务发出提交请求时,如果数据库中的事务数量大于commit_sibling的值,事务将等待一段时间(commit_delay值);否则,事务将直接写入到WAL。系统默认值是5,这个参数还确定了commit_delay的有效性。

源码分析

启动

graph TB main-->PostmasterMain-->StartChildProcess-->fork_process-->AuxiliaryProcessMain-->WalWriterMain

写文件

graph TB loop-->ResetLatch-->|处理信号包括退出进程|HandleWalWriterInterruptss-->XLogBackgroundFlush-->WaitXLogInsertionsToFinish-->XLogWrite-->pgstat_report_wal-->WaitLatch-->loop

WalWriter会根据WalWriterDelay时间进行循环,当WalWriterDelay时间到达后,再次执行XLogBackgroundFlush进行WAL日志写入。

int			WalWriterDelay = 200;
int			WalWriterFlushAfter = 128;

for (;;)
{
    if (XLogBackgroundFlush())
      left_till_hibernate = LOOPS_UNTIL_HIBERNATE;
  else if (left_till_hibernate > 0)
      left_till_hibernate--;
    if (left_till_hibernate > 0)
      cur_timeout = WalWriterDelay;	/* in ms */
  else
      cur_timeout = WalWriterDelay * HIBERNATE_FACTOR;

  (void) WaitLatch(MyLatch,
             WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
             cur_timeout,
             WAIT_EVENT_WAL_WRITER_MAIN);
}

reference

  1. https://www.modb.pro/db/28621

文章作者: growdu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 growdu !
  目录
分类导航
随笔2 AI27 算法1 计算机基础13 博客搭建7 ChatGPT2 集群63 计算机通信1 数据库34 数据库深入80 DPDK26 Docker11 Elasticsearch4 编辑工具4 FAQ1 Go Web1 hometown2 编程语言16 网络9 OPC1 Linux38 openGauss4 页面12 PostgreSQL54 程序员自我修养1 协议11 成长之路1 stock1 存储5 工具20 VPP18 视频作品1 Vue13 Web1 代码示例11 数据库15 BenchmarkSQL1 PostgreSQL 源码修炼之路14
最热文章
1
13 逻辑复制深入
数据库深入🔥 1570
2
0 Postgresql存储、索引及系统优化、主备切换
PostgreSQL🔥 1495
3
一文读懂openguass dcf网络模块
集群🔥 1420
4
逻辑复制源码分析
数据库深入🔥 1327
5
PostgreSQL 分区表:从一行 `PARTITION BY` 到路由热路径的全链路拆解
数据库🔥 1094
6
applyparallelworker.c 之 LA 端源码深度解析:Leader Apply Worker 的指挥中枢
数据库深入🔥 1082
7
PostgreSQL Background Worker 全解:从 `RegisterBackgroundWorker` 到逻辑复制 4 类 worker 的全生命周期
数据库🔥 1078
8
PostgreSQL的后台进程walsender分析 - 关系型数据库 - 亿速云
PostgreSQL🔥 1033
9
PostgreSQL 逻辑复制的监控:六张视图 + 一组可执行 SQL,把 publisher/subscriber 的速率与健康度彻底看透
数据库🔥 1032
10
PostgreSQL 逻辑复制支持 DDL 之后:DDL 与 DML 的时序难题(重点:分区表)
数据库🔥 999
11
reorderbuffer.c 源码深度解析:PostgreSQL 逻辑复制的"事务重组引擎
数据库深入🔥 953
12
PostgreSQL 内核开发:读取一张表的 9 步标准流程与缓存全景
数据库🔥 938
13
从 `postgres` 二进制到生产级守护 —— PostgreSQL 最外层模块与启动全流程拆解
数据库🔥 936
14
支持逻辑复制同步 DDL 适配 SQL Server 方案
数据库深入🔥 934
15
PostgreSQL 逻辑复制的 ReorderBuffer 与事务机制:从一行 WAL 到一致性变更流的全链路绑定
数据库🔥 913
16
DDL同步架构(美化版)
数据库深入🔥 908
17
PostgreSQL Latch 机制详解:从一行 SetLatch 到 epoll 的内核之旅
数据库🔥 871
18
pgbench 源码全解:一个 C 文件如何撑起 PostgreSQL 官方压测工具
数据库🔥 860
19
PostgreSQL libpq 机制与缓冲区详解
数据库🔥 850
20
PostgreSQL 逻辑复制 spill 文件深度剖析:从 `xid-*.spill` 到 TPC-C 的增长方程
数据库🔥 845