热备是指在服务器处于归档恢复或备用模式时,能够连接到服务器并运行只读查询的能力。这对于复制目的和将备份恢复到所需状态并具有很高的精度非常有用。热备还指服务器能够从恢复状态切换到正常运行状态,同时用户继续运行查询和/或保持连接打开。
在热备模式下运行查询类似于正常的查询操作,但存在一些使用和管理方面的差异,将在下面说明。
当在备用服务器上将 hot_standby 参数设置为 true 时,它将在恢复将系统带到一致状态后开始接受连接。所有此类连接都严格只读;即使是临时表也不能写入。
备用服务器上的数据需要一些时间从主服务器到达,因此主服务器和备用服务器之间将存在可衡量的延迟。因此,几乎同时在主服务器和备用服务器上运行相同的查询可能会返回不同的结果。我们说备用服务器上的数据与主服务器最终一致。一旦事务的提交记录在备用服务器上重播,该事务所做的更改将对备用服务器上所采取的任何新快照可见。快照可以在每个查询开始时或每个事务开始时采取,具体取决于当前的事务隔离级别。有关更多详细信息,请参阅第 13.2 节。
在热备期间启动的事务可以发出以下命令
查询访问:SELECT
, COPY TO
游标命令:DECLARE
, FETCH
, CLOSE
设置:SHOW
, SET
, RESET
事务管理命令
BEGIN
, END
, ABORT
, START TRANSACTION
SAVEPOINT
, RELEASE
, ROLLBACK TO SAVEPOINT
EXCEPTION
块和其他内部子事务
LOCK TABLE
,但前提是在以下模式之一中明确指定:ACCESS SHARE
, ROW SHARE
或 ROW EXCLUSIVE
。
计划和资源:PREPARE
, EXECUTE
, DEALLOCATE
, DISCARD
插件和扩展:LOAD
UNLISTEN
在热备期间启动的事务将永远不会分配事务 ID,并且不能写入系统预写日志。因此,以下操作将产生错误消息
数据操作语言 (DML):INSERT
, UPDATE
, DELETE
, MERGE
, COPY FROM
, TRUNCATE
。请注意,在恢复期间没有允许的操作会导致触发器执行。此限制甚至适用于临时表,因为在不分配事务 ID 的情况下无法读取或写入表行,而这在热备环境中目前是不可能的。
数据定义语言 (DDL):CREATE
, DROP
, ALTER
, COMMENT
。此限制甚至适用于临时表,因为执行这些操作将需要更新系统目录表。
SELECT ... FOR SHARE | UPDATE
,因为在不更新底层数据文件的情况下无法获取行锁。
关于生成 DML 命令的 SELECT
语句的规则。
LOCK
显式请求高于 ROW EXCLUSIVE MODE
的模式。
LOCK
以简短的默认形式,因为它请求 ACCESS EXCLUSIVE MODE
。
显式设置非只读状态的事务管理命令
BEGIN READ WRITE
, START TRANSACTION READ WRITE
SET TRANSACTION READ WRITE
, SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE
SET transaction_read_only = off
两阶段提交命令:PREPARE TRANSACTION
, COMMIT PREPARED
, ROLLBACK PREPARED
,因为即使是只读事务也需要在准备阶段(两阶段提交的第一阶段)写入 WAL。
序列更新:nextval()
, setval()
LISTEN
, NOTIFY
在正常操作中,“只读” 事务允许使用 LISTEN
和 NOTIFY
,因此热备会话的操作比普通只读会话的限制更严格。在将来的版本中,这些限制中的一些可能会放宽。
在热备期间,参数 transaction_read_only
始终为 true,并且不能更改。但只要不尝试修改数据库,热备期间的连接就会像任何其他数据库连接一样工作。如果发生故障转移或切换,数据库将切换到正常处理模式。会话将在服务器更改模式时保持连接。热备结束后,将能够启动读写事务(即使是从热备期间开始的会话)。
用户可以通过发出 SHOW in_hot_standby
来确定热备当前是否对他们的会话处于活动状态。(在 14 之前的服务器版本中,in_hot_standby
参数不存在;对于旧服务器,一个可行的替代方法是 SHOW transaction_read_only
。)此外,一组函数(表 9.96)允许用户访问有关备用服务器的信息。这些允许您编写能够感知数据库当前状态的程序。这些可用于监视恢复进度,或允许您编写将数据库恢复到特定状态的复杂程序。
主服务器和备用服务器在许多方面是松散连接的。主服务器上的操作将影响备用服务器。因此,它们之间可能存在负面互动或冲突。最容易理解的冲突是性能:如果主服务器上正在进行大量数据负载,那么这将在备用服务器上生成类似的 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_delay 和 max_standby_streaming_delay,用于定义 WAL 应用的最大允许延迟。当应用任何新接收的 WAL 数据花费的时间超过相关延迟设置时,将取消冲突查询。有两个参数,以便可以针对从存档读取 WAL 数据(即,从基本备份进行初始恢复或“追赶”已远远落后的备用服务器)与通过流式复制读取 WAL 数据的情况指定不同的延迟值。
在主要用于高可用的备用服务器中,最好将延迟参数设置得相对较短,这样服务器不会因备用查询导致的延迟而远远落后于主服务器。但是,如果备用服务器用于执行长时间运行的查询,那么较高的延迟值甚至无限的延迟值可能更可取。但是请记住,长时间运行的查询可能会导致备用服务器上的其他会话看不到主服务器上的最新更改,如果它延迟了 WAL 记录的应用。
一旦超过了max_standby_archive_delay
或 max_standby_streaming_delay
指定的延迟,冲突查询将被取消。这通常只会导致取消错误,尽管在重放DROP DATABASE
的情况下,整个冲突会话将被终止。此外,如果冲突是关于空闲事务持有的锁,则冲突会话将被终止(这种行为在未来可能会发生变化)。
取消的查询可以立即重试(当然,在开始新的事务后)。由于查询取消取决于正在重放的 WAL 记录的性质,因此如果再次执行被取消的查询,它很可能会成功。
请记住,延迟参数与备用服务器收到 WAL 数据后的经过时间进行比较。因此,备用服务器上任何一个查询的宽限期永远不会超过延迟参数,如果备用服务器由于等待之前的查询完成而已经落后,或者由于无法跟上繁重的更新负载而落后,则宽限期可能会大大减少。
备用查询与 WAL 重放之间冲突的最常见原因是“早期清理”。通常,PostgreSQL 允许在没有需要看到旧行版本的交易的情况下清理旧行版本,以确保根据 MVCC 规则正确显示数据。但是,此规则只能应用于在主服务器上执行的事务。因此,主服务器上的清理可能会删除备用服务器上的事务仍然可见的行版本。
行版本清理不是与备用查询冲突的唯一潜在原因。所有仅索引扫描(包括在备用服务器上运行的扫描)都必须使用MVCC快照,该快照与可见性映射“一致”。因此,每当VACUUM
将页面设置为可见性映射中的全可见 包含一个或多个行不 对所有备用查询可见时,都需要发生冲突。因此,即使对没有更新或删除行的表运行VACUUM
也可能导致冲突。
用户应该清楚地了解,在主服务器上定期和大量更新的表将很快导致备用服务器上长时间运行的查询被取消。在这种情况下,将max_standby_archive_delay
或 max_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 参数控制。
如果hot_standby
在postgresql.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
未在主服务器上设置为replica
或 logical
的期间写入的 WAL 时,无法启用热备用。在以下两种情况下,也可能会延迟到达一致状态
写入事务具有超过 64 个子事务
非常长期的写入事务
如果您正在运行基于文件的日志传送(“暖备用”),您可能需要等到下一个 WAL 文件到达,这可能需要长达主服务器上的archive_timeout
设置的时间。
某些参数的设置决定了用于跟踪事务 ID、锁和已准备事务的共享内存的大小。为了确保备用服务器在恢复期间不会用完共享内存,这些共享内存结构在备用服务器上必须不小于主服务器上的共享内存结构。例如,如果主服务器使用了已准备的事务,但备用服务器没有为跟踪已准备的事务分配任何共享内存,那么恢复将无法继续,直到更改备用服务器的配置。受影响的参数是
max_connections
max_prepared_transactions
max_locks_per_transaction
max_wal_senders
max_worker_processes
确保这不会成为问题的最简单方法是在备用服务器上将这些参数设置为等于或大于主服务器上的参数值。因此,如果要增加这些值,应先在所有备用服务器上进行,然后再将更改应用于主服务器。相反,如果要减小这些值,应先在主服务器上进行,然后再将更改应用于所有备用服务器。请记住,当备用服务器被提升时,它将成为其后备用服务器所需参数设置的新参考。因此,为了避免在切换或故障转移期间出现此问题,建议在所有备用服务器上保持这些设置相同。
WAL 跟踪主服务器上这些参数的更改。如果热备用服务器处理 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_delay 和 max_standby_streaming_delay 选择适当的设置非常重要。最佳选择因业务优先级而异。例如,如果服务器主要充当高可用性服务器,那么您将希望延迟设置较低,甚至为零,尽管这是一个非常激进的设置。如果备用服务器被用作决策支持查询的额外服务器,那么将最大延迟值设置为数小时甚至 -1(表示永远等待查询完成)可能是可以接受的。
在主服务器上写入的事务状态“提示位”不会被 WAL 记录,因此备用服务器上的数据可能会在备用服务器上重新写入提示。因此,即使所有用户都是只读的,备用服务器仍然会执行磁盘写入;数据值本身不会发生任何变化。用户仍然会写入大型排序临时文件并重新生成 relcache 信息文件,因此在热备用模式下,数据库的任何部分都不会真正成为只读的。另请注意,使用 dblink 模块写入远程数据库,以及使用 PL 函数在数据库之外进行的其他操作仍然是可能的,即使事务在本地是只读的。
以下类型的管理命令在恢复模式下不被接受
数据定义语言 (DDL):例如,CREATE INDEX
权限和所有权:GRANT
、REVOKE
、REASSIGN
维护命令: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_start
、pg_switch_wal
等。
动态加载模块可以正常工作,包括 pg_stat_statements
。
建议锁在恢复期间正常工作,包括死锁检测。请注意,建议锁从未写入 WAL 日志,因此主服务器或备用服务器上的建议锁不可能与 WAL 重放冲突。也不可能在主服务器上获取建议锁并使其在备用服务器上启动类似的建议锁。建议锁仅与获取它们的服务器相关。
基于触发器的复制系统,如 Slony、Londiste 和 Bucardo 根本不会在备用服务器上运行,尽管它们将在主服务器上正常运行,只要更改没有发送到备用服务器以应用。WAL 重放不是基于触发器的,因此您无法从备用服务器中继到任何需要额外数据库写入或依赖于触发器使用的系统。
无法分配新的 OID,尽管有些UUID生成器可能仍然有效,只要它们不依赖于将新状态写入数据库。
目前,在只读事务期间不允许创建临时表,因此在某些情况下,现有的脚本将无法正常运行。此限制可能在以后的版本中放宽。这是一个 SQL 标准合规性问题和一个技术问题。
DROP TABLESPACE
只能在表空间为空的情况下成功。一些备用用户可能正在通过其 temp_tablespaces
参数主动使用表空间。如果表空间中存在临时文件,所有活动查询将被取消以确保临时文件被删除,以便可以删除表空间并继续 WAL 重放。
在主服务器上运行 DROP DATABASE
或 ALTER DATABASE ... SET TABLESPACE
将生成一个 WAL 条目,该条目将导致连接到该数据库的所有备用用户被强制断开连接。此操作将立即发生,无论 max_standby_streaming_delay
的设置如何。请注意,ALTER DATABASE ... RENAME
不会断开用户的连接,这在大多数情况下将不会被注意到,尽管在某些情况下可能会导致程序混淆,如果它以某种方式依赖于数据库名称。
在正常(非恢复)模式下,如果您为具有登录功能的角色发出 DROP USER
或 DROP ROLE
,而该用户仍处于连接状态,那么连接的用户将不会发生任何事情 - 他们将保持连接状态。但是,用户无法重新连接。此行为也适用于恢复,因此主服务器上的 DROP USER
不会断开备用服务器上的该用户连接。
累积统计系统在恢复期间处于活动状态。所有扫描、读取、块、索引使用等都将在备用服务器上正常记录。但是,WAL 重放不会增加关系和数据库特定的计数器。即重放不会增加 pg_stat_all_tables
列(如 n_tup_ins
),启动进程执行的读取或写入也不会在 pg_statio_
视图中跟踪,也不会增加相关的 pg_stat_database
列。
自动真空在恢复期间不处于活动状态。它将在恢复结束时正常启动。
检查点进程和后台写入进程在恢复期间处于活动状态。检查点进程将执行重启点(类似于主服务器上的检查点),后台写入进程将执行正常的块清理活动。这可能包括更新存储在备用服务器上的提示位信息。 CHECKPOINT
命令在恢复期间被接受,尽管它执行重启点而不是新的检查点。
上面在 第 26.4.2 节 和 第 26.4.3 节 中提到了各种参数。
在主服务器上,可以使用 wal_level 参数。如果在主服务器上设置 max_standby_archive_delay 和 max_standby_streaming_delay,则它们不会生效。
在备用服务器上,可以使用参数 hot_standby、max_standby_archive_delay 和 max_standby_streaming_delay。
热备用有一些限制。这些问题将在未来的版本中得到修复,而且可能会修复。
在进行快照之前,需要了解正在运行的事务的完整信息。使用大量子事务的事务(目前超过 64 个)将延迟只读连接的启动,直到最长运行的写入事务完成。如果出现这种情况,将向服务器日志发送解释性消息。
在主服务器上的每个检查点都会生成备用查询的有效起点。如果备用服务器在主服务器处于关闭状态时关闭,则在主服务器启动之前可能无法重新进入热备用状态,以便它在 WAL 日志中生成更多起点。这种情况在最常见的可能发生的情况下不是问题。通常,如果主服务器关闭并且不再可用,那很可能是由于需要将备用服务器转换为作为新主服务器运行的严重故障。在主服务器被有意关闭的情况下,协调以确保备用服务器平稳地成为新主服务器也是标准程序。
在恢复结束时,准备好的事务持有的 AccessExclusiveLocks
将需要两倍于正常数量的锁表条目。如果您计划运行大量并发准备好的事务,这些事务通常会获取 AccessExclusiveLocks
,或者您计划进行一个获取大量 AccessExclusiveLocks
的大型事务,建议您选择一个更大的 max_locks_per_transaction
值,可能高达主服务器上参数值的两倍。如果您的 max_prepared_transactions
设置为 0,则根本不需要考虑这一点。
可序列化事务隔离级别在热备用中尚不可用。(有关详细信息,请参见 第 13.2.3 节 和 第 13.4.1 节。)尝试在热备用模式下将事务设置为可序列化隔离级别将生成错误。
如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表格 报告文档问题。