选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

文档 / SQL 命令 / 事务控制

SQL COMMAND · 事务控制

WAIT FOR

等待 WAL 达到目标 LSN

WAIT事务控制引入 19现存至 20 devel0 次语法变更

动词
WAIT
对象
FOR
引入版本
19
状态
现存
语法变更次数
0
手册小节数
5

本站手册 · 20 devel官方文档 ↗

版本轨迹

相对 PostgreSQL 19 语法未变,正文有更新。手册文件由 sql-wait-for.html 改为 sql-waitfor.html。

PostgreSQL 20 devel 尚未正式发布;本页来自对应手册快照,内容仍可能变化。

语法铁道图 PostgreSQL 20

沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。

WAIT FOR LSN ' lsn ' WITH ( option , )
option
MODE ' mode ' TIMEOUT ' timeout ' NO_THROW
mode
standby_replay standby_write standby_flush primary_flush

语法概要

WAIT FOR LSN 'lsn'
    [ WITH ( option [, ...] ) ]

其中 option 可以是:

    MODE 'mode'
    TIMEOUT 'timeout'
    NO_THROW

mode 可以是:

    standby_replay | standby_write | standby_flush | primary_flush

PostgreSQL 20 devel 手册 · 查看完整参考页

描述

等待直到根据指定的 mode 达到指定的 lsn, 该模式决定等待 WAL 被写入、刷盘还是重放。 如果没有指定 timeout,或者其值为零,则此命令会无限期等待 lsn

超时时会发出错误,除非在 WITH 子句中指定了 NO_THROW。 对于备库模式(standby_replaystandby_writestandby_flush),如果在达到 lsn 之前服务器被提升, 也会发出错误。如果指定了 NO_THROW,命令会返回一个状态字符串,而不是抛出错误。

可能的返回值是 successtimeoutnot in recovery

参数

lsn

指定要等待的目标 LSN

WITH ( option [, ...] )

此子句指定等待操作的可选参数。支持以下参数:

MODE 'mode'

指定要等待的 LSN 处理类型。如果未指定,默认值为 standby_replay。有效模式如下:

  • standby_replay:等待该 LSN 在备库上被重放(应用到数据库)。 成功完成后,pg_last_wal_replay_lsn() 将返回大于或等于目标 LSN 的值。 此模式只能在恢复期间使用。

  • standby_write:等待包含该 LSN 的 WAL 被写入备库磁盘, 但不一定已经刷盘。这比 standby_flush 更快,但持久性保证更弱, 因为数据可能仍在操作系统缓冲区中。备库上已有的 WAL(来自基础备份、 归档恢复或先前的流式传输)以及从主库新接收的 WAL 均可满足此条件。 此模式只能在恢复期间使用。

  • standby_flush:等待包含该 LSN 的 WAL 在备库上刷盘。 这提供了持久性保证,而无需等待 WAL 被应用。备库上已有的 WAL(来自基础备份、 归档恢复或先前的流式传输)以及从主库新接收的 WAL 均可满足此条件。 此模式只能在恢复期间使用。

  • primary_flush:等待包含该 LSN 的 WAL 在主库上刷盘。 成功完成后,pg_current_wal_flush_lsn() 将返回大于或等于目标 LSN 的值。 此模式只能在主库上使用(不能在恢复期间使用)。

TIMEOUT 'timeout'

在指定且 timeout 大于零时,命令会一直等待到 lsn 达到,或者直到指定的 timeout 到期为止。

timeout 可以给定为整数毫秒数。 也可以给定为字符串字面量,表示整数毫秒数,或者带单位的数值 (见 Section 19.1.1)。

NO_THROW

指定在超时或在主库上运行时不抛出错误。在这种情况下,可以从返回值中获取结果状态。

输出

success

此返回值表示已成功达到目标 lsn

timeout

此返回值表示在达到目标 lsn 之前发生了超时。

not in recovery

此返回值表示数据库服务器不处于恢复状态。 这可能意味着数据库服务器在接收到命令时并不处于恢复状态(即在主库上执行), 也可能意味着它在达到目标 lsn 之前被提升。 在提升的情况下,此状态表示发生了时间线变更,应用程序应重新评估目标 LSN 是否仍然适用。

备注

WAIT FOR 必须作为顶层命令执行。 它不能在函数、过程或 DO 块中执行。 它还要求不存在活动或已注册的快照,因此不能在必须保持此类快照处于活动状态的上下文中使用, 包括隔离级别高于 READ COMMITTED 的事务。

WAIT FOR 会根据指定的 mode 一直等待直到达到指定的 lsnstandby_replay 模式会等待该 LSN 被回放(应用到数据库), 这有助于在使用异步副本读取和主库写入时实现读己之写一致性。 standby_flush 模式会等待 WAL 在副本上刷入持久存储,或者等待备库上已有的 WAL 已被回放。 standby_write 模式会等待 WAL 被写入操作系统,或者已经回放;对于新接收的 WAL, 这比刷盘更快,但持久性保证更弱。 primary_flush 模式会等待 WAL 在主库上刷盘。 在所有情况下,最后一次修改的 LSN 应当存储在客户端应用程序一侧或连接池一侧。

备库模式(standby_replaystandby_writestandby_flush)只能在恢复期间使用,而 primary_flush 只能在主库上使用。对当前服务器状态使用错误的模式会导致错误。 如果在使用备库模式等待期间备库被提升,命令将返回 not in recovery(或者在未指定 NO_THROW 时抛出错误)。提升会创建新的时间线,而正在等待的 LSN 可能指向旧时间线中的 WAL。

WAIT FOR只比较LSN数值;它并不知道 WAL 记录属于哪条时间线。 当备库跨上游时间线切换继续恢复时,这一点很重要—例如,级联备库的上游被提升。 在这种情况下,只要所选等待模式使用的位置达到或超过该LSN数值, WAIT FOR就会返回success,而不考虑该 LSN属于哪条时间线。需要确认目标指向预期时间线的应用程序必须自行验证时间线。

在备库服务器上,WAIT FOR 会话可能会被恢复冲突中断。 某些恢复冲突是不可避免的:例如,回放一个表空间删除操作时,无论后端正在执行什么,都会通过终止所有后端来解决冲突。 在备库上使用 WAIT FOR 的应用程序应准备好处理此类中断,例如通过重试命令或回退到其他机制。

示例

可以使用 WAIT FOR 命令等待 pg_lsn 值。 例如,应用程序可以更新 movie 表,并在刚刚完成更改后获取 lsn。 由于 synchronous_commit 可能设置为 off,此示例在主库上使用 pg_current_wal_insert_lsn 获取 lsn

postgres=# UPDATE movie SET genre = 'Dramatic' WHERE genre = 'Drama';
UPDATE 100
postgres=# SELECT pg_current_wal_insert_lsn();
 pg_current_wal_insert_lsn
---------------------------
 0/0306EE20
(1 row)

然后,应用程序可以使用从主库获得的 lsn 运行 WAIT FOR。 之后,主库上所做的更改应当保证在副本上可见。

postgres=# WAIT FOR LSN '0/0306EE20';
 status
---------
 success
(1 row)
postgres=# SELECT * FROM movie WHERE genre = 'Drama';
 genre
-------
(0 rows)

等待刷盘(数据在副本上持久化):

postgres=# WAIT FOR LSN '0/0306EE20' WITH (MODE 'standby_flush');
 status
---------
 success
(1 row)

带超时的等待写入:

postgres=# WAIT FOR LSN '0/0306EE20' WITH (MODE 'standby_write', TIMEOUT '100ms', NO_THROW);
 status
---------
 success
(1 row)

等待主库刷盘:

postgres=# WAIT FOR LSN '0/0306EE20' WITH (MODE 'primary_flush');
 status
---------
 success
(1 row)

如果在超时之前未达到目标 LSN,则会抛出错误:

postgres=# WAIT FOR LSN '0/0306EE20' WITH (TIMEOUT '0.1s');
ERROR:  timed out while waiting for target LSN 0/0306EE20 to be replayed; current standby_replay LSN 0/0306EA60

同一个示例使用带 NO_THROW 选项的 WAIT FOR

postgres=# WAIT FOR LSN '0/0306EE20' WITH (TIMEOUT '100ms', NO_THROW);
 status
---------
 timeout
(1 row)

语法演化

相邻大版本之间的差异,新的在前。版本号链接到对应快照。

  1. PostgreSQL 20← 19文件改名

    sql-wait-for.html → sql-waitfor.html

    正文更新
  2. PostgreSQL 19← 18新增此命令

同组命令

命令动词对象版本变动最近变更
TRANSACTIONS事务控制15 条
ABORTABORT 121 次
中止当前事务现存
BEGINBEGIN
开始一个事务块现存
COMMITCOMMIT 121 次
提交当前事务现存
ENDEND 121 次
提交当前事务现存
ROLLBACKROLLBACK 121 次
中止当前事务现存
SAVEPOINTSAVEPOINT
在当前事务中定义一个新的保存点现存
SET CONSTRAINTSSETCONSTRAINTS
为当前事务设置约束检查时机现存
WAIT FORWAITFOR
等待 WAL 达到目标 LSN现存
COMMIT PREPAREDCOMMITPREPARED
提交一个先前为两阶段提交而预备的事务现存
ROLLBACK PREPAREDROLLBACKPREPARED
回滚一个先前为两阶段提交而预备的事务现存
RELEASE SAVEPOINTRELEASESAVEPOINT
释放一个先前定义的保存点现存
ROLLBACK TO SAVEPOINTROLLBACKTO SAVEPOINT
回滚到一个保存点现存
PREPARE TRANSACTIONPREPARETRANSACTION
为两阶段提交准备当前事务现存
SET TRANSACTIONSETTRANSACTION
设置当前事务的特性现存
START TRANSACTIONSTARTTRANSACTION
开始一个事务块现存

本站手册收录版本:19 beta 3 20 devel

内容来自本站 PostgreSQL 手册译文,最后同步 2026-09-15。

译文问题请提交到 pgsty/pgdoc;本站展示或功能问题请提交到 pgsty/pgweb