9.3 9.4 9.5 9.6 10 11 12 13 14 Current(15)
阿里云PostgreSQL 问题报告 纠错本页面

27.4. 热备

27.4.1. 用户概览
27.4.2. 处理查询冲突
27.4.3. 管理员概览
27.4.4. 热备参数参考
27.4.5. 警告

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

在热备模式中运行查询与正常查询操作相似,尽管如下所述存在一些用法和管理上的区别。

27.4.1. 用户概览

hot_standby参数在一台后备服务器上被设置为真时,一旦恢复将系统带到一个一致的状态它将开始接受连接。所有这些连接都被限制为只读,甚至临时表都不能被写入。

后备服务器上的数据需要一些时间从主服务器到达后备服务器,因此在主服务器和后备服务器之间将有一段可以度量的延迟。近乎同时在主服务器和后备服务器上运行相同的查询可能因此而返回不同的结果。我们说后备服务器上的数据与主服务器是最终一致的。一旦一个事务的提交记录在后备服务器上被重播,那个事务所作的修改将对后备服务器上所有新取得的快照可见。快照可以在每个查询或每个事务的开始时取得,这取决于当前的事务隔离级别。详见第 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语句的规则。

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

  • 简短默认形式的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总是为真并且不可以被改变。但是只要不尝试修改数据库,热备期间的连接工作起来更像其他数据库连接。如果发生故障转移或切换,该数据库将切换到正常处理模式。当服务器改变模式时会话将保持连接。一旦热备结束,它将可以发起读写事务(即使是一个在热备期间启动的会话)。

用户可以通过SHOW in_hot_standby来检查hot standby会话是否是活跃的 (在服务器版本 14 之前该参数in_hot_standby不存在。对于更早版本的服务器,可行的替代方法是 SHOW transaction_read_only。) 此外, 还有一些函数 (表 9.90) 允许用户访问有关备用服务器的信息。 它们允许您编写程序来识别数据库当前的状态。用于监控恢复进度, 或者您可以编写复杂的程序将数据库恢复到特定状态。

27.4.2. 处理查询冲突

主服务器和后备服务器在多方面都松散地连接在一起。主服务器上的动作将在后备服务器上产生效果。结果是在它们之间有潜在的负作用或冲突。最容易理解的冲突是性能:如果在主服务器上发生一次大数据量的载入,那么着将在后备服务器上产生一个相似的 WAL 记录流,因而后备服务器查询可能要竞争系统资源(例如 I/O)。

还有其他类型的冲突可能发生在热备份中。这些冲突是硬冲突,因为查询可能需要取消, 在某些情况下,会断开会话以解决这些冲突。用户提供了几种处理这些冲突的方法。冲突案例包括:

  • 在主服务器上获取Access Exclusive锁,包括显式的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 重播之间发生冲突的最常见原因是过早清除。正常地,PostgreSQL允许在没有事务需要看到旧行版本时对它们进行清除,这样可以保证根据 MVCC 规则的正确的数据可见性。不过,这个规则只能被应用于执行在主控机上的事务。因此有可能主控机上的清除会移除对一个后备服务器事务还可见的行版本。

有经验的用户应当注意行版本清除和行版本冻结都可能与后备查询冲突。即便在一个没有被更新或被删除行的表上运行一次手工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系统视图也包含汇总信息。

当 WAL 重放由于冲突而需要比deadlock_timeout更长时间时,用户可以控制是否打印日志消息。由参数 log_recovery_conflict_waits 控制。

27.4.3. 管理员概览

如果hot_standbypostgresql.conf中设置为on (默认值),并且存在一个standby.signal 文件,则服务器将以热备模式运行。 但是,热备连接可能需要一些时间才能被允许, 因为服务器在提供一致状态以供查询运行之前不会接受连接。 在此期间,试图连接的客户端将被拒绝并显示错误消息。 要确认服务器已启动,请从应用程序中循环尝试连接,或在服务器日志中查找以下消息:

LOG:  entering standby mode

... 然后一段时间后 ...

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

一致性信息每次在主服务器上的检查点时记录一次。 当在主服务器上设置wal_levelreplicalogical时, 不可能在读取期间启用热备。在以下条件同时存在时,达到一致状态也可能会延迟:

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

  • 非常长寿的写事务

如果您正在运行基于文件的日志传送(“温备”),您可能需要等待下一个WAL文件到达, 这可能与主服务器上的archive_timeout设置一样长。

设置几个参数可确定用于跟踪事务ID、锁和预备事务的共享内存大小。备用服务器上的设置必须大于或等于主服务器上的设置,以确保在恢复过程中不会耗尽共享内存。例如,如果主数据库正在执行预备事务,而备用数据库没有获取共享内存来跟踪预备事务,则备用数据库将无法继续恢复,直到配置更改。受影响的参数是:

  • max_connections

  • max_prepared_transactions

  • max_locks_per_transaction

  • max_wal_senders

  • max_worker_processes

确保这不是问题的可靠方法是使备用数据库上的这些参数的值等于或大于主数据库上的值。因此,如果您想增加这些值,您应该先更改备用服务器上的设置,然后再更改主服务器上的设置。相反,如果要减小这些值,则应先更改主服务器上的设置,然后再更改备用服务器上的设置。请记住,当一个备用数据库被提升时,它会成为后续备用数据库所需参数设置的新基准。因此,最好在所有备用服务器上保持这些设置相同,这样在切换/故障转移期间就不会出现问题。

WAL 跟踪主节点上这些参数的变化。如果热备处理一个 WAL,表明主节点当前值大于备用数据库上的值,它将记录一个警告并中止恢复。例如:

WARNING:由于参数设置不足,无法进行热备
详细信息:max_connections = 80 的设置低于主服务器上的设置,其值为 100。
LOG:恢复已暂停
详细信息:如果恢复未暂停,服务器将关闭。
提示:您可以在进行必要的配置更改后重新启动服务器。

此时,您应该更改备库设置并重新启动实例以继续恢复。如果备库不是热备,不兼容的参数更改将立即将其关闭而不会暂停。因为这样继续开机没有意义。

管理员为max_standby_archive_delaymax_standby_streaming_delay选择适当的设置很重要。最好的选择取决于业务的优先级。例如如果服务器主要的任务是作为高可用服务器,那么你将想要低延迟设置,甚至是零(尽管它是一个非常激进的设置)。如果后备服务器的任务是作为一个用于决策支持查询的额外服务器,那么将其最大延迟值设置为很多小时甚至 -1 (表示无限等待)可能都是可以接受的。

在主服务器上写出的事务状态 "hint bits" 是不被 WAL 记录的,因此后备服务器上的数据将可能重新写出该提示。这样,即使所有用户都是只读的,后备服务器仍将执行磁盘写操作;但数据值本身并没有发生改变。用户将仍写出大的排序临时文件并且重新生成 relcache 信息文件,这样在热备模式中数据库没有哪个部分是真正只读的。还要注意使用dblink模块写到远程数据库以及其他使用 PL 函数位于数据库之外的操作仍将可用,即使该事务是本地只读的。

在恢复模式期间,下列类型的管理命令是不被接受的:

  • 数据定义语言(DDL): e.g., CREATE INDEX

  • 特权和所有权: GRANT, REVOKE,

  • 维护命令: ANALYZE, VACUUM,CLUSTER, REINDEX

注意这些命令中的某些实际上在主服务器上的“只读”模式事务期间是被允许的。

结果是,你无法创建只存在于后备服务器上的额外索引以及统计信息。如果需要这些管理命令,它们应该在主服务器上被执行,并且最后那些改变将被传播到后备服务器。

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命令会被接受,然而它会执行一个重启点而不是一个新的检查点。

27.4.4. 热备参数参考

多个参数已经在第 27.4.2 节第 27.4.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就没有效果,然而当后备服务器变成主服务器时它将变得相关。

27.4.5. 警告

热备份有几个限制。 这些限制可能会在未来的版本中得到修复:

  • 在快照被拍摄之前,需要完全了解正在运行的事务。 使用大量子事务(目前大于64个)的事务将延迟只读连接的启动,直到最长运行的写事务完成。 如果出现这种情况,将向服务器日志发送解释性消息。

  • 在主服务器的每个检查点上生成热备份查询的有效起始点。 如果在主服务器处于关闭状态时关闭热备份,可能无法重新进入热备份状态,直到主服务器启动,以便在WAL日志中生成进一步的起始点。 在可能发生的最常见情况下,这种情况并不是问题。 通常,如果主服务器关闭并且不再可用,那很可能是由于需要将热备份转换为新主服务器的严重故障。在主服务器被有意关闭的情况下,协调确保热备份顺利成为新主服务器也是标准程序。

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

  • 热备份中尚不支持Serializable事务隔离级别。(有关详细信息,请参见第 13.2.3 节第 13.4.1 节。) 在热备份模式下尝试将事务设置为可串行化隔离级别将生成错误。