Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

26.4. 热备用 #

26.4.1. 用户概述
26.4.2. 处理查询冲突
26.4.3. 管理员概述
26.4.4. 热备用参数参考
26.4.5. 注意事项

热备用是用来描述在服务器处于存档恢复或备用模式时连接到服务器并运行只读查询的功能。这对于复制目的以及以极高精度恢复备份到所需状态都非常有用。术语热备用还指在用户继续运行查询和/或保持连接打开的情况下服务器能够从恢复模式转换到正常运行模式的功能。

在热备用模式下运行查询类似于正常的查询操作,但以下有几个用法和管理方面的差异。

26.4.1. 用户概述 #

当在备用服务器上将 hot_standby 参数设置为 true 时,在恢复使系统达到一致状态后,它将开始接受连接。所有此类连接都严格为只读;甚至不能写入临时表中。

备用服务器上的数据需要一些时间才能从主服务器上到达,因此在主服务器和备用服务器之间将存在可度量的延迟。因此,在主服务器和备用服务器上几乎同时运行相同的查询,可能会返回不同的结果。我们说备用服务器上的数据与主服务器的最终一致。一旦事务的提交记录在备用服务器上重新执行,则该事务所做的更改对在备用服务器上获取的任何新快照都可见。快照可能会在每个查询开始时或在每个事务开始时获取,具体取决于当前的事务隔离级别。更多详细信息,请参阅 第 13.2 节

在热备用期间启动的事务可以发出以下命令

  • 查询访问: SELECTCOPY TO

  • 游标命令: DECLAREFETCHCLOSE

  • 设置: SHOWSETRESET

  • 事务管理命令

    • BEGINENDABORTSTART TRANSACTION

    • SAVEPOINTRELEASEROLLBACK TO SAVEPOINT

    • EXCEPTION 块和其他内部子事务

  • LOCK TABLE,但仅在以下这些模式之一中时显式使用:ACCESS SHAREROW SHAREROW EXCLUSIVE

  • 计划和资源: PREPAREEXECUTEDEALLOCATEDISCARD

  • 插件和扩展: LOAD

  • UNLISTEN

在热备用期间启动的事务永远不会被分配事务 ID,且不能写入系统预写日志。因此,以下操作将生成错误消息

  • 数据操作语言 (DML): INSERTUPDATEDELETEMERGECOPY FROMTRUNCATE。请注意,没有任何已允许的操作会导致在恢复期间执行触发器。此限制甚至适用于临时表,因为无法在不分配事务 ID(目前在热备用环境中不可行)的情况下,读取或写入表行。

  • 数据定义语言 (DDL):CREATEDROPALTERCOMMENT。此限制甚至适用于临时表,因为执行这些操作需要更新系统目录表。

  • SELECT ... FOR SHARE | UPDATE,因为在不更新底层数据文件的情况下无法获取行锁。

  • 生成 DML 命令的 SELECT 语句的规则。

  • LOCK 显式请求高于 ROW EXCLUSIVE MODE 的模式。

  • LOCK 以短默认形式使用,因为它请求 ACCESS EXCLUSIVE MODE

  • 显式设置非只读状态的事务管理命令

    • BEGIN READ WRITESTART TRANSACTION READ WRITE

    • SET TRANSACTION READ WRITESET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE

    • SET transaction_read_only = off

  • 两阶段提交命令:PREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED,因为即使是只读事务也需要在准备阶段(两阶段提交的第一阶段)写入 WAL。

  • 序列更新:nextval()setval()

  • LISTENNOTIFY

在正常操作中,允许 只读 事务使用 LISTENNOTIFY,所以热备用会话操作的限制要比普通只读会话严格一些。这些限制中的部分内容在未来版本中可能有所放松。

在热备用期间,参数 transaction_read_only 始终为 true 并且可能不会更改。但是,只要不尝试修改数据库,热备用期间的连接的行为就与任何其他数据库连接非常相似。如果发生故障转移或切换,该数据库将切换到正常处理模式。在服务器切换模式时,会话将保持连接。热备用结束后,可以启动读写事务(即使是从热备用期间开始的会话也是如此)。

用户可以通过发出 SHOW in_hot_standby 命令来确定当前是否对热备用状态有效。(在 14 之前的服务器版本中,in_hot_standby 参数不存在;一种适用于旧服务器的可行替代方法是 SHOW transaction_read_only。)此外,一组函数(表 9.96)允许用户访问有关备用服务器的信息。这些函数可用来编写能感知数据库当前状态的程序。这些程序可用来监视恢复进度或用来编写将数据库恢复到特定状态的复杂程序。

26.4.2. 处理查询冲突 #

从很多方面来讲,主服务器和备用服务器都是松散相连的。在主服务器上的操作会对备用服务器产生影响。因此,两者之间可能会出现不良交互或冲突。最容易理解的冲突是性能:如果在主服务器上发生了巨大的数据加载,那么这将在备用服务器上生成类似的 WAL 记录流,因此备用服务器的查询可能会争夺系统资源,如 I/O。

使用热备用还可能会发生其他类型的冲突。这些冲突在如下意义上是 硬冲突,即可能需要取消查询,在某些情况下还可能断开会话以解决这些冲突。已为用户提供几种方法来处理这些冲突。冲突情况包括

  • 获取主服务器上的独占锁,包括显式的 LOCK 命令和各种DDL操作,会与备用服务器的查询中的表访问产生冲突。

  • 删除主服务器上的表空间会与使用该表空间作为临时工作文件的备用服务器查询产生冲突。

  • 删除主服务器上的数据库会与连接到备用服务器上该数据库的会话产生冲突。

  • 使用 WAL 中的真空清理记录与仍可以 查看 所有待删除行的备用服务器事务产生冲突。

  • 使用 WAL 中的真空清理记录与在备用服务器上访问目标页面的查询产生冲突,无论待删除的数据是否可见。

在主服务器上,这些情况只会导致等待;用户可以选择取消任何冲突操作。然而,在备用服务器上没有选择:WAL 记录的操作已在主服务器上发生,因此备用服务器必须应用它。此外,让 WAL 应用无限期等待可能非常不希望,这是因为备用服务器的状态将变得越来越落后于主服务器。因此,提供了一种机制来强制取消与要应用的 WAL 记录冲突的备用服务器查询。

问题情况的一个示例是主服务器上的管理员正在对备用服务器上当前正在查询的表运行DROP TABLE。如果DROP TABLE应用于备用服务器,则显然备用查询无法继续。如果此情况发生在主服务器上,则DROP TABLE将等待其他查询完成。但是,当DROP TABLE在主服务器上运行时,主服务器没有有关备用服务器上正在运行哪些查询的信息,因此它不会等待任何此类备用查询。WAL 更改记录在备用查询仍然运行时到达备用服务器,导致冲突。备用服务器必须延迟 WAL 记录(以及其后面的所有内容)的应用,否则取消冲突查询以便可以应用DROP TABLE

当发生冲突的查询较短时,通常需要允许它完成,通过稍稍延迟 WAL 应用;但通常不需要对 WAL 应用进行长延迟。因此,取消机制具有参数 max_standby_archive_delaymax_standby_streaming_delay,它们定义 WAL 应用中允许的最大延迟。一旦应用任何新接收的 WAL 数据的时间超过相关的延迟设置,将取消冲突查询。有两个参数,以便可以针对从存档读取 WAL 数据的情况(即从基础备份进行初始恢复或“赶上”落后很远的备用服务器)与通过流式复制读取 WAL 数据的情况指定不同的延迟值。

对于主要用于高可用性的备用服务器,最好将延迟参数设置得相对较短,以便服务器不会因备用查询引起的延迟而远远落后于主服务器。但是,如果备用服务器用于执行长时间运行的查询,则高延迟或甚至无限延迟值可能是更好的选择。但是,请记住,长时间运行的查询可能会导致备用服务器上的其他会话看不到主服务器上的最新更改,如果它延迟了 WAL 记录的应用。

一旦超出max_standby_archive_delaymax_standby_streaming_delay指定的延迟,将取消冲突查询。这通常只会导致取消错误,但对于重播DROP DATABASE的情况,将终止整个冲突会话。此外,如果冲突是由于空闲事务持有的锁,则冲突会话将终止(此行为将来可能会更改)。

取消的查询可以立即重试(当然在开始一个新事务之后)。由于查询取消取决于正在重新处理的 WAL 记录的性质,如果再次执行,已取消的查询很可能能够成功。

记住,延迟参数与备用服务器收到 WAL 数据以来的经过时间相比较。因此,对于备用服务器上的任何一个查询允许的宽限期绝不会超过延迟参数,而且如果备用服务器已经落后,或者因为等待前一查询完成而导致无法跟上较大的更新负载,则可能相当短。

备用查询与 WAL 重放之间发生冲突的最常见原因是 过早清理。通常,当不存在需要查看旧行版本的任何事务以按照 MVCC 规则确保数据的可见性正确性时,PostgreSQL 允许清理旧行版本。但是,这个规则仅适用于在主服务器上执行的事务。因此,有可能主服务器上的清理将删除对备用服务器上的某个事务仍然可见的行版本。

行版本清理并不是与备用查询发生冲突的唯一潜在原因。所有纯索引扫描(包括在备用服务器上运行的那些扫描)都必须使用一个MVCC与可见性映射“吻合”的快照。因此,每当 VACUUM 将一个页面设置为主可见性映射中的全部可见,并包含一行或多行对所有备用查询不可见时,都会需要发生冲突。因此,即使对一个没有需要清理的更新或已删除行运行 VACUUM,也可能导致发生冲突。

用户应该明确,在主服务器上定期且大量更新的表将很快导致备用服务器上的长时间运行查询取消。在这种情况下,可以将为 max_standby_archive_delaymax_standby_streaming_delay 设置一个有限值视为类似于设置 statement_timeout

如果对备用查询取消的数量感到不满,可以采取补救措施。第一个选项是设置参数 hot_standby_feedback,该参数会阻止 VACUUM 删除最近死的行,从而不发生清理冲突。如果您这样做,则应注意这会延迟主数据库中的死行清理,这可能会导致不良的表膨胀。ただし、这种情况不会比备用查询直接在主服务器上运行时更糟,并且您仍然可以从将执行卸载到备用服务器中受益。如果备用服务器频繁连接和断开,您可能希望进行调整以处理未提供 hot_standby_feedback 反馈的期间。例如,考虑增加 max_standby_archive_delay,以便在断开连接的时间段内,不再有 WAL 存档文件中的冲突来快速取消查询。您还应该考虑增加 max_standby_streaming_delay,以避免重新连接后新到达的流式 WAL 条目快速取消。

可以使用备用服务器上的 pg_stat_database_conflicts 系统视图查看查询取消的数量及其原因。 pg_stat_database 系统视图还包含摘要信息。

用户可以控制当 WAL 重放等待 deadlock_timeout 的时间过长出现冲突时是否会生成日志消息。这由 log_recovery_conflict_waits 参数控制。

26.4.3. 管理员概览 #

如果 hot_standbypostgresql.conf 中为 on (为默认值),且存在 standby.signal 文件,服务器将以热备用模式运行。ただし、热备用连接可能会需要一段时间才能允许,因为服务器会在完成足够的恢复以提供查询可以针对其运行的一致状态后才接受连接。在此期间,尝试连接的客户端将被拒绝,并出现错误消息。要确认服务器是否已启动,可以在应用程序中循环尝试连接,或在服务器日志中查找这些消息

LOG:  entering standby mode

... then some time later ...

LOG:  consistent recovery state reached
LOG:  database system is ready to accept read-only connections

一致性信息在主数据库中每个检查点记录一次。当读取在 wal_level 未设置为 replicalogical 的时间段内编写的 WAL 时,无法启用热备用模式。当出现这两种情况时,达到一致状态也可能会延迟

  • 写事务有超过 64 个子事务

  • 长期存在的写事务

如果您正在运行基于文件的日志传送(“热备用”),您可能需要等到下一个 WAL 文件到来,这可能会与主数据库上的 archive_timeout 设置一样长。

某些参数的设置决定了用于跟踪事务 ID、锁和准备事务的共享内存的大小。为了确保备用数据库在恢复期间不会用尽共享内存,备用数据库中的这些共享内存结构不能小于主数据库中的相应结构。例如,如果主数据库使用准备事务,而备用数据库未分配任何共享内存用于跟踪准备事务,则在更改备用数据库的配置前无法继续恢复。受影响的参数是

  • max_connections

  • max_prepared_transactions

  • max_locks_per_transaction

  • max_wal_senders

  • max_worker_processes

为了确保这不会成为问题,最简单的方法是将这些参数在备用数据库上设置为等于或大于主数据库上的值。因此,如果您想增加这些值,您应该先在所有备用服务器上进行操作,然后再对主服务器应用更改。相反,如果您想减少这些值,您应该先在主服务器上进行操作,然后再对所有备用服务器应用更改。记住,当备用数据库升级后,它会成为其后的备用数据库的所需参数设置的新参考。因此,为了避免在切换或故障转移期间造成此问题,建议在所有备用服务器上保持这些设置相同。

WAL 会在主数据库上跟踪这些参数的更改。如果热备用处理 WAL 表明主数据库上的当前值高于其自身的值,它将记录一条警告并暂停恢复,例如

WARNING:  hot standby is not possible because of insufficient parameter settings
DETAIL:  max_connections = 80 is a lower setting than on the primary server, where its value was 100.
LOG:  recovery has paused
DETAIL:  If recovery is unpaused, the server will shut down.
HINT:  You can then restart the server after making the necessary configuration changes.

在该时刻,需要更新备用数据库上的设置并重启实例,然后恢复才能继续。如果备用不是热备用,那么当它遇到不兼容的参数更改时,它将立即关闭而不会暂停,因为那时再保持运行毫无意义。

管理人员为 max_standby_archive_delaymax_standby_streaming_delay 选择适当的设置非常重要。具体的选择应基于业务优先事项。例如,如果服务器主要被用作高可用性服务器,您将希望设置较低的延迟,甚至可以是零,但这是一种非常激进的设置。如果备用服务器作为决策支持查询的附加服务器,则可以将最大延迟值设置为很多小时,甚至 -1(意味着一直等待查询完成)。

主要数据库上写入的事务状态“提示位”并未记录 WAL,因此备用数据库上的数据可能会在备用数据库上重新写入提示。因此,即使所有用户都是只读的,备用服务器仍将执行磁盘写入;数据值本身没有发生更改。用户仍将写入大型排序临时文件并重新生成 relcache 信息文件,因此在热备用模式期间,数据库没有任何部分真正处于只读状态。同样需要注意的是,即使事务在本地是只读的,也可以使用 dblink 模块对远程数据库进行写入,以及使用 PL 函数对数据库之外的其他操作进行写入。

在恢复模式期间,不会接受以下类型的管理命令

  • 数据定义语言 (DDL):例如,CREATE INDEX

  • 权限和所有权:GRANTREVOKEREASSIGN

  • 维护命令:ANALYZEVACUUMCLUSTERREINDEX

再次需要注意的是,事实上允许在主要数据库上处于“只读”模式的事务期间执行其中一些命令。

其结果是,您不能创建只存在于备用数据库上的其他索引,也不能创建只存在于备用数据库上的统计数据。如果需要这些管理命令,则应在主数据库上执行它们,并且最终这些更改将传播到备用数据库。

pg_cancel_backend()pg_terminate_backend() 将对用户后端有效,但对执行恢复的启动进程无效。 pg_stat_activity 不将正在恢复的事务显示为活动状态。因此,在恢复期间,pg_prepared_xacts 总为空。如果您想要解析有问题的准备好的事务,请在主数据库上查看 pg_prepared_xacts 并发布命令以在那里解析事务,或者在恢复结束之后解析事务。

pg_locks 将按正常状态显示后端持有的锁。 pg_locks 还会显示由启动进程管理的虚拟事务,该启动进程拥有正在由恢复重演的事务中的所有 AccessExclusiveLocks。需要注意的是,启动进程不会获取锁进行数据库更改,因此 AccessExclusiveLocks 之外的锁不会在启动进程的 pg_locks 中显示;它们只是被假定存在。

Nagios 插件 check_pgsql 将有效,因为它检查的是简单信息已经存在。 check_postgres 监控脚本也将有效,但一些报告的值可能会给出不同的或成疑问的结果。例如,上次真空时间不会被保留,因为备用数据库上不会发生真空。在主数据库上运行的真空仍会向备用数据库发送其更改。

WAL 文件控制命令在恢复过程中不可用,例如,pg_backup_startpg_switch_wal 等。

动态加载的模块可用,包括 pg_stat_statements

建议锁定在恢复过程中正常可用,包括死锁检测。请注意,建议锁定不会记录在 WAL 中,因此主服务器或备用服务器上的建议锁定不可能与 WAL 重放冲突。无法在主服务器上获取建议锁定,也无法在备用服务器上发起类似的建议锁定。建议锁仅与获取它们的服务器相关。

SlonyLondisteBucardo 等基于触发器的复制系统根本无法在备用服务器上运行,但只要更改内容不会发送到备用服务器以进行应用,它们就能在主服务器上正常运行。WAL 重放不是基于触发器的,因此无法从备用服务器中继到需要其他数据库写入或依赖于使用触发器的任何系统。

无法分配新的 OID,尽管某些UUID只要不依赖于向数据库写入新状态,生成器仍然可以使用。

目前,在只读事务中不允许创建临时表,因此在某些情况下现有的脚本无法正确运行。此限制可能会在以后的版本中放松。这既是 SQL 标准合规性问题,又是技术问题。

DROP TABLESPACE 只有在表空间为空时才能成功。某些备用服务器的用户可能会通过其 temp_tablespaces 参数主动使用该表空间。如果表空间中存在临时文件,则所有活动查询都将被取消,以确保删除临时文件,以便移除表空间并继续 WAL 重放。

在主服务器上运行 DROP DATABASEALTER DATABASE ... SET TABLESPACE 将生成一个 WAL 项,该表空间将使连接到备用服务器中该数据库的所有用户强制断开连接。此操作立即发生,无论 max_standby_streaming_delay 设置为何。请注意,ALTER DATABASE ... RENAME 不会断开用户连接,在大多数情况下这都不会被注意到,但在某些情况下,如果程序在某些方面依赖于数据库名称,可能会导致程序混乱。

在正常(非恢复)模式下,如果你向一个具有登录功能的角色发出 DROP USERDROP ROLE 命令,同时该用户仍然处于连接状态,那么已连接的用户不受影响 — 他们保持连接。但是用户无法重新连接。此行为也适用于恢复模式,因此在主服务器上的 DROP USER 不会断开备用服务器上的该用户连接。

累积统计信息系统在恢复过程中处于活动状态。备用服务器上将正常记录所有扫描、读取、块、索引使用等等。但是,WAL 重播不会递增与关系和数据库特定的计数器。即,重播不会递增 pg_stat_all_tables 列(如 n_tup_ins),启动进程执行的读取或写入也不会在 pg_statio_ 视图中进行跟踪,关联的 pg_stat_database 列也不会递增。

自动清理不会在恢复过程中处于活动状态。它将在恢复结束时正常启动。

检查点进程和后台写入器进程在恢复过程中处于活动状态。检查点进程将执行重启点(类似于主检查点),后台写入器进程将执行常规块清理活动。这可能包括在备用服务器上存储的提示位信息的更新。在恢复过程中接受 CHECKPOINT 命令,尽管它执行重启点而非新的检查点。

26.4.4. 热备用参数参考 #

上面在 第 26.4.2 节第 26.4.3 节 中提到了各种参数。

在主服务器上,可以使用 wal_level 参数。如果在主服务器上设置,max_standby_archive_delaymax_standby_streaming_delay 没有任何效果。

在备用服务器上,可以使用参数 hot_standbymax_standby_archive_delaymax_standby_streaming_delay

26.4.5. 注意事项 #

热备用有一些局限性。这些局限性可能会也可能会在将来的发行版中得到修复

  • 在拍摄快照之前需要了解所有运行中事务的详细情况。使用大量子事务(当前大于 64)的事务将延迟只读连接的启动时间,直到运行时间最长的写入事务完成为止。如果发生这种情况,解释性消息将发送到服务器日志。

  • 有效的备用查询起始点在主服务器的每个检查点都会生成。如果在主服务器处于关闭状态时备用服务器关闭,那么在主服务器启动之前,可能无法重新进入热备用状态,以便在 WAL 日志中生成更多的起始点。在可能发生这种情况的最常见情况下,此情况不是问题。通常,如果主服务器关闭并且不再可用,那可能是由于严重故障,要求将备用服务器转换以作为新主服务器以任何方式操作。并且在故意关闭主服务器的情况下,协调以确保备用服务器顺利成为新的主服务器也是标准程序。

  • 在恢复结束时,已准备事务持有的 AccessExclusiveLocks 将需要两倍于锁定表条目的正常数量。如果您计划同时运行大量通常采用 AccessExclusiveLocks 的已准备事务,或者您计划进行一次采用大量 AccessExclusiveLocks 的大事务,建议您选择较大的 max_locks_per_transaction 值,可能与主服务器上的参数值相同。如果您将 max_prepared_transactions 设置为 0,则无需考虑这一点。

  • 可串行化事务隔离级别在热备用状态中不可用。(请参阅第 13.2.3 节第 13.4.1 节 了解详情。)在热备用模式中尝试将事务设置为可串行化隔离级别将生成一个错误。