26.5. 热备

热备用是一个术语,用于描述在服务器处于归档恢复或待机模式时连接到服务器并运行只读查询的功能。这对于复制目的以及将备份还原到所需状态都非常有用。术语“热备用”还指服务器在用户 continue 运行查询和/或保持其连接打开时从恢复状态过渡到正常操作的能力。

在热备用模式下运行查询与普通查询操作相似,尽管下面会解释几种用法和 Management 上的区别。

26 .5.1. 用户概述

在备用服务器上将hot_standby参数设置为 true 时,一旦恢复使系统进入一致状态,它将开始接受连接。所有这些连接都是严格只读的;甚至不能写入临时表。

备用服务器上的数据需要花费一些时间才能从主服务器到达,因此主服务器和备用服务器之间会有可测量的延迟。因此,在主数据库和备用数据库上几乎同时运行同一查询可能会返回不同的结果。我们说备用数据库上的数据最终与主数据库一致。一旦在备用数据库上重放事务的提交记录,该事务所做的更改将对在备用数据库上拍摄的所有新快照可见。根据当前事务隔离级别,可以在每个查询的开始或每个事务的开始拍摄快照。有关更多详细信息,请参见Section 13.2

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

  • 查询访问权限-SELECTCOPY TO

  • 光标命令-DECLAREFETCHCLOSE

  • 参数-SHOWSETRESET

  • TransactionManagement 命令

  • BEGIN , END , ABORT , START TRANSACTION

    • SAVEPOINT , RELEASE , ROLLBACK TO SAVEPOINT

    • EXCEPTION块和其他内部子 Transaction

  • LOCK TABLE,尽管仅在以下两种模式之一中明确使用时:ACCESS SHAREROW SHAREROW EXCLUSIVE

  • 计划和资源-PREPAREEXECUTEDEALLOCATEDISCARD

  • 插件和 extensions-LOAD

  • UNLISTEN

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

  • 数据操作语言(DML)-INSERTUPDATEDELETECOPY FROMTRUNCATE。请注意,没有允许导致恢复期间执行触发器的动作。此限制甚至适用于临时表,因为如果不分配事务 ID 则无法读取或写入表行,这在当前的热备环境中是不可能的。

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

  • SELECT ... FOR SHARE | UPDATE,因为如果不更新基础数据文件就无法获取行锁。

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

  • LOCK明确要求高于ROW EXCLUSIVE MODE的模式。

  • LOCK为简写的默认格式,因为它请求ACCESS EXCLUSIVE MODE

  • 显式设置非只读状态的事务 Management 命令:

  • BEGIN READ WRITE , START TRANSACTION READ WRITE

    • SET TRANSACTION READ WRITE , SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE

    • SET transaction_read_only = off

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

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

  • LISTEN , NOTIFY

在正常操作中,允许“只读”事务使用LISTENNOTIFY,因此热备会话在比普通只读会话更严格的限制下运行。这些限制中的某些限制可能会在将来的版本中放宽。

在热备用期间,参数transaction_read_only始终为 true,并且不能更改。但是,只要不尝试修改数据库,热备用期间的连接就会像其他任何数据库连接一样工作。如果发生故障转移或切换,数据库将切换到正常处理模式。服务器更改模式时,会话将保持连接状态。一旦热备份完成,就可以启动读写事务(即使从热备份期间开始的会话开始)。

用户可以通过发出SHOW transaction_read_only来告知其会话是否为只读。另外,一组功能(Table 9.80)允许用户访问有关备用服务器的信息。这些使您可以编写了解数据库当前状态的程序。这些可用于监视恢复进度,或允许您编写将数据库恢复到特定状态的复杂程序。

26 .5.2. 处理查询冲突

主服务器和备用服务器在许多方面都是松散连接的。对主数据库的操作将对备用数据库产生影响。结果,它们之间可能存在负面互动或冲突。最容易理解的冲突是性能:如果主数据库上的数据负载很大,那么这将在备用数据库上生成类似的 WAL 记录流,因此备用数据库查询可能会争用系统资源,例如 I/O。

热备份还会发生其他类型的冲突。从某种意义上说,这些冲突是“硬冲突”,即可能需要取消查询,并且在某些情况下,会话需要断开连接才能解决它们。为用户提供了处理这些冲突的几种方法。冲突案件包括:

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

  • 在主数据库上删除表空间与将临时工作文件用于该表空间的备用查询冲突。

  • 在主数据库上删除数据库与在备用数据库上连接到该数据库的会话冲突。

  • 来自 WAL 的真空清除记录的应用与备用事务冲突,这些事务的快照仍可以“查看”要删除的任何行。

  • 来自 WAL 的真空清除记录的应用与访问备用数据库上的目标页面的查询冲突,无论是否可见要删除的数据。

在主服务器上,这些情况仅导致 await。并且用户可以选择取消这两个冲突的操作。但是,在备用数据库上别无选择:在主数据库上已经发生 WAL 记录的操作,因此备用数据库一定不能失败。此外,允许 WAL 应用程序无限期地 await 可能是非常不希望的,因为备用数据库的状态将越来越远地落后于主要数据库。因此,提供了一种机制来强制取消与待应用的 WAL 记录冲突的备用查询。

问题情况的一个示例是主服务器上的 Management 员在当前正在备用服务器上查询的表上运行DROP TABLE的主服务器上。显然,如果将DROP TABLE应用于备用数据库,备用数据库查询将无法 continue。如果在主服务器上发生这种情况,则DROP TABLE将等到另一个查询完成。但是,当DROP TABLE在主数据库上运行时,主数据库没有有关在备用数据库上运行哪些查询的信息,因此它不会 await 任何此类备用数据库查询。在备用查询仍在运行时,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 数据以来经过的时间进行比较。因此,备用数据库上任何一个查询所允许的宽限期都不会超过 delay 参数,如果备用数据库由于 await 先前查询完成或由于之前查询的完成而已经落后,则宽限期可能会大大减少。无法跟上繁重的更新工作。

备用查询和 WAL 重播之间发生冲突的最常见原因是“早期清理”。通常,当没有事务需要查看旧行版本以确保根据 MVCC 规则正确显示数据时,PostgreSQL 允许清除旧行版本。但是,此规则仅适用于在主服务器上执行的事务。因此,有可能主服务器上的清理将删除备用服务器上的事务仍可见的行版本。

有经验的用户应注意,行版本清除和行版本冻结都可能与备用查询冲突。即使在没有更新或删除的行的表上运行手册VACUUM FREEZE也可能导致冲突。

用户应清楚了解,在主服务器上定期且进行大量更新的表将迅速导致取消备用数据库上运行时间较长的查询。在这种情况下,可以将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 条目快速取消。

另一种选择是在主服务器上增加vacuum_defer_cleanup_age,这样就不会像平常一样迅速清理死行。这将使查询有更多时间在备用数据库上取消之前执行,而不必设置较高的max_standby_streaming_delay。但是,用这种方法很难保证任何特定的执行时间窗口,因为vacuum_defer_cleanup_age是在主服务器上执行的事务中度量的。

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

26 .5.3. Management 员概述

如果postgresql.conf中的hot_standbyon(默认值),并且存在recovery.conf文件,则服务器将在热备模式下运行。但是,允许热备连接可能要花费一些时间,因为服务器将不接受连接,直到服务器完成足够的恢复以提供可以运行查询的一致状态为止。在此期间,尝试连接的 Client 端将被拒绝并显示一条错误消息。要确认服务器已启动,请循环尝试从应用程序进行连接,或者在服务器日志中查找以下消息:

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设置一样长。

如果备用数据库上的某些参数已更改,则需要重新配置。对于这些参数,备用数据库上的值必须等于或大于主数据库上的值。如果这些参数设置得不够高,则备用数据库将拒绝启动。然后可以提供更高的值,并且服务器重新启动以再次开始恢复。这些参数是:

  • max_connections

  • max_prepared_transactions

  • max_locks_per_transaction

  • max_worker_processes

Management 员必须为max_standby_archive_delaymax_standby_streaming_delay选择适当的设置,这一点很重要。最佳选择取决于业务优先级。例如,如果服务器主要被用作高可用性服务器,那么您将需要低延迟设置,甚至可能为零,尽管这是非常激进的设置。如果将备用服务器用作决策支持查询的其他服务器,则可以将最大延迟值设置为多个小时甚至为-1,这是可以接受的,这意味着永远 await 查询完成。

写在主数据库上的事务状态“提示位”未进行 WAL 记录,因此备用数据库上的数据很可能会再次在备用数据库上重写提示。因此,即使所有用户都是只读的,备用服务器仍将执行磁盘写操作。数据值本身没有变化。用户仍将编写大型的临时文件并重新生成 relcache 信息文件,因此在热备用模式下,数据库的任何部分都不是 true 的只读文件。还要注意,即使事务在本地是只读的,使用 dblink 模块写入远程数据库以及使用 PL 函数在数据库外部进行其他操作仍然可能。

在恢复模式下,不接受以下类型的 Management 命令:

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

  • 特权和所有权-GRANTREVOKEREASSIGN

  • 维护命令-ANALYZEVACUUMCLUSTERREINDEX

同样,请注意,在主服务器上的“只读”模式事务期间实际上允许使用其中一些命令。

因此,您无法创建仅在备用数据库上存在的其他索引,也不能创建仅在备用数据库上存在的统计信息。如果需要这些 Management 命令,则应在主数据库上执行这些命令,最终这些更改将传播到备用数据库。

pg_cancel_backend()pg_terminate_backend()将在用户后端上运行,但不适用于执行恢复的启动过程。 pg_stat_activity不显示正在恢复的事务处于活动状态。结果,pg_prepared_xacts在恢复期间始终为空。如果要解决不确定的准备好的事务,请在主要数据库上查看pg_prepared_xacts并发出命令以在那里解决事务或在恢复结束后解决它们。

pg_locks将正常显示后端持有的锁。 pg_locks还显示了由 Startup 进程 Management 的虚拟事务,该事务拥有由恢复重播的事务所有AccessExclusiveLocks。请注意,启动过程不会获取锁来进行数据库更改,因此对于pg_locks来说,启动过程不会显示AccessExclusiveLocks以外的其他锁。它们只是假定存在。

Nagios 插件 check_pgsql 将起作用,因为它检查的简单信息已存在。尽管某些报告的值可能给出不同或令人困惑的结果,但 check_postgres 监视脚本也将起作用。例如,由于在待机状态下不会发生真空,因此无法维持最后的真空时间。在主服务器上运行的吸尘器仍会将其更改发送到备用服务器。

WAL 文件控制命令在恢复期间将不起作用,例如pg_start_backuppg_switch_wal等。

可动态加载的模块可以工作,包括pg_stat_statements

咨询锁在恢复中可以正常工作,包括死锁检测。请注意,咨询锁定永远不会被 WAL 记录,因此主或备用咨询锁定都不可能与 WAL 重放冲突。也不可能在主服务器上获得建议锁定,而在备用服务器上启动类似的建议锁定。咨询锁仅与获取它们的服务器有关。

基于触发器的复制系统(例如 Slony,Londiste 和 Bucardo)根本不会在备用服务器上运行,尽管只要更改未发送到备用服务器以进行应用,它们就可以在主服务器上快乐地运行。 WAL 重播不是基于触发器的,因此您不能从备用数据库中继到需要更多数据库写操作或依赖触发器使用的任何系统。

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

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

DROP TABLESPACE仅在表空间为空时才能成功。一些备用用户可能通过其temp_tablespaces参数正在积极使用表空间。如果表空间中有临时文件,则将取消所有活动查询以确保删除了临时文件,因此可以删除表空间,并且 WAL 重播可以 continue。

在主数据库上运行DROP DATABASEALTER DATABASE ... SET TABLESPACE将生成 WAL 条目,该条目将导致与备用数据库上的该数据库连接的所有用户被强制断开连接。无论max_standby_streaming_delay的设置如何,此操作都会立即发生。请注意,ALTER DATABASE ... RENAME不会断开用户的连接,尽管在某些情况下如果它取决于数据库名称,则在某些情况下可能会引起程序混乱,因此ALTER DATABASE ... RENAME不会引起注意。

在正常(非恢复)模式下,如果在该用户仍处于连接状态时为具有登录功能的角色发出DROP USERDROP ROLE,则该连接的用户将没有任何反应-他们保持连接状态。但是,用户无法重新连接。此行为也适用于恢复,因此主数据库上的DROP USER不会断开备用数据库上的该用户的连接。

统计收集器在恢复期间处于活动状态。所有扫描,读取,块,索引使用情况等将正常记录在备用数据库上。重播的操作不会重复其对主操作的影响,因此重播插入将不会增加 pg_stat_user_tables 的 Inserts 列。恢复开始时会删除统计文件,因此主数据库和备用数据库的统计信息会有所不同;这被认为是功能,而不是错误。

恢复期间,自动真空功能无效。它会在恢复结束时正常启动。

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

26 .5.4. 热备参数参考

上面在Section 26.5.2Section 26.5.3中提到了各种参数。

在主数据库上,可以使用参数wal_levelvacuum_defer_cleanup_age。如果在主服务器上设置max_standby_archive_delaymax_standby_streaming_delay则无效。

在备用数据库上,可以使用参数hot_standbymax_standby_archive_delaymax_standby_streaming_delay。只要服务器保持待机模式,vacuum_defer_cleanup_age就没有任何作用,尽管如果备用服务器成为主服务器,它将变得很重要。

26.5.5. Caveats

热备有几个限制。这些可以并且可能会在将来的版本中修复:

  • 在获取快照之前,需要全面了解正在运行的事务。使用大量子事务(当前大于 64 个)的事务将延迟只读连接的启动,直到完成运行时间最长的写事务。如果发生这种情况,说明性消息将发送到服务器日志。

  • 备用查询的有效起点是在主服务器上的每个检查点生成的。如果在主服务器处于关闭状态时关闭了备用数据库,则在主数据库启动之前,可能无法重新进入热备状态,以便在 WAL 日志中生成更多起点。在可能发生的最常见情况下,这种情况不是问题。通常,如果主数据库已关闭且不再可用,则可能是由于严重故障而导致需要将备用数据库转换为仍作为新的主数据库运行。在有意拆除主要数据库的情况下,协调以确保备用数据库平稳地成为新的主要数据库也是标准程序。

  • 恢复结束时,准备好的事务持有的AccessExclusiveLocks将需要锁表条目的正常数量的两倍。如果您计划运行通常需要AccessExclusiveLocks的大量并发准备事务,或者计划有一个需要很多AccessExclusiveLocks的大型事务,则建议选择较大的max_locks_per_transaction值,可能是max_locks_per_transaction的两倍。主服务器上的参数。如果max_prepared_transactions的设置为 0,则完全不需要考虑这一点。

  • 可序列化事务隔离级别在热备用中尚不可用。 (有关详细信息,请参见Section 13.2.3Section 13.4.1。)尝试在热备用模式下将事务设置为可序列化的隔离级别将产生错误。