{"Entry":{"collection":"storage","key":"wal-internals","name":"WAL Internals","aliases":[],"metadata":{"aliases":[],"category":"Physical structures","content_hash":"b4c1bf3f3df56edb5a2887edb2951954e9a7a700ca9e455fa49af5c29b889e22","derived_content_hash":"816b0cb6f7b0fe8e7f8d37b71361a25a708e3ca0df195dee40b8cbb3b290fbc4","imported_at":"2026-09-30T00:40:47.121215+08:00","name":"WAL Internals","name_zh":"","slug":"wal-internals","summary":"WAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see Section 28.5 )."}},"Definition":{"Collection":"storage","Key":"wal-internals","SourceDatabase":"center","Version":"18","SourceTable":"storage_structure","SourceKey":"wal-internals","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","Facts":{"comparison_data":{"layouts":[]},"comparison_hash":"27341929154bfb55531f03501322b65af719c5561f3c4ddc9528a14aa4df69b5","description":["WAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see Section 28.5 )."],"description_zh":"WAL 会自动启用；管理员除了确保满足 WAL 文件的磁盘空间需求，并完成任何必要调优之外，不需要再做其他操作（见 第 28.5 节 ）。 每写入一条新记录， WAL 记录就会追加到 WAL 文件中。插入位置由日志序列号（ LSN ）描述，它是 WAL 内的一个字节偏移量，会随着每条新记录的写入而单调递增。 LSN 值以数据类型 pg_lsn 返回。通过比较两个值，可以计算它们之间相隔的 WAL 数据量，因此它们可用于衡量复制和恢复的进度。 WAL 文件保存在数据目录下的 pg_wal 目录中，由一组段文件组成，每个段通常为 16 MB（不过可通过修改 --wal-segsize initdb 选项来改变大小）。每个段又分为若干页面，通常每页 8 kB（该大小可通过 configure 选项 --with-wal-blocksize 更改）。WAL 记录头定义在 access/xlogrecord.h 中；记录内容则取决于被记录的事件类型。段文件以不断递增的数字命名，从 000000010000000000000001 开始。这些编号不会回绕，但要把可用的编号耗尽还需要非常、非常长的时间。 如果能将 WAL 放在与主数据库文件不同的磁盘上，会更有利。这可以通过把 pg_wal 目录移动到其他位置（当然要在服务器关闭时进行），然后在主数据目录中的原位置创建一个指向新位置的符号链接来实现。","description_zh_html":"\u003cp\u003e存储结构 wal-internals。\u003c/p\u003e\u003ch3\u003e同版本中文手册节选\u003c/h3\u003e\u003cp\u003e\n\u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 会自动启用；管理员除了确保满足\n   \u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 文件的磁盘空间需求，并完成任何必要调优之外，不需要再做其他操作（见\u003ca class=\"xref\" href=\"/zh/docs/18/wal-configuration.html\"\u003e第 28.5 节\u003c/a\u003e）。\n  \u003c/p\u003e\u003cp\u003e\n   每写入一条新记录，\u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 记录就会追加到\n   \u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 文件中。插入位置由日志序列号（\u003cacronym class=\"acronym\"\u003eLSN\u003c/acronym\u003e）描述，它是 WAL 内的一个字节偏移量，会随着每条新记录的写入而单调递增。\u003cacronym class=\"acronym\"\u003eLSN\u003c/acronym\u003e 值以数据类型\n   \u003ca class=\"link\" href=\"/zh/docs/18/datatype-pg-lsn.html\"\u003e\u003ccode class=\"type\"\u003epg_lsn\u003c/code\u003e\u003c/a\u003e 返回。通过比较两个值，可以计算它们之间相隔的 \u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 数据量，因此它们可用于衡量复制和恢复的进度。\n  \u003c/p\u003e\u003cp\u003e\n\u003cacronym class=\"acronym\"\u003eWAL\u003c/acronym\u003e 文件保存在数据目录下的 \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e 目录中，由一组段文件组成，每个段通常为 16 MB（不过可通过修改\n   \u003ccode class=\"option\"\u003e--wal-segsize\u003c/code\u003e \u003cspan class=\"application\"\u003einitdb\u003c/span\u003e 选项来改变大小）。每个段又分为若干页面，通常每页 8 kB（该大小可通过 configure 选项 \u003ccode class=\"option\"\u003e--with-wal-blocksize\u003c/code\u003e 更改）。WAL 记录头定义在\n   \u003ccode class=\"filename\"\u003eaccess/xlogrecord.h\u003c/code\u003e 中；记录内容则取决于被记录的事件类型。段文件以不断递增的数字命名，从\n   \u003ccode class=\"filename\"\u003e000000010000000000000001\u003c/code\u003e 开始。这些编号不会回绕，但要把可用的编号耗尽还需要非常、非常长的时间。\n  \u003c/p\u003e\u003cp\u003e\n   如果能将 WAL 放在与主数据库文件不同的磁盘上，会更有利。这可以通过把\n   \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e 目录移动到其他位置（当然要在服务器关闭时进行），然后在主数据目录中的原位置创建一个指向新位置的符号链接来实现。\n  \u003c/p\u003e\u003cp\u003e\u003ca href=\"/zh/docs/18/wal-internals.html\"\u003e查看完整中文手册与上下文\u003c/a\u003e。\u003c/p\u003e","facts":[{"label":"Definition scope","value":"Same-version core physical storage documentation"}],"facts_zh":[{"label":"定义范围","value":"同版本核心物理存储文档"}],"manual_html":"\u003cdiv class=\"sect1\"\u003e\n\u003cdiv class=\"titlepage\"\u003e\n\u003cdiv\u003e\n\u003cdiv\u003e\n\u003ch2 class=\"title\"\u003e28.6. WAL Internals \u003c/h2\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cp\u003eWAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see \u003ca class=\"xref\" href=\"/docs/18/wal-configuration.html\" title=\"28.5. WAL Configuration\"\u003eSection 28.5\u003c/a\u003e).\u003c/p\u003e\n\u003cp\u003eWAL records are appended to the WAL files as each new record is written. The insert position is described by a Log Sequence Number (LSN) that is a byte offset into the WAL, increasing monotonically with each new record. LSN values are returned as the datatype \u003ca class=\"link\" href=\"/docs/18/datatype-pg-lsn.html\" title=\"8.20. pg_lsn Type\"\u003e\u003ccode class=\"type\"\u003epg_lsn\u003c/code\u003e\u003c/a\u003e. Values can be compared to calculate the volume of WAL data that separates them, so they are used to measure the progress of replication and recovery.\u003c/p\u003e\n\u003cp\u003eWAL files are stored in the directory \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e under the data directory, as a set of segment files, normally each 16 MB in size (but the size can be changed by altering the \u003ccode class=\"option\"\u003e--wal-segsize\u003c/code\u003e \u003cspan class=\"application\"\u003einitdb\u003c/span\u003e option). Each segment is divided into pages, normally 8 kB each (this size can be changed via the \u003ccode class=\"option\"\u003e--with-wal-blocksize\u003c/code\u003e configure option). The WAL record headers are described in \u003ccode class=\"filename\"\u003eaccess/xlogrecord.h\u003c/code\u003e; the record content is dependent on the type of event that is being logged. Segment files are given ever-increasing numbers as names, starting at \u003ccode class=\"filename\"\u003e000000010000000000000001\u003c/code\u003e. The numbers do not wrap, but it will take a very, very long time to exhaust the available stock of numbers.\u003c/p\u003e\n\u003cp\u003eIt is advantageous if the WAL is located on a different disk from the main database files. This can be achieved by moving the \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e directory to another location (while the server is shut down, of course) and creating a symbolic link from the original location in the main data directory to the new location.\u003c/p\u003e\n\u003cp\u003eThe aim of WAL is to ensure that the log is written before database records are altered, but this can be subverted by disk drives that falsely report a successful write to the kernel, when in fact they have only cached the data and not yet stored it on the disk. A power failure in such a situation might lead to irrecoverable data corruption. Administrators should try to ensure that disks holding \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e's WAL files do not make such false reports. (See \u003ca class=\"xref\" href=\"/docs/18/wal-reliability.html\" title=\"28.1. Reliability\"\u003eSection 28.1\u003c/a\u003e.)\u003c/p\u003e\n\u003cp\u003eAfter a checkpoint has been made and the WAL flushed, the checkpoint's position is saved in the file \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e. Therefore, at the start of recovery, the server first reads \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e and then the checkpoint record; then it performs the REDO operation by scanning forward from the WAL location indicated in the checkpoint record. Because the entire content of data pages is saved in the WAL on the first page modification after a checkpoint (assuming \u003ca class=\"xref\" href=\"/docs/18/runtime-config-wal.html#GUC-FULL-PAGE-WRITES\"\u003efull_page_writes\u003c/a\u003e is not disabled), all pages changed since the checkpoint will be restored to a consistent state.\u003c/p\u003e\n\u003cp\u003eTo deal with the case where \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e is corrupt, we should support the possibility of scanning existing WAL segments in reverse order — newest to oldest — in order to find the latest checkpoint. This has not been implemented yet. \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e is small enough (less than one disk page) that it is not subject to partial-write problems, and as of this writing there have been no reports of database failures due solely to the inability to read \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e itself. So while it is theoretically a weak spot, \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e does not seem to be a problem in practice.\u003c/p\u003e\n\u003c/div\u003e","manual_path":"/docs/18/wal-internals.html","related":[{"label":"Table AM","url":"/wiki/tableam/?v=18"},{"label":"Storage Parameters","url":"/wiki/relopts/?v=18"}],"release":{"channel":"stable","label":"18.6","major":"18","ref":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"},"sections":[],"sections_zh":[],"signature":"","sources":[{"label":"PostgreSQL 18 English manual","path":"wal-internals.html","sha256":"81c125b1657049ba0b146e15b1decb82aa524ac54df1add0b07e154d95f3f300","url":"/docs/18/wal-internals.html"}],"tables":[],"tables_zh":[],"zh_from":{"authored_translation":"source-derived-identity","body_sha256":"9ac2159e018e63e6c39a376a35f072e8b93a1cbce8faf79cbe8015eba1275a14","kind":"same-version-chinese-manual-with-source-derived-identity","manual":{"anchor":"","build_id":107,"extraction":"concept-introduction","fragment_sha256":"8455a6c0e0a7acaf68d56ea4c590a1512739ac8923b8e74f8c78950635b21f48","locale":"zh-Hans","page_key":"wal-internals.html","source_hash":"aa49da7337b89d6d213b58a08c640ec5af68b764fc70e19ecdafaf1e4e2f2241","source_revision":"unknown:rendered-translation-baseline","translated_from_revision":null,"translation_revision":"git:b1b500221dbe5437cfca004d6b04d3f6e422765d;html-sha256:08e987a66af27b98444a8057c256314eafa13611a3fb9e888214fc436824244b","url":"/zh/docs/18/wal-internals.html","version":"18"},"runtime_rerun":false,"source_facts_revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}},"ManualEvidence":{"manual_path":"/docs/18/wal-internals.html","release":{"channel":"stable","label":"18.6","major":"18","ref":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"},"sources":[{"label":"PostgreSQL 18 English manual","path":"wal-internals.html","sha256":"81c125b1657049ba0b146e15b1decb82aa524ac54df1add0b07e154d95f3f300","url":"/docs/18/wal-internals.html"}]},"MeasuredEvidence":{}},"Text":{"Collection":"storage","Key":"wal-internals","SourceDatabase":"center","Version":"18","Locale":"en","Title":"WAL Internals","Summary":"WAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see Section 28.5 ).","BodyHTML":"\u003cdiv\u003e\n\u003cdiv\u003e\n\u003cdiv\u003e\n\u003cdiv\u003e\n\u003ch2\u003e28.6. WAL Internals \u003c/h2\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cp\u003eWAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see \u003ca href=\"/docs/18/wal-configuration.html\" rel=\"nofollow\"\u003eSection 28.5\u003c/a\u003e).\u003c/p\u003e\n\u003cp\u003eWAL records are appended to the WAL files as each new record is written. The insert position is described by a Log Sequence Number (LSN) that is a byte offset into the WAL, increasing monotonically with each new record. LSN values are returned as the datatype \u003ca href=\"/docs/18/datatype-pg-lsn.html\" rel=\"nofollow\"\u003e\u003ccode\u003epg_lsn\u003c/code\u003e\u003c/a\u003e. Values can be compared to calculate the volume of WAL data that separates them, so they are used to measure the progress of replication and recovery.\u003c/p\u003e\n\u003cp\u003eWAL files are stored in the directory \u003ccode\u003epg_wal\u003c/code\u003e under the data directory, as a set of segment files, normally each 16 MB in size (but the size can be changed by altering the \u003ccode\u003e--wal-segsize\u003c/code\u003e \u003cspan\u003einitdb\u003c/span\u003e option). Each segment is divided into pages, normally 8 kB each (this size can be changed via the \u003ccode\u003e--with-wal-blocksize\u003c/code\u003e configure option). The WAL record headers are described in \u003ccode\u003eaccess/xlogrecord.h\u003c/code\u003e; the record content is dependent on the type of event that is being logged. Segment files are given ever-increasing numbers as names, starting at \u003ccode\u003e000000010000000000000001\u003c/code\u003e. The numbers do not wrap, but it will take a very, very long time to exhaust the available stock of numbers.\u003c/p\u003e\n\u003cp\u003eIt is advantageous if the WAL is located on a different disk from the main database files. This can be achieved by moving the \u003ccode\u003epg_wal\u003c/code\u003e directory to another location (while the server is shut down, of course) and creating a symbolic link from the original location in the main data directory to the new location.\u003c/p\u003e\n\u003cp\u003eThe aim of WAL is to ensure that the log is written before database records are altered, but this can be subverted by disk drives that falsely report a successful write to the kernel, when in fact they have only cached the data and not yet stored it on the disk. A power failure in such a situation might lead to irrecoverable data corruption. Administrators should try to ensure that disks holding \u003cspan\u003ePostgreSQL\u003c/span\u003e\u0026#39;s WAL files do not make such false reports. (See \u003ca href=\"/docs/18/wal-reliability.html\" rel=\"nofollow\"\u003eSection 28.1\u003c/a\u003e.)\u003c/p\u003e\n\u003cp\u003eAfter a checkpoint has been made and the WAL flushed, the checkpoint\u0026#39;s position is saved in the file \u003ccode\u003epg_control\u003c/code\u003e. Therefore, at the start of recovery, the server first reads \u003ccode\u003epg_control\u003c/code\u003e and then the checkpoint record; then it performs the REDO operation by scanning forward from the WAL location indicated in the checkpoint record. Because the entire content of data pages is saved in the WAL on the first page modification after a checkpoint (assuming \u003ca href=\"/docs/18/runtime-config-wal.html#GUC-FULL-PAGE-WRITES\" rel=\"nofollow\"\u003efull_page_writes\u003c/a\u003e is not disabled), all pages changed since the checkpoint will be restored to a consistent state.\u003c/p\u003e\n\u003cp\u003eTo deal with the case where \u003ccode\u003epg_control\u003c/code\u003e is corrupt, we should support the possibility of scanning existing WAL segments in reverse order — newest to oldest — in order to find the latest checkpoint. This has not been implemented yet. \u003ccode\u003epg_control\u003c/code\u003e is small enough (less than one disk page) that it is not subject to partial-write problems, and as of this writing there have been no reports of database failures due solely to the inability to read \u003ccode\u003epg_control\u003c/code\u003e itself. So while it is theoretically a weak spot, \u003ccode\u003epg_control\u003c/code\u003e does not seem to be a problem in practice.\u003c/p\u003e\n\u003c/div\u003e","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","ContentHash":"298696d6cee55d34b97c3f49f8693731a605ca843a13691a3c8a1c30dc961f81","Payload":{"description":["WAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see Section 28.5 )."],"manual_html":"\u003cdiv class=\"sect1\"\u003e\n\u003cdiv class=\"titlepage\"\u003e\n\u003cdiv\u003e\n\u003cdiv\u003e\n\u003ch2 class=\"title\"\u003e28.6. WAL Internals \u003c/h2\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cp\u003eWAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see \u003ca class=\"xref\" href=\"/docs/18/wal-configuration.html\" title=\"28.5. WAL Configuration\"\u003eSection 28.5\u003c/a\u003e).\u003c/p\u003e\n\u003cp\u003eWAL records are appended to the WAL files as each new record is written. The insert position is described by a Log Sequence Number (LSN) that is a byte offset into the WAL, increasing monotonically with each new record. LSN values are returned as the datatype \u003ca class=\"link\" href=\"/docs/18/datatype-pg-lsn.html\" title=\"8.20. pg_lsn Type\"\u003e\u003ccode class=\"type\"\u003epg_lsn\u003c/code\u003e\u003c/a\u003e. Values can be compared to calculate the volume of WAL data that separates them, so they are used to measure the progress of replication and recovery.\u003c/p\u003e\n\u003cp\u003eWAL files are stored in the directory \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e under the data directory, as a set of segment files, normally each 16 MB in size (but the size can be changed by altering the \u003ccode class=\"option\"\u003e--wal-segsize\u003c/code\u003e \u003cspan class=\"application\"\u003einitdb\u003c/span\u003e option). Each segment is divided into pages, normally 8 kB each (this size can be changed via the \u003ccode class=\"option\"\u003e--with-wal-blocksize\u003c/code\u003e configure option). The WAL record headers are described in \u003ccode class=\"filename\"\u003eaccess/xlogrecord.h\u003c/code\u003e; the record content is dependent on the type of event that is being logged. Segment files are given ever-increasing numbers as names, starting at \u003ccode class=\"filename\"\u003e000000010000000000000001\u003c/code\u003e. The numbers do not wrap, but it will take a very, very long time to exhaust the available stock of numbers.\u003c/p\u003e\n\u003cp\u003eIt is advantageous if the WAL is located on a different disk from the main database files. This can be achieved by moving the \u003ccode class=\"filename\"\u003epg_wal\u003c/code\u003e directory to another location (while the server is shut down, of course) and creating a symbolic link from the original location in the main data directory to the new location.\u003c/p\u003e\n\u003cp\u003eThe aim of WAL is to ensure that the log is written before database records are altered, but this can be subverted by disk drives that falsely report a successful write to the kernel, when in fact they have only cached the data and not yet stored it on the disk. A power failure in such a situation might lead to irrecoverable data corruption. Administrators should try to ensure that disks holding \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e's WAL files do not make such false reports. (See \u003ca class=\"xref\" href=\"/docs/18/wal-reliability.html\" title=\"28.1. Reliability\"\u003eSection 28.1\u003c/a\u003e.)\u003c/p\u003e\n\u003cp\u003eAfter a checkpoint has been made and the WAL flushed, the checkpoint's position is saved in the file \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e. Therefore, at the start of recovery, the server first reads \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e and then the checkpoint record; then it performs the REDO operation by scanning forward from the WAL location indicated in the checkpoint record. Because the entire content of data pages is saved in the WAL on the first page modification after a checkpoint (assuming \u003ca class=\"xref\" href=\"/docs/18/runtime-config-wal.html#GUC-FULL-PAGE-WRITES\"\u003efull_page_writes\u003c/a\u003e is not disabled), all pages changed since the checkpoint will be restored to a consistent state.\u003c/p\u003e\n\u003cp\u003eTo deal with the case where \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e is corrupt, we should support the possibility of scanning existing WAL segments in reverse order — newest to oldest — in order to find the latest checkpoint. This has not been implemented yet. \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e is small enough (less than one disk page) that it is not subject to partial-write problems, and as of this writing there have been no reports of database failures due solely to the inability to read \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e itself. So while it is theoretically a weak spot, \u003ccode class=\"filename\"\u003epg_control\u003c/code\u003e does not seem to be a problem in practice.\u003c/p\u003e\n\u003c/div\u003e","related":[{"label":"Table AM","url":"/wiki/tableam/?v=18"},{"label":"Storage Parameters","url":"/wiki/relopts/?v=18"}],"sections":[],"tables":[]}},"RequestedLocale":"en","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
