diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
commit | 293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch) | |
tree | fc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /doc/src/sgml/high-availability.sgml | |
parent | Initial commit. (diff) | |
download | postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip |
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'doc/src/sgml/high-availability.sgml')
-rw-r--r-- | doc/src/sgml/high-availability.sgml | 2328 |
1 files changed, 2328 insertions, 0 deletions
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml new file mode 100644 index 0000000..40b37c7 --- /dev/null +++ b/doc/src/sgml/high-availability.sgml @@ -0,0 +1,2328 @@ +<!-- doc/src/sgml/high-availability.sgml --> + +<chapter id="high-availability"> + <title>High Availability, Load Balancing, and Replication</title> + + <indexterm><primary>high availability</primary></indexterm> + <indexterm><primary>failover</primary></indexterm> + <indexterm><primary>replication</primary></indexterm> + <indexterm><primary>load balancing</primary></indexterm> + <indexterm><primary>clustering</primary></indexterm> + <indexterm><primary>data partitioning</primary></indexterm> + + <para> + Database servers can work together to allow a second server to + take over quickly if the primary server fails (high + availability), or to allow several computers to serve the same + data (load balancing). Ideally, database servers could work + together seamlessly. Web servers serving static web pages can + be combined quite easily by merely load-balancing web requests + to multiple machines. In fact, read-only database servers can + be combined relatively easily too. Unfortunately, most database + servers have a read/write mix of requests, and read/write servers + are much harder to combine. This is because though read-only + data needs to be placed on each server only once, a write to any + server has to be propagated to all servers so that future read + requests to those servers return consistent results. + </para> + + <para> + This synchronization problem is the fundamental difficulty for + servers working together. Because there is no single solution + that eliminates the impact of the sync problem for all use cases, + there are multiple solutions. Each solution addresses this + problem in a different way, and minimizes its impact for a specific + workload. + </para> + + <para> + Some solutions deal with synchronization by allowing only one + server to modify the data. Servers that can modify data are + called read/write, <firstterm>master</firstterm> or <firstterm>primary</firstterm> servers. + Servers that track changes in the primary are called <firstterm>standby</firstterm> + or <firstterm>secondary</firstterm> servers. A standby server that cannot be connected + to until it is promoted to a primary server is called a <firstterm>warm + standby</firstterm> server, and one that can accept connections and serves read-only + queries is called a <firstterm>hot standby</firstterm> server. + </para> + + <para> + Some solutions are synchronous, + meaning that a data-modifying transaction is not considered + committed until all servers have committed the transaction. This + guarantees that a failover will not lose any data and that all + load-balanced servers will return consistent results no matter + which server is queried. In contrast, asynchronous solutions allow some + delay between the time of a commit and its propagation to the other servers, + opening the possibility that some transactions might be lost in + the switch to a backup server, and that load balanced servers + might return slightly stale results. Asynchronous communication + is used when synchronous would be too slow. + </para> + + <para> + Solutions can also be categorized by their granularity. Some solutions + can deal only with an entire database server, while others allow control + at the per-table or per-database level. + </para> + + <para> + Performance must be considered in any choice. There is usually a + trade-off between functionality and + performance. For example, a fully synchronous solution over a slow + network might cut performance by more than half, while an asynchronous + one might have a minimal performance impact. + </para> + + <para> + The remainder of this section outlines various failover, replication, + and load balancing solutions. + </para> + + <sect1 id="different-replication-solutions"> + <title>Comparison of Different Solutions</title> + + <variablelist> + + <varlistentry> + <term>Shared Disk Failover</term> + <listitem> + + <para> + Shared disk failover avoids synchronization overhead by having only one + copy of the database. It uses a single disk array that is shared by + multiple servers. If the main database server fails, the standby server + is able to mount and start the database as though it were recovering from + a database crash. This allows rapid failover with no data loss. + </para> + + <para> + Shared hardware functionality is common in network storage devices. + Using a network file system is also possible, though care must be + taken that the file system has full <acronym>POSIX</acronym> behavior (see <xref + linkend="creating-cluster-nfs"/>). One significant limitation of this + method is that if the shared disk array fails or becomes corrupt, the + primary and standby servers are both nonfunctional. Another issue is + that the standby server should never access the shared storage while + the primary server is running. + </para> + + </listitem> + </varlistentry> + + <varlistentry> + <term>File System (Block Device) Replication</term> + <listitem> + + <para> + A modified version of shared hardware functionality is file system + replication, where all changes to a file system are mirrored to a file + system residing on another computer. The only restriction is that + the mirroring must be done in a way that ensures the standby server + has a consistent copy of the file system — specifically, writes + to the standby must be done in the same order as those on the primary. + <productname>DRBD</productname> is a popular file system replication solution + for Linux. + </para> + +<!-- +https://forge.continuent.org/pipermail/sequoia/2006-November/004070.html + +Oracle RAC is a shared disk approach and just send cache invalidations +to other nodes but not actual data. As the disk is shared, data is +only committed once to disk and there is a distributed locking +protocol to make nodes agree on a serializable transactional order. +--> + + </listitem> + </varlistentry> + + <varlistentry> + <term>Write-Ahead Log Shipping</term> + <listitem> + + <para> + Warm and hot standby servers can be kept current by reading a + stream of write-ahead log (<acronym>WAL</acronym>) + records. If the main server fails, the standby contains + almost all of the data of the main server, and can be quickly + made the new primary database server. This can be synchronous or + asynchronous and can only be done for the entire database server. + </para> + <para> + A standby server can be implemented using file-based log shipping + (<xref linkend="warm-standby"/>) or streaming replication (see + <xref linkend="streaming-replication"/>), or a combination of both. For + information on hot standby, see <xref linkend="hot-standby"/>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Logical Replication</term> + <listitem> + <para> + Logical replication allows a database server to send a stream of data + modifications to another server. <productname>PostgreSQL</productname> + logical replication constructs a stream of logical data modifications + from the WAL. Logical replication allows replication of data changes on + a per-table basis. In addition, a server that is publishing its own + changes can also subscribe to changes from another server, allowing data + to flow in multiple directions. For more information on logical + replication, see <xref linkend="logical-replication"/>. Through the + logical decoding interface (<xref linkend="logicaldecoding"/>), + third-party extensions can also provide similar functionality. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Trigger-Based Primary-Standby Replication</term> + <listitem> + + <para> + A trigger-based replication setup typically funnels data modification + queries to a designated primary server. Operating on a per-table basis, + the primary server sends data changes (typically) asynchronously to the + standby servers. Standby servers can answer queries while the primary is + running, and may allow some local data changes or write activity. This + form of replication is often used for offloading large analytical or data + warehouse queries. + </para> + + <para> + <productname>Slony-I</productname> is an example of this type of + replication, with per-table granularity, and support for multiple standby + servers. Because it updates the standby server asynchronously (in + batches), there is possible data loss during fail over. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>SQL-Based Replication Middleware</term> + <listitem> + + <para> + With SQL-based replication middleware, a program intercepts + every SQL query and sends it to one or all servers. Each server + operates independently. Read-write queries must be sent to all servers, + so that every server receives any changes. But read-only queries can be + sent to just one server, allowing the read workload to be distributed + among them. + </para> + + <para> + If queries are simply broadcast unmodified, functions like + <function>random()</function>, <function>CURRENT_TIMESTAMP</function>, and + sequences can have different values on different servers. + This is because each server operates independently, and because + SQL queries are broadcast rather than actual data changes. If + this is unacceptable, either the middleware or the application + must determine such values from a single source and then use those + values in write queries. Care must also be taken that all + transactions either commit or abort on all servers, perhaps + using two-phase commit (<xref linkend="sql-prepare-transaction"/> + and <xref linkend="sql-commit-prepared"/>). + <productname>Pgpool-II</productname> and <productname>Continuent Tungsten</productname> + are examples of this type of replication. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Asynchronous Multimaster Replication</term> + <listitem> + + <para> + For servers that are not regularly connected or have slow + communication links, like laptops or + remote servers, keeping data consistent among servers is a + challenge. Using asynchronous multimaster replication, each + server works independently, and periodically communicates with + the other servers to identify conflicting transactions. The + conflicts can be resolved by users or conflict resolution rules. + Bucardo is an example of this type of replication. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Synchronous Multimaster Replication</term> + <listitem> + + <para> + In synchronous multimaster replication, each server can accept + write requests, and modified data is transmitted from the + original server to every other server before each transaction + commits. Heavy write activity can cause excessive locking and + commit delays, leading to poor performance. Read requests can + be sent to any server. Some implementations use shared disk + to reduce the communication overhead. Synchronous multimaster + replication is best for mostly read workloads, though its big + advantage is that any server can accept write requests — + there is no need to partition workloads between primary and + standby servers, and because the data changes are sent from one + server to another, there is no problem with non-deterministic + functions like <function>random()</function>. + </para> + + <para> + <productname>PostgreSQL</productname> does not offer this type of replication, + though <productname>PostgreSQL</productname> two-phase commit (<xref + linkend="sql-prepare-transaction"/> and <xref + linkend="sql-commit-prepared"/>) + can be used to implement this in application code or middleware. + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + <xref linkend="high-availability-matrix"/> summarizes + the capabilities of the various solutions listed above. + </para> + + <table id="high-availability-matrix"> + <title>High Availability, Load Balancing, and Replication Feature Matrix</title> + <tgroup cols="9"> + <colspec colname="col1" colwidth="1.1*"/> + <colspec colname="col2" colwidth="1*"/> + <colspec colname="col3" colwidth="1*"/> + <colspec colname="col4" colwidth="1*"/> + <colspec colname="col5" colwidth="1*"/> + <colspec colname="col6" colwidth="1*"/> + <colspec colname="col7" colwidth="1*"/> + <colspec colname="col8" colwidth="1*"/> + <colspec colname="col9" colwidth="1*"/> + <thead> + <row> + <entry>Feature</entry> + <entry>Shared Disk</entry> + <entry>File System Repl.</entry> + <entry>Write-Ahead Log Shipping</entry> + <entry>Logical Repl.</entry> + <entry>Trigger-&zwsp;Based Repl.</entry> + <entry>SQL Repl. Middle-ware</entry> + <entry>Async. MM Repl.</entry> + <entry>Sync. MM Repl.</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>Popular examples</entry> + <entry align="center">NAS</entry> + <entry align="center">DRBD</entry> + <entry align="center">built-in streaming repl.</entry> + <entry align="center">built-in logical repl., pglogical</entry> + <entry align="center">Londiste, Slony</entry> + <entry align="center">pgpool-II</entry> + <entry align="center">Bucardo</entry> + <entry align="center"></entry> + </row> + + <row> + <entry>Comm. method</entry> + <entry align="center">shared disk</entry> + <entry align="center">disk blocks</entry> + <entry align="center">WAL</entry> + <entry align="center">logical decoding</entry> + <entry align="center">table rows</entry> + <entry align="center">SQL</entry> + <entry align="center">table rows</entry> + <entry align="center">table rows and row locks</entry> + </row> + + <row> + <entry>No special hardware required</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + </row> + + <row> + <entry>Allows multiple primary servers</entry> + <entry align="center"></entry> + <entry align="center"></entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + </row> + + <row> + <entry>No overhead on primary</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center"></entry> + </row> + + <row> + <entry>No waiting for multiple servers</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">with sync off</entry> + <entry align="center">with sync off</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center"></entry> + </row> + + <row> + <entry>Primary failure will never lose data</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">with sync on</entry> + <entry align="center">with sync on</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + </row> + + <row> + <entry>Replicas accept read-only queries</entry> + <entry align="center"></entry> + <entry align="center"></entry> + <entry align="center">with hot standby</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + </row> + + <row> + <entry>Per-table granularity</entry> + <entry align="center"></entry> + <entry align="center"></entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + </row> + + <row> + <entry>No conflict resolution necessary</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + <entry align="center">•</entry> + <entry align="center"></entry> + <entry align="center">•</entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + There are a few solutions that do not fit into the above categories: + </para> + + <variablelist> + + <varlistentry> + <term>Data Partitioning</term> + <listitem> + + <para> + Data partitioning splits tables into data sets. Each set can + be modified by only one server. For example, data can be + partitioned by offices, e.g., London and Paris, with a server + in each office. If queries combining London and Paris data + are necessary, an application can query both servers, or + primary/standby replication can be used to keep a read-only copy + of the other office's data on each server. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Multiple-Server Parallel Query Execution</term> + <listitem> + + <para> + Many of the above solutions allow multiple servers to handle multiple + queries, but none allow a single query to use multiple servers to + complete faster. This solution allows multiple servers to work + concurrently on a single query. It is usually accomplished by + splitting the data among servers and having each server execute its + part of the query and return results to a central server where they + are combined and returned to the user. This can be implemented using the + <productname>PL/Proxy</productname> tool set. + </para> + + </listitem> + </varlistentry> + + </variablelist> + + <para> + It should also be noted that because <productname>PostgreSQL</productname> + is open source and easily extended, a number of companies have + taken <productname>PostgreSQL</productname> and created commercial + closed-source solutions with unique failover, replication, and load + balancing capabilities. These are not discussed here. + </para> + + </sect1> + + + <sect1 id="warm-standby"> + <title>Log-Shipping Standby Servers</title> + + + <para> + Continuous archiving can be used to create a <firstterm>high + availability</firstterm> (HA) cluster configuration with one or more + <firstterm>standby servers</firstterm> ready to take over operations if the + primary server fails. This capability is widely referred to as + <firstterm>warm standby</firstterm> or <firstterm>log shipping</firstterm>. + </para> + + <para> + The primary and standby server work together to provide this capability, + though the servers are only loosely coupled. The primary server operates + in continuous archiving mode, while each standby server operates in + continuous recovery mode, reading the WAL files from the primary. No + changes to the database tables are required to enable this capability, + so it offers low administration overhead compared to some other + replication solutions. This configuration also has relatively low + performance impact on the primary server. + </para> + + <para> + Directly moving WAL records from one database server to another + is typically described as log shipping. <productname>PostgreSQL</productname> + implements file-based log shipping by transferring WAL records + one file (WAL segment) at a time. WAL files (16MB) can be + shipped easily and cheaply over any distance, whether it be to an + adjacent system, another system at the same site, or another system on + the far side of the globe. The bandwidth required for this technique + varies according to the transaction rate of the primary server. + Record-based log shipping is more granular and streams WAL changes + incrementally over a network connection (see <xref + linkend="streaming-replication"/>). + </para> + + <para> + It should be noted that log shipping is asynchronous, i.e., the WAL + records are shipped after transaction commit. As a result, there is a + window for data loss should the primary server suffer a catastrophic + failure; transactions not yet shipped will be lost. The size of the + data loss window in file-based log shipping can be limited by use of the + <varname>archive_timeout</varname> parameter, which can be set as low + as a few seconds. However such a low setting will + substantially increase the bandwidth required for file shipping. + Streaming replication (see <xref linkend="streaming-replication"/>) + allows a much smaller window of data loss. + </para> + + <para> + Recovery performance is sufficiently good that the standby will + typically be only moments away from full + availability once it has been activated. As a result, this is called + a warm standby configuration which offers high + availability. Restoring a server from an archived base backup and + rollforward will take considerably longer, so that technique only + offers a solution for disaster recovery, not high availability. + A standby server can also be used for read-only queries, in which case + it is called a <firstterm>hot standby</firstterm> server. See + <xref linkend="hot-standby"/> for more information. + </para> + + <indexterm zone="high-availability"> + <primary>warm standby</primary> + </indexterm> + + <indexterm zone="high-availability"> + <primary>PITR standby</primary> + </indexterm> + + <indexterm zone="high-availability"> + <primary>standby server</primary> + </indexterm> + + <indexterm zone="high-availability"> + <primary>log shipping</primary> + </indexterm> + + <indexterm zone="high-availability"> + <primary>witness server</primary> + </indexterm> + + <indexterm zone="high-availability"> + <primary>STONITH</primary> + </indexterm> + + <sect2 id="standby-planning"> + <title>Planning</title> + + <para> + It is usually wise to create the primary and standby servers + so that they are as similar as possible, at least from the + perspective of the database server. In particular, the path names + associated with tablespaces will be passed across unmodified, so both + primary and standby servers must have the same mount paths for + tablespaces if that feature is used. Keep in mind that if + <xref linkend="sql-createtablespace"/> + is executed on the primary, any new mount point needed for it must + be created on the primary and all standby servers before the command + is executed. Hardware need not be exactly the same, but experience shows + that maintaining two identical systems is easier than maintaining two + dissimilar ones over the lifetime of the application and system. + In any case the hardware architecture must be the same — shipping + from, say, a 32-bit to a 64-bit system will not work. + </para> + + <para> + In general, log shipping between servers running different major + <productname>PostgreSQL</productname> release + levels is not possible. It is the policy of the PostgreSQL Global + Development Group not to make changes to disk formats during minor release + upgrades, so it is likely that running different minor release levels + on primary and standby servers will work successfully. However, no + formal support for that is offered and you are advised to keep primary + and standby servers at the same release level as much as possible. + When updating to a new minor release, the safest policy is to update + the standby servers first — a new minor release is more likely + to be able to read WAL files from a previous minor release than vice + versa. + </para> + + </sect2> + + <sect2 id="standby-server-operation" xreflabel="Standby Server Operation"> + <title>Standby Server Operation</title> + + <para> + A server enters standby mode if a + <anchor id="file-standby-signal" xreflabel="standby.signal"/> + <filename>standby.signal</filename> + <indexterm><primary><filename>standby.signal</filename></primary></indexterm> + file exists in the data directory when the server is started. + </para> + + <para> + In standby mode, the server continuously applies WAL received from the + primary server. The standby server can read WAL from a WAL archive + (see <xref linkend="guc-restore-command"/>) or directly from the primary + over a TCP connection (streaming replication). The standby server will + also attempt to restore any WAL found in the standby cluster's + <filename>pg_wal</filename> directory. That typically happens after a server + restart, when the standby replays again WAL that was streamed from the + primary before the restart, but you can also manually copy files to + <filename>pg_wal</filename> at any time to have them replayed. + </para> + + <para> + At startup, the standby begins by restoring all WAL available in the + archive location, calling <varname>restore_command</varname>. Once it + reaches the end of WAL available there and <varname>restore_command</varname> + fails, it tries to restore any WAL available in the <filename>pg_wal</filename> directory. + If that fails, and streaming replication has been configured, the + standby tries to connect to the primary server and start streaming WAL + from the last valid record found in archive or <filename>pg_wal</filename>. If that fails + or streaming replication is not configured, or if the connection is + later disconnected, the standby goes back to step 1 and tries to + restore the file from the archive again. This loop of retries from the + archive, <filename>pg_wal</filename>, and via streaming replication goes on until the server + is stopped or is promoted. + </para> + + <para> + Standby mode is exited and the server switches to normal operation + when <command>pg_ctl promote</command> is run, or + <function>pg_promote()</function> is called. Before failover, + any WAL immediately available in the archive or in <filename>pg_wal</filename> + will be restored, but no attempt is made to connect to the primary. + </para> + </sect2> + + <sect2 id="preparing-primary-for-standby"> + <title>Preparing the Primary for Standby Servers</title> + + <para> + Set up continuous archiving on the primary to an archive directory + accessible from the standby, as described + in <xref linkend="continuous-archiving"/>. The archive location should be + accessible from the standby even when the primary is down, i.e., it should + reside on the standby server itself or another trusted server, not on + the primary server. + </para> + + <para> + If you want to use streaming replication, set up authentication on the + primary server to allow replication connections from the standby + server(s); that is, create a role and provide a suitable entry or + entries in <filename>pg_hba.conf</filename> with the database field set to + <literal>replication</literal>. Also ensure <varname>max_wal_senders</varname> is set + to a sufficiently large value in the configuration file of the primary + server. If replication slots will be used, + ensure that <varname>max_replication_slots</varname> is set sufficiently + high as well. + </para> + + <para> + Take a base backup as described in <xref linkend="backup-base-backup"/> + to bootstrap the standby server. + </para> + </sect2> + + <sect2 id="standby-server-setup"> + <title>Setting Up a Standby Server</title> + + <para> + To set up the standby server, restore the base backup taken from primary + server (see <xref linkend="backup-pitr-recovery"/>). Create a file + <link linkend="file-standby-signal"><filename>standby.signal</filename></link><indexterm><primary>standby.signal</primary></indexterm> + in the standby's cluster data + directory. Set <xref linkend="guc-restore-command"/> to a simple command to copy files from + the WAL archive. If you plan to have multiple standby servers for high + availability purposes, make sure that <varname>recovery_target_timeline</varname> is set to + <literal>latest</literal> (the default), to make the standby server follow the timeline change + that occurs at failover to another standby. + </para> + + <note> + <para> + <xref linkend="guc-restore-command"/> should return immediately + if the file does not exist; the server will retry the command again if + necessary. + </para> + </note> + + <para> + If you want to use streaming replication, fill in + <xref linkend="guc-primary-conninfo"/> with a libpq connection string, including + the host name (or IP address) and any additional details needed to + connect to the primary server. If the primary needs a password for + authentication, the password needs to be specified in + <xref linkend="guc-primary-conninfo"/> as well. + </para> + + <para> + If you're setting up the standby server for high availability purposes, + set up WAL archiving, connections and authentication like the primary + server, because the standby server will work as a primary server after + failover. + </para> + + <para> + If you're using a WAL archive, its size can be minimized using the <xref + linkend="guc-archive-cleanup-command"/> parameter to remove files that are no + longer required by the standby server. + The <application>pg_archivecleanup</application> utility is designed specifically to + be used with <varname>archive_cleanup_command</varname> in typical single-standby + configurations, see <xref linkend="pgarchivecleanup"/>. + Note however, that if you're using the archive for backup purposes, you + need to retain files needed to recover from at least the latest base + backup, even if they're no longer needed by the standby. + </para> + + <para> + A simple example of configuration is: +<programlisting> +primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass options=''-c wal_sender_timeout=5000''' +restore_command = 'cp /path/to/archive/%f %p' +archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r' +</programlisting> + </para> + + <para> + You can have any number of standby servers, but if you use streaming + replication, make sure you set <varname>max_wal_senders</varname> high enough in + the primary to allow them to be connected simultaneously. + </para> + + </sect2> + + <sect2 id="streaming-replication"> + <title>Streaming Replication</title> + + <indexterm zone="high-availability"> + <primary>Streaming Replication</primary> + </indexterm> + + <para> + Streaming replication allows a standby server to stay more up-to-date + than is possible with file-based log shipping. The standby connects + to the primary, which streams WAL records to the standby as they're + generated, without waiting for the WAL file to be filled. + </para> + + <para> + Streaming replication is asynchronous by default + (see <xref linkend="synchronous-replication"/>), in which case there is + a small delay between committing a transaction in the primary and the + changes becoming visible in the standby. This delay is however much + smaller than with file-based log shipping, typically under one second + assuming the standby is powerful enough to keep up with the load. With + streaming replication, <varname>archive_timeout</varname> is not required to + reduce the data loss window. + </para> + + <para> + If you use streaming replication without file-based continuous + archiving, the server might recycle old WAL segments before the standby + has received them. If this occurs, the standby will need to be + reinitialized from a new base backup. You can avoid this by setting + <varname>wal_keep_size</varname> to a value large enough to ensure that + WAL segments are not recycled too early, or by configuring a replication + slot for the standby. If you set up a WAL archive that's accessible from + the standby, these solutions are not required, since the standby can + always use the archive to catch up provided it retains enough segments. + </para> + + <para> + To use streaming replication, set up a file-based log-shipping standby + server as described in <xref linkend="warm-standby"/>. The step that + turns a file-based log-shipping standby into streaming replication + standby is setting the <varname>primary_conninfo</varname> setting + to point to the primary server. Set + <xref linkend="guc-listen-addresses"/> and authentication options + (see <filename>pg_hba.conf</filename>) on the primary so that the standby server + can connect to the <literal>replication</literal> pseudo-database on the primary + server (see <xref linkend="streaming-replication-authentication"/>). + </para> + + <para> + On systems that support the keepalive socket option, setting + <xref linkend="guc-tcp-keepalives-idle"/>, + <xref linkend="guc-tcp-keepalives-interval"/> and + <xref linkend="guc-tcp-keepalives-count"/> helps the primary promptly + notice a broken connection. + </para> + + <para> + Set the maximum number of concurrent connections from the standby servers + (see <xref linkend="guc-max-wal-senders"/> for details). + </para> + + <para> + When the standby is started and <varname>primary_conninfo</varname> is set + correctly, the standby will connect to the primary after replaying all + WAL files available in the archive. If the connection is established + successfully, you will see a <literal>walreceiver</literal> in the standby, and + a corresponding <literal>walsender</literal> process in the primary. + </para> + + <sect3 id="streaming-replication-authentication"> + <title>Authentication</title> + <para> + It is very important that the access privileges for replication be set up + so that only trusted users can read the WAL stream, because it is + easy to extract privileged information from it. Standby servers must + authenticate to the primary as an account that has the + <literal>REPLICATION</literal> privilege or a superuser. It is + recommended to create a dedicated user account with + <literal>REPLICATION</literal> and <literal>LOGIN</literal> + privileges for replication. While <literal>REPLICATION</literal> + privilege gives very high permissions, it does not allow the user to + modify any data on the primary system, which the + <literal>SUPERUSER</literal> privilege does. + </para> + + <para> + Client authentication for replication is controlled by a + <filename>pg_hba.conf</filename> record specifying <literal>replication</literal> in the + <replaceable>database</replaceable> field. For example, if the standby is running on + host IP <literal>192.168.1.100</literal> and the account name for replication + is <literal>foo</literal>, the administrator can add the following line to the + <filename>pg_hba.conf</filename> file on the primary: + +<programlisting> +# Allow the user "foo" from host 192.168.1.100 to connect to the primary +# as a replication standby if the user's password is correctly supplied. +# +# TYPE DATABASE USER ADDRESS METHOD +host replication foo 192.168.1.100/32 md5 +</programlisting> + </para> + <para> + The host name and port number of the primary, connection user name, + and password are specified in the <xref linkend="guc-primary-conninfo"/>. + The password can also be set in the <filename>~/.pgpass</filename> file on the + standby (specify <literal>replication</literal> in the <replaceable>database</replaceable> + field). + For example, if the primary is running on host IP <literal>192.168.1.50</literal>, + port <literal>5432</literal>, the account name for replication is + <literal>foo</literal>, and the password is <literal>foopass</literal>, the administrator + can add the following line to the <filename>postgresql.conf</filename> file on the + standby: + +<programlisting> +# The standby connects to the primary that is running on host 192.168.1.50 +# and port 5432 as the user "foo" whose password is "foopass". +primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' +</programlisting> + </para> + </sect3> + + <sect3 id="streaming-replication-monitoring"> + <title>Monitoring</title> + <para> + An important health indicator of streaming replication is the amount + of WAL records generated in the primary, but not yet applied in the + standby. You can calculate this lag by comparing the current WAL write + location on the primary with the last WAL location received by the + standby. These locations can be retrieved using + <function>pg_current_wal_lsn</function> on the primary and + <function>pg_last_wal_receive_lsn</function> on the standby, + respectively (see <xref linkend="functions-admin-backup-table"/> and + <xref linkend="functions-recovery-info-table"/> for details). + The last WAL receive location in the standby is also displayed in the + process status of the WAL receiver process, displayed using the + <command>ps</command> command (see <xref linkend="monitoring-ps"/> for details). + </para> + <para> + You can retrieve a list of WAL sender processes via the + <link linkend="monitoring-pg-stat-replication-view"><structname> + pg_stat_replication</structname></link> view. Large differences between + <function>pg_current_wal_lsn</function> and the view's <literal>sent_lsn</literal> field + might indicate that the primary server is under heavy load, while + differences between <literal>sent_lsn</literal> and + <function>pg_last_wal_receive_lsn</function> on the standby might indicate + network delay, or that the standby is under heavy load. + </para> + <para> + On a hot standby, the status of the WAL receiver process can be retrieved + via the <link linkend="monitoring-pg-stat-wal-receiver-view"> + <structname>pg_stat_wal_receiver</structname></link> view. A large + difference between <function>pg_last_wal_replay_lsn</function> and the + view's <literal>flushed_lsn</literal> indicates that WAL is being + received faster than it can be replayed. + </para> + </sect3> + </sect2> + + <sect2 id="streaming-replication-slots"> + <title>Replication Slots</title> + <indexterm> + <primary>replication slot</primary> + <secondary>streaming replication</secondary> + </indexterm> + <para> + Replication slots provide an automated way to ensure that the primary does + not remove WAL segments until they have been received by all standbys, + and that the primary does not remove rows which could cause a + <link linkend="hot-standby-conflict">recovery conflict</link> even when the + standby is disconnected. + </para> + <para> + In lieu of using replication slots, it is possible to prevent the removal + of old WAL segments using <xref linkend="guc-wal-keep-size"/>, or by + storing the segments in an archive using + <xref linkend="guc-archive-command"/> or <xref linkend="guc-archive-library"/>. + However, these methods often result in retaining more WAL segments than + required, whereas replication slots retain only the number of segments + known to be needed. On the other hand, replication slots can retain so + many WAL segments that they fill up the space allocated + for <literal>pg_wal</literal>; + <xref linkend="guc-max-slot-wal-keep-size"/> limits the size of WAL files + retained by replication slots. + </para> + <para> + Similarly, <xref linkend="guc-hot-standby-feedback"/> on its own, without + also using a replication slot, provides protection against relevant rows + being removed by vacuum, but provides no protection during any time period + when the standby is not connected. Replication slots overcome these + disadvantages. + </para> + <sect3 id="streaming-replication-slots-manipulation"> + <title>Querying and Manipulating Replication Slots</title> + <para> + Each replication slot has a name, which can contain lower-case letters, + numbers, and the underscore character. + </para> + <para> + Existing replication slots and their state can be seen in the + <link linkend="view-pg-replication-slots"><structname>pg_replication_slots</structname></link> + view. + </para> + <para> + Slots can be created and dropped either via the streaming replication + protocol (see <xref linkend="protocol-replication"/>) or via SQL + functions (see <xref linkend="functions-replication"/>). + </para> + </sect3> + <sect3 id="streaming-replication-slots-config"> + <title>Configuration Example</title> + <para> + You can create a replication slot like this: +<programlisting> +postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot'); + slot_name | lsn +-------------+----- + node_a_slot | + +postgres=# SELECT slot_name, slot_type, active FROM pg_replication_slots; + slot_name | slot_type | active +-------------+-----------+-------- + node_a_slot | physical | f +(1 row) +</programlisting> + To configure the standby to use this slot, <varname>primary_slot_name</varname> + should be configured on the standby. Here is a simple example: +<programlisting> +primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' +primary_slot_name = 'node_a_slot' +</programlisting> + </para> + </sect3> + </sect2> + + <sect2 id="cascading-replication"> + <title>Cascading Replication</title> + + <indexterm zone="high-availability"> + <primary>Cascading Replication</primary> + </indexterm> + + <para> + The cascading replication feature allows a standby server to accept replication + connections and stream WAL records to other standbys, acting as a relay. + This can be used to reduce the number of direct connections to the primary + and also to minimize inter-site bandwidth overheads. + </para> + + <para> + A standby acting as both a receiver and a sender is known as a cascading + standby. Standbys that are more directly connected to the primary are known + as upstream servers, while those standby servers further away are downstream + servers. Cascading replication does not place limits on the number or + arrangement of downstream servers, though each standby connects to only + one upstream server which eventually links to a single primary server. + </para> + + <para> + A cascading standby sends not only WAL records received from the + primary but also those restored from the archive. So even if the replication + connection in some upstream connection is terminated, streaming replication + continues downstream for as long as new WAL records are available. + </para> + + <para> + Cascading replication is currently asynchronous. Synchronous replication + (see <xref linkend="synchronous-replication"/>) settings have no effect on + cascading replication at present. + </para> + + <para> + Hot standby feedback propagates upstream, whatever the cascaded arrangement. + </para> + + <para> + If an upstream standby server is promoted to become the new primary, downstream + servers will continue to stream from the new primary if + <varname>recovery_target_timeline</varname> is set to <literal>'latest'</literal> (the default). + </para> + + <para> + To use cascading replication, set up the cascading standby so that it can + accept replication connections (that is, set + <xref linkend="guc-max-wal-senders"/> and <xref linkend="guc-hot-standby"/>, + and configure + <link linkend="auth-pg-hba-conf">host-based authentication</link>). + You will also need to set <varname>primary_conninfo</varname> in the downstream + standby to point to the cascading standby. + </para> + </sect2> + + <sect2 id="synchronous-replication"> + <title>Synchronous Replication</title> + + <indexterm zone="high-availability"> + <primary>Synchronous Replication</primary> + </indexterm> + + <para> + <productname>PostgreSQL</productname> streaming replication is asynchronous by + default. If the primary server + crashes then some transactions that were committed may not have been + replicated to the standby server, causing data loss. The amount + of data loss is proportional to the replication delay at the time of + failover. + </para> + + <para> + Synchronous replication offers the ability to confirm that all changes + made by a transaction have been transferred to one or more synchronous + standby servers. This extends that standard level of durability + offered by a transaction commit. This level of protection is referred + to as 2-safe replication in computer science theory, and group-1-safe + (group-safe and 1-safe) when <varname>synchronous_commit</varname> is set to + <literal>remote_write</literal>. + </para> + + <para> + When requesting synchronous replication, each commit of a + write transaction will wait until confirmation is + received that the commit has been written to the write-ahead log on disk + of both the primary and standby server. The only possibility that data + can be lost is if both the primary and the standby suffer crashes at the + same time. This can provide a much higher level of durability, though only + if the sysadmin is cautious about the placement and management of the two + servers. Waiting for confirmation increases the user's confidence that the + changes will not be lost in the event of server crashes but it also + necessarily increases the response time for the requesting transaction. + The minimum wait time is the round-trip time between primary and standby. + </para> + + <para> + Read-only transactions and transaction rollbacks need not wait for + replies from standby servers. Subtransaction commits do not wait for + responses from standby servers, only top-level commits. Long + running actions such as data loading or index building do not wait + until the very final commit message. All two-phase commit actions + require commit waits, including both prepare and commit. + </para> + + <para> + A synchronous standby can be a physical replication standby or a logical + replication subscriber. It can also be any other physical or logical WAL + replication stream consumer that knows how to send the appropriate + feedback messages. Besides the built-in physical and logical replication + systems, this includes special programs such + as <command>pg_receivewal</command> and <command>pg_recvlogical</command> + as well as some third-party replication systems and custom programs. + Check the respective documentation for details on synchronous replication + support. + </para> + + <sect3 id="synchronous-replication-config"> + <title>Basic Configuration</title> + + <para> + Once streaming replication has been configured, configuring synchronous + replication requires only one additional configuration step: + <xref linkend="guc-synchronous-standby-names"/> must be set to + a non-empty value. <varname>synchronous_commit</varname> must also be set to + <literal>on</literal>, but since this is the default value, typically no change is + required. (See <xref linkend="runtime-config-wal-settings"/> and + <xref linkend="runtime-config-replication-primary"/>.) + This configuration will cause each commit to wait for + confirmation that the standby has written the commit record to durable + storage. + <varname>synchronous_commit</varname> can be set by individual + users, so it can be configured in the configuration file, for particular + users or databases, or dynamically by applications, in order to control + the durability guarantee on a per-transaction basis. + </para> + + <para> + After a commit record has been written to disk on the primary, the + WAL record is then sent to the standby. The standby sends reply + messages each time a new batch of WAL data is written to disk, unless + <varname>wal_receiver_status_interval</varname> is set to zero on the standby. + In the case that <varname>synchronous_commit</varname> is set to + <literal>remote_apply</literal>, the standby sends reply messages when the commit + record is replayed, making the transaction visible. + If the standby is chosen as a synchronous standby, according to the setting + of <varname>synchronous_standby_names</varname> on the primary, the reply + messages from that standby will be considered along with those from other + synchronous standbys to decide when to release transactions waiting for + confirmation that the commit record has been received. These parameters + allow the administrator to specify which standby servers should be + synchronous standbys. Note that the configuration of synchronous + replication is mainly on the primary. Named standbys must be directly + connected to the primary; the primary knows nothing about downstream + standby servers using cascaded replication. + </para> + + <para> + Setting <varname>synchronous_commit</varname> to <literal>remote_write</literal> will + cause each commit to wait for confirmation that the standby has received + the commit record and written it out to its own operating system, but not + for the data to be flushed to disk on the standby. This + setting provides a weaker guarantee of durability than <literal>on</literal> + does: the standby could lose the data in the event of an operating system + crash, though not a <productname>PostgreSQL</productname> crash. + However, it's a useful setting in practice + because it can decrease the response time for the transaction. + Data loss could only occur if both the primary and the standby crash and + the database of the primary gets corrupted at the same time. + </para> + + <para> + Setting <varname>synchronous_commit</varname> to <literal>remote_apply</literal> will + cause each commit to wait until the current synchronous standbys report + that they have replayed the transaction, making it visible to user + queries. In simple cases, this allows for load balancing with causal + consistency. + </para> + + <para> + Users will stop waiting if a fast shutdown is requested. However, as + when using asynchronous replication, the server will not fully + shutdown until all outstanding WAL records are transferred to the currently + connected standby servers. + </para> + + </sect3> + + <sect3 id="synchronous-replication-multiple-standbys"> + <title>Multiple Synchronous Standbys</title> + + <para> + Synchronous replication supports one or more synchronous standby servers; + transactions will wait until all the standby servers which are considered + as synchronous confirm receipt of their data. The number of synchronous + standbys that transactions must wait for replies from is specified in + <varname>synchronous_standby_names</varname>. This parameter also specifies + a list of standby names and the method (<literal>FIRST</literal> and + <literal>ANY</literal>) to choose synchronous standbys from the listed ones. + </para> + <para> + The method <literal>FIRST</literal> specifies a priority-based synchronous + replication and makes transaction commits wait until their WAL records are + replicated to the requested number of synchronous standbys chosen based on + their priorities. The standbys whose names appear earlier in the list are + given higher priority and will be considered as synchronous. Other standby + servers appearing later in this list represent potential synchronous + standbys. If any of the current synchronous standbys disconnects for + whatever reason, it will be replaced immediately with the + next-highest-priority standby. + </para> + <para> + An example of <varname>synchronous_standby_names</varname> for + a priority-based multiple synchronous standbys is: +<programlisting> +synchronous_standby_names = 'FIRST 2 (s1, s2, s3)' +</programlisting> + In this example, if four standby servers <literal>s1</literal>, <literal>s2</literal>, + <literal>s3</literal> and <literal>s4</literal> are running, the two standbys + <literal>s1</literal> and <literal>s2</literal> will be chosen as synchronous standbys + because their names appear early in the list of standby names. + <literal>s3</literal> is a potential synchronous standby and will take over + the role of synchronous standby when either of <literal>s1</literal> or + <literal>s2</literal> fails. <literal>s4</literal> is an asynchronous standby since + its name is not in the list. + </para> + <para> + The method <literal>ANY</literal> specifies a quorum-based synchronous + replication and makes transaction commits wait until their WAL records + are replicated to <emphasis>at least</emphasis> the requested number of + synchronous standbys in the list. + </para> + <para> + An example of <varname>synchronous_standby_names</varname> for + a quorum-based multiple synchronous standbys is: +<programlisting> +synchronous_standby_names = 'ANY 2 (s1, s2, s3)' +</programlisting> + In this example, if four standby servers <literal>s1</literal>, <literal>s2</literal>, + <literal>s3</literal> and <literal>s4</literal> are running, transaction commits will + wait for replies from at least any two standbys of <literal>s1</literal>, + <literal>s2</literal> and <literal>s3</literal>. <literal>s4</literal> is an asynchronous + standby since its name is not in the list. + </para> + <para> + The synchronous states of standby servers can be viewed using + the <structname>pg_stat_replication</structname> view. + </para> + </sect3> + + <sect3 id="synchronous-replication-performance"> + <title>Planning for Performance</title> + + <para> + Synchronous replication usually requires carefully planned and placed + standby servers to ensure applications perform acceptably. Waiting + doesn't utilize system resources, but transaction locks continue to be + held until the transfer is confirmed. As a result, incautious use of + synchronous replication will reduce performance for database + applications because of increased response times and higher contention. + </para> + + <para> + <productname>PostgreSQL</productname> allows the application developer + to specify the durability level required via replication. This can be + specified for the system overall, though it can also be specified for + specific users or connections, or even individual transactions. + </para> + + <para> + For example, an application workload might consist of: + 10% of changes are important customer details, while + 90% of changes are less important data that the business can more + easily survive if it is lost, such as chat messages between users. + </para> + + <para> + With synchronous replication options specified at the application level + (on the primary) we can offer synchronous replication for the most + important changes, without slowing down the bulk of the total workload. + Application level options are an important and practical tool for allowing + the benefits of synchronous replication for high performance applications. + </para> + + <para> + You should consider that the network bandwidth must be higher than + the rate of generation of WAL data. + </para> + + </sect3> + + <sect3 id="synchronous-replication-ha"> + <title>Planning for High Availability</title> + + <para> + <varname>synchronous_standby_names</varname> specifies the number and + names of synchronous standbys that transaction commits made when + <varname>synchronous_commit</varname> is set to <literal>on</literal>, + <literal>remote_apply</literal> or <literal>remote_write</literal> will wait for + responses from. Such transaction commits may never be completed + if any one of synchronous standbys should crash. + </para> + + <para> + The best solution for high availability is to ensure you keep as many + synchronous standbys as requested. This can be achieved by naming multiple + potential synchronous standbys using <varname>synchronous_standby_names</varname>. + </para> + + <para> + In a priority-based synchronous replication, the standbys whose names + appear earlier in the list will be used as synchronous standbys. + Standbys listed after these will take over the role of synchronous standby + if one of current ones should fail. + </para> + + <para> + In a quorum-based synchronous replication, all the standbys appearing + in the list will be used as candidates for synchronous standbys. + Even if one of them should fail, the other standbys will keep performing + the role of candidates of synchronous standby. + </para> + + <para> + When a standby first attaches to the primary, it will not yet be properly + synchronized. This is described as <literal>catchup</literal> mode. Once + the lag between standby and primary reaches zero for the first time + we move to real-time <literal>streaming</literal> state. + The catch-up duration may be long immediately after the standby has + been created. If the standby is shut down, then the catch-up period + will increase according to the length of time the standby has been down. + The standby is only able to become a synchronous standby + once it has reached <literal>streaming</literal> state. + This state can be viewed using + the <structname>pg_stat_replication</structname> view. + </para> + + <para> + If primary restarts while commits are waiting for acknowledgment, those + waiting transactions will be marked fully committed once the primary + database recovers. + There is no way to be certain that all standbys have received all + outstanding WAL data at time of the crash of the primary. Some + transactions may not show as committed on the standby, even though + they show as committed on the primary. The guarantee we offer is that + the application will not receive explicit acknowledgment of the + successful commit of a transaction until the WAL data is known to be + safely received by all the synchronous standbys. + </para> + + <para> + If you really cannot keep as many synchronous standbys as requested + then you should decrease the number of synchronous standbys that + transaction commits must wait for responses from + in <varname>synchronous_standby_names</varname> (or disable it) and + reload the configuration file on the primary server. + </para> + + <para> + If the primary is isolated from remaining standby servers you should + fail over to the best candidate of those other remaining standby servers. + </para> + + <para> + If you need to re-create a standby server while transactions are + waiting, make sure that the commands pg_backup_start() and + pg_backup_stop() are run in a session with + <varname>synchronous_commit</varname> = <literal>off</literal>, otherwise those + requests will wait forever for the standby to appear. + </para> + + </sect3> + </sect2> + + <sect2 id="continuous-archiving-in-standby"> + <title>Continuous Archiving in Standby</title> + + <indexterm> + <primary>continuous archiving</primary> + <secondary>in standby</secondary> + </indexterm> + + <para> + When continuous WAL archiving is used in a standby, there are two + different scenarios: the WAL archive can be shared between the primary + and the standby, or the standby can have its own WAL archive. When + the standby has its own WAL archive, set <varname>archive_mode</varname> + to <literal>always</literal>, and the standby will call the archive + command for every WAL segment it receives, whether it's by restoring + from the archive or by streaming replication. The shared archive can + be handled similarly, but the <varname>archive_command</varname> or <varname>archive_library</varname> must + test if the file being archived exists already, and if the existing file + has identical contents. This requires more care in the + <varname>archive_command</varname> or <varname>archive_library</varname>, as it must + be careful to not overwrite an existing file with different contents, + but return success if the exactly same file is archived twice. And + all that must be done free of race conditions, if two servers attempt + to archive the same file at the same time. + </para> + + <para> + If <varname>archive_mode</varname> is set to <literal>on</literal>, the + archiver is not enabled during recovery or standby mode. If the standby + server is promoted, it will start archiving after the promotion, but + will not archive any WAL or timeline history files that + it did not generate itself. To get a complete + series of WAL files in the archive, you must ensure that all WAL is + archived, before it reaches the standby. This is inherently true with + file-based log shipping, as the standby can only restore files that + are found in the archive, but not if streaming replication is enabled. + When a server is not in recovery mode, there is no difference between + <literal>on</literal> and <literal>always</literal> modes. + </para> + </sect2> + </sect1> + + <sect1 id="warm-standby-failover"> + <title>Failover</title> + + <para> + If the primary server fails then the standby server should begin + failover procedures. + </para> + + <para> + If the standby server fails then no failover need take place. If the + standby server can be restarted, even some time later, then the recovery + process can also be restarted immediately, taking advantage of + restartable recovery. If the standby server cannot be restarted, then a + full new standby server instance should be created. + </para> + + <para> + If the primary server fails and the standby server becomes the + new primary, and then the old primary restarts, you must have + a mechanism for informing the old primary that it is no longer the primary. This is + sometimes known as <acronym>STONITH</acronym> (Shoot The Other Node In The Head), which is + necessary to avoid situations where both systems think they are the + primary, which will lead to confusion and ultimately data loss. + </para> + + <para> + Many failover systems use just two systems, the primary and the standby, + connected by some kind of heartbeat mechanism to continually verify the + connectivity between the two and the viability of the primary. It is + also possible to use a third system (called a witness server) to prevent + some cases of inappropriate failover, but the additional complexity + might not be worthwhile unless it is set up with sufficient care and + rigorous testing. + </para> + + <para> + <productname>PostgreSQL</productname> does not provide the system + software required to identify a failure on the primary and notify + the standby database server. Many such tools exist and are well + integrated with the operating system facilities required for + successful failover, such as IP address migration. + </para> + + <para> + Once failover to the standby occurs, there is only a + single server in operation. This is known as a degenerate state. + The former standby is now the primary, but the former primary is down + and might stay down. To return to normal operation, a standby server + must be recreated, + either on the former primary system when it comes up, or on a third, + possibly new, system. The <xref linkend="app-pgrewind"/> utility can be + used to speed up this process on large clusters. + Once complete, the primary and standby can be + considered to have switched roles. Some people choose to use a third + server to provide backup for the new primary until the new standby + server is recreated, + though clearly this complicates the system configuration and + operational processes. + </para> + + <para> + So, switching from primary to standby server can be fast but requires + some time to re-prepare the failover cluster. Regular switching from + primary to standby is useful, since it allows regular downtime on + each system for maintenance. This also serves as a test of the + failover mechanism to ensure that it will really work when you need it. + Written administration procedures are advised. + </para> + + <para> + To trigger failover of a log-shipping standby server, run + <command>pg_ctl promote</command> or call <function>pg_promote()</function>. + If you're setting up reporting servers that are only used to offload + read-only queries from the primary, not for high availability purposes, + you don't need to promote. + </para> + </sect1> + + <sect1 id="hot-standby"> + <title>Hot Standby</title> + + <indexterm zone="high-availability"> + <primary>hot standby</primary> + </indexterm> + + <para> + Hot standby is the term used to describe the ability to connect to + the server and run read-only queries while the server is in archive + recovery or standby mode. This + is useful both for replication purposes and for restoring a backup + to a desired state with great precision. + The term hot standby also refers to the ability of the server to move + from recovery through to normal operation while users continue running + queries and/or keep their connections open. + </para> + + <para> + Running queries in hot standby mode is similar to normal query operation, + though there are several usage and administrative differences + explained below. + </para> + + <sect2 id="hot-standby-users"> + <title>User's Overview</title> + + <para> + When the <xref linkend="guc-hot-standby"/> parameter is set to true on a + standby server, it will begin accepting connections once the recovery has + brought the system to a consistent state. All such connections are + strictly read-only; not even temporary tables may be written. + </para> + + <para> + The data on the standby takes some time to arrive from the primary server + so there will be a measurable delay between primary and standby. Running the + same query nearly simultaneously on both primary and standby might therefore + return differing results. We say that data on the standby is + <firstterm>eventually consistent</firstterm> with the primary. Once the + commit record for a transaction is replayed on the standby, the changes + made by that transaction will be visible to any new snapshots taken on + the standby. Snapshots may be taken at the start of each query or at the + start of each transaction, depending on the current transaction isolation + level. For more details, see <xref linkend="transaction-iso"/>. + </para> + + <para> + Transactions started during hot standby may issue the following commands: + + <itemizedlist> + <listitem> + <para> + Query access: <command>SELECT</command>, <command>COPY TO</command> + </para> + </listitem> + <listitem> + <para> + Cursor commands: <command>DECLARE</command>, <command>FETCH</command>, <command>CLOSE</command> + </para> + </listitem> + <listitem> + <para> + Settings: <command>SHOW</command>, <command>SET</command>, <command>RESET</command> + </para> + </listitem> + <listitem> + <para> + Transaction management commands: + <itemizedlist> + <listitem> + <para> + <command>BEGIN</command>, <command>END</command>, <command>ABORT</command>, <command>START TRANSACTION</command> + </para> + </listitem> + <listitem> + <para> + <command>SAVEPOINT</command>, <command>RELEASE</command>, <command>ROLLBACK TO SAVEPOINT</command> + </para> + </listitem> + <listitem> + <para> + <command>EXCEPTION</command> blocks and other internal subtransactions + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + <listitem> + <para> + <command>LOCK TABLE</command>, though only when explicitly in one of these modes: + <literal>ACCESS SHARE</literal>, <literal>ROW SHARE</literal> or <literal>ROW EXCLUSIVE</literal>. + </para> + </listitem> + <listitem> + <para> + Plans and resources: <command>PREPARE</command>, <command>EXECUTE</command>, + <command>DEALLOCATE</command>, <command>DISCARD</command> + </para> + </listitem> + <listitem> + <para> + Plugins and extensions: <command>LOAD</command> + </para> + </listitem> + <listitem> + <para> + <command>UNLISTEN</command> + </para> + </listitem> + </itemizedlist> + </para> + + <para> + Transactions started during hot standby will never be assigned a + transaction ID and cannot write to the system write-ahead log. + Therefore, the following actions will produce error messages: + + <itemizedlist> + <listitem> + <para> + Data Manipulation Language (DML): <command>INSERT</command>, + <command>UPDATE</command>, <command>DELETE</command>, + <command>MERGE</command>, <command>COPY FROM</command>, + <command>TRUNCATE</command>. + Note that there are no allowed actions that result in a trigger + being executed during recovery. This restriction applies even to + temporary tables, because table rows cannot be read or written without + assigning a transaction ID, which is currently not possible in a + hot standby environment. + </para> + </listitem> + <listitem> + <para> + Data Definition Language (DDL): <command>CREATE</command>, + <command>DROP</command>, <command>ALTER</command>, <command>COMMENT</command>. + This restriction applies even to temporary tables, because carrying + out these operations would require updating the system catalog tables. + </para> + </listitem> + <listitem> + <para> + <command>SELECT ... FOR SHARE | UPDATE</command>, because row locks cannot be + taken without updating the underlying data files. + </para> + </listitem> + <listitem> + <para> + Rules on <command>SELECT</command> statements that generate DML commands. + </para> + </listitem> + <listitem> + <para> + <command>LOCK</command> that explicitly requests a mode higher than <literal>ROW EXCLUSIVE MODE</literal>. + </para> + </listitem> + <listitem> + <para> + <command>LOCK</command> in short default form, since it requests <literal>ACCESS EXCLUSIVE MODE</literal>. + </para> + </listitem> + <listitem> + <para> + Transaction management commands that explicitly set non-read-only state: + <itemizedlist> + <listitem> + <para> + <command>BEGIN READ WRITE</command>, + <command>START TRANSACTION READ WRITE</command> + </para> + </listitem> + <listitem> + <para> + <command>SET TRANSACTION READ WRITE</command>, + <command>SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE</command> + </para> + </listitem> + <listitem> + <para> + <command>SET transaction_read_only = off</command> + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + <listitem> + <para> + Two-phase commit commands: <command>PREPARE TRANSACTION</command>, + <command>COMMIT PREPARED</command>, <command>ROLLBACK PREPARED</command> + because even read-only transactions need to write WAL in the + prepare phase (the first phase of two phase commit). + </para> + </listitem> + <listitem> + <para> + Sequence updates: <function>nextval()</function>, <function>setval()</function> + </para> + </listitem> + <listitem> + <para> + <command>LISTEN</command>, <command>NOTIFY</command> + </para> + </listitem> + </itemizedlist> + </para> + + <para> + In normal operation, <quote>read-only</quote> transactions are allowed to + use <command>LISTEN</command> and <command>NOTIFY</command>, + so hot standby sessions operate under slightly tighter + restrictions than ordinary read-only sessions. It is possible that some + of these restrictions might be loosened in a future release. + </para> + + <para> + During hot standby, the parameter <varname>transaction_read_only</varname> is always + true and may not be changed. But as long as no attempt is made to modify + the database, connections during hot standby will act much like any other + database connection. If failover or switchover occurs, the database will + switch to normal processing mode. Sessions will remain connected while the + server changes mode. Once hot standby finishes, it will be possible to + initiate read-write transactions (even from a session begun during + hot standby). + </para> + + <para> + Users can determine whether hot standby is currently active for their + session by issuing <command>SHOW in_hot_standby</command>. + (In server versions before 14, the <varname>in_hot_standby</varname> + parameter did not exist; a workable substitute method for older servers + is <command>SHOW transaction_read_only</command>.) In addition, a set of + functions (<xref linkend="functions-recovery-info-table"/>) allow users to + access information about the standby server. These allow you to write + programs that are aware of the current state of the database. These + can be used to monitor the progress of recovery, or to allow you to + write complex programs that restore the database to particular states. + </para> + </sect2> + + <sect2 id="hot-standby-conflict"> + <title>Handling Query Conflicts</title> + + <para> + The primary and standby servers are in many ways loosely connected. Actions + on the primary will have an effect on the standby. As a result, there is + potential for negative interactions or conflicts between them. The easiest + conflict to understand is performance: if a huge data load is taking place + on the primary then this will generate a similar stream of WAL records on the + standby, so standby queries may contend for system resources, such as I/O. + </para> + + <para> + There are also additional types of conflict that can occur with hot standby. + These conflicts are <emphasis>hard conflicts</emphasis> in the sense that queries + might need to be canceled and, in some cases, sessions disconnected to resolve them. + The user is provided with several ways to handle these + conflicts. Conflict cases include: + + <itemizedlist> + <listitem> + <para> + Access Exclusive locks taken on the primary server, including both + explicit <command>LOCK</command> commands and various <acronym>DDL</acronym> + actions, conflict with table accesses in standby queries. + </para> + </listitem> + <listitem> + <para> + Dropping a tablespace on the primary conflicts with standby queries + using that tablespace for temporary work files. + </para> + </listitem> + <listitem> + <para> + Dropping a database on the primary conflicts with sessions connected + to that database on the standby. + </para> + </listitem> + <listitem> + <para> + Application of a vacuum cleanup record from WAL conflicts with + standby transactions whose snapshots can still <quote>see</quote> any of + the rows to be removed. + </para> + </listitem> + <listitem> + <para> + Application of a vacuum cleanup record from WAL conflicts with + queries accessing the target page on the standby, whether or not + the data to be removed is visible. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + On the primary server, these cases simply result in waiting; and the + user might choose to cancel either of the conflicting actions. However, + on the standby there is no choice: the WAL-logged action already occurred + on the primary so the standby must not fail to apply it. Furthermore, + allowing WAL application to wait indefinitely may be very undesirable, + because the standby's state will become increasingly far behind the + primary's. Therefore, a mechanism is provided to forcibly cancel standby + queries that conflict with to-be-applied WAL records. + </para> + + <para> + An example of the problem situation is an administrator on the primary + server running <command>DROP TABLE</command> on a table that is currently being + queried on the standby server. Clearly the standby query cannot continue + if the <command>DROP TABLE</command> is applied on the standby. If this situation + occurred on the primary, the <command>DROP TABLE</command> would wait until the + other query had finished. But when <command>DROP TABLE</command> is run on the + primary, the primary doesn't have information about what queries are + running on the standby, so it will not wait for any such standby + queries. The WAL change records come through to the standby while the + standby query is still running, causing a conflict. The standby server + must either delay application of the WAL records (and everything after + them, too) or else cancel the conflicting query so that the <command>DROP + TABLE</command> can be applied. + </para> + + <para> + When a conflicting query is short, it's typically desirable to allow it to + complete by delaying WAL application for a little bit; but a long delay in + WAL application is usually not desirable. So the cancel mechanism has + parameters, <xref linkend="guc-max-standby-archive-delay"/> and <xref + linkend="guc-max-standby-streaming-delay"/>, that define the maximum + allowed delay in WAL application. Conflicting queries will be canceled + once it has taken longer than the relevant delay setting to apply any + newly-received WAL data. There are two parameters so that different delay + values can be specified for the case of reading WAL data from an archive + (i.e., initial recovery from a base backup or <quote>catching up</quote> a + standby server that has fallen far behind) versus reading WAL data via + streaming replication. + </para> + + <para> + In a standby server that exists primarily for high availability, it's + best to set the delay parameters relatively short, so that the server + cannot fall far behind the primary due to delays caused by standby + queries. However, if the standby server is meant for executing + long-running queries, then a high or even infinite delay value may be + preferable. Keep in mind however that a long-running query could + cause other sessions on the standby server to not see recent changes + on the primary, if it delays application of WAL records. + </para> + + <para> + Once the delay specified by <varname>max_standby_archive_delay</varname> or + <varname>max_standby_streaming_delay</varname> has been exceeded, conflicting + queries will be canceled. This usually results just in a cancellation + error, although in the case of replaying a <command>DROP DATABASE</command> + the entire conflicting session will be terminated. Also, if the conflict + is over a lock held by an idle transaction, the conflicting session is + terminated (this behavior might change in the future). + </para> + + <para> + Canceled queries may be retried immediately (after beginning a new + transaction, of course). Since query cancellation depends on + the nature of the WAL records being replayed, a query that was + canceled may well succeed if it is executed again. + </para> + + <para> + Keep in mind that the delay parameters are compared to the elapsed time + since the WAL data was received by the standby server. Thus, the grace + period allowed to any one query on the standby is never more than the + delay parameter, and could be considerably less if the standby has already + fallen behind as a result of waiting for previous queries to complete, or + as a result of being unable to keep up with a heavy update load. + </para> + + <para> + The most common reason for conflict between standby queries and WAL replay + is <quote>early cleanup</quote>. Normally, <productname>PostgreSQL</productname> allows + cleanup of old row versions when there are no transactions that need to + see them to ensure correct visibility of data according to MVCC rules. + However, this rule can only be applied for transactions executing on the + primary. So it is possible that cleanup on the primary will remove row + versions that are still visible to a transaction on the standby. + </para> + + <para> + Row version cleanup isn't the only potential cause of conflicts with + standby queries. All index-only scans (including those that run on + standbys) must use an <acronym>MVCC</acronym> snapshot that + <quote>agrees</quote> with the visibility map. Conflicts are therefore + required whenever <command>VACUUM</command> <link + linkend="vacuum-for-visibility-map">sets a page as all-visible in the + visibility map</link> containing one or more rows + <emphasis>not</emphasis> visible to all standby queries. So even running + <command>VACUUM</command> against a table with no updated or deleted rows + requiring cleanup might lead to conflicts. + </para> + + <para> + Users should be clear that tables that are regularly and heavily updated + on the primary server will quickly cause cancellation of longer running + queries on the standby. In such cases the setting of a finite value for + <varname>max_standby_archive_delay</varname> or + <varname>max_standby_streaming_delay</varname> can be considered similar to + setting <varname>statement_timeout</varname>. + </para> + + <para> + Remedial possibilities exist if the number of standby-query cancellations + is found to be unacceptable. The first option is to set the parameter + <varname>hot_standby_feedback</varname>, which prevents <command>VACUUM</command> from + removing recently-dead rows and so cleanup conflicts do not occur. + If you do this, you + should note that this will delay cleanup of dead rows on the primary, + which may result in undesirable table bloat. However, the cleanup + situation will be no worse than if the standby queries were running + directly on the primary server, and you are still getting the benefit of + off-loading execution onto the standby. + If standby servers connect and disconnect frequently, you + might want to make adjustments to handle the period when + <varname>hot_standby_feedback</varname> feedback is not being provided. + For example, consider increasing <varname>max_standby_archive_delay</varname> + so that queries are not rapidly canceled by conflicts in WAL archive + files during disconnected periods. You should also consider increasing + <varname>max_standby_streaming_delay</varname> to avoid rapid cancellations + by newly-arrived streaming WAL entries after reconnection. + </para> + + <para> + The number of query cancels and the reason for them can be viewed using + the <structname>pg_stat_database_conflicts</structname> system view on the standby + server. The <structname>pg_stat_database</structname> system view also contains + summary information. + </para> + + <para> + Users can control whether a log message is produced when WAL replay is waiting + longer than <varname>deadlock_timeout</varname> for conflicts. This + is controlled by the <xref linkend="guc-log-recovery-conflict-waits"/> parameter. + </para> + </sect2> + + <sect2 id="hot-standby-admin"> + <title>Administrator's Overview</title> + + <para> + If <varname>hot_standby</varname> is <literal>on</literal> in <filename>postgresql.conf</filename> + (the default value) and there is a + <link linkend="file-standby-signal"><filename>standby.signal</filename></link><indexterm><primary>standby.signal</primary><secondary>for hot standby</secondary></indexterm> + file present, the server will run in hot standby mode. + However, it may take some time for hot standby connections to be allowed, + because the server will not accept connections until it has completed + sufficient recovery to provide a consistent state against which queries + can run. During this period, + clients that attempt to connect will be refused with an error message. + To confirm the server has come up, either loop trying to connect from + the application, or look for these messages in the server logs: + +<programlisting> +LOG: entering standby mode + +... then some time later ... + +LOG: consistent recovery state reached +LOG: database system is ready to accept read-only connections +</programlisting> + + Consistency information is recorded once per checkpoint on the primary. + It is not possible to enable hot standby when reading WAL + written during a period when <varname>wal_level</varname> was not set to + <literal>replica</literal> or <literal>logical</literal> on the primary. Reaching + a consistent state can also be delayed in the presence of both of these + conditions: + + <itemizedlist> + <listitem> + <para> + A write transaction has more than 64 subtransactions + </para> + </listitem> + <listitem> + <para> + Very long-lived write transactions + </para> + </listitem> + </itemizedlist> + + If you are running file-based log shipping ("warm standby"), you might need + to wait until the next WAL file arrives, which could be as long as the + <varname>archive_timeout</varname> setting on the primary. + </para> + + <para> + The settings of some parameters determine the size of shared memory for + tracking transaction IDs, locks, and prepared transactions. These shared + memory structures must be no smaller on a standby than on the primary in + order to ensure that the standby does not run out of shared memory during + recovery. For example, if the primary had used a prepared transaction but + the standby had not allocated any shared memory for tracking prepared + transactions, then recovery could not continue until the standby's + configuration is changed. The parameters affected are: + + <itemizedlist> + <listitem> + <para> + <varname>max_connections</varname> + </para> + </listitem> + <listitem> + <para> + <varname>max_prepared_transactions</varname> + </para> + </listitem> + <listitem> + <para> + <varname>max_locks_per_transaction</varname> + </para> + </listitem> + <listitem> + <para> + <varname>max_wal_senders</varname> + </para> + </listitem> + <listitem> + <para> + <varname>max_worker_processes</varname> + </para> + </listitem> + </itemizedlist> + + The easiest way to ensure this does not become a problem is to have these + parameters set on the standbys to values equal to or greater than on the + primary. Therefore, if you want to increase these values, you should do + so on all standby servers first, before applying the changes to the + primary server. Conversely, if you want to decrease these values, you + should do so on the primary server first, before applying the changes to + all standby servers. Keep in mind that when a standby is promoted, it + becomes the new reference for the required parameter settings for the + standbys that follow it. Therefore, to avoid this becoming a problem + during a switchover or failover, it is recommended to keep these settings + the same on all standby servers. + </para> + + <para> + The WAL tracks changes to these parameters on the + primary. If a hot standby processes WAL that indicates that the current + value on the primary is higher than its own value, it will log a warning + and pause recovery, for example: +<screen> +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. +</screen> + At that point, the settings on the standby need to be updated and the + instance restarted before recovery can continue. If the standby is not a + hot standby, then when it encounters the incompatible parameter change, it + will shut down immediately without pausing, since there is then no value + in keeping it up. + </para> + + <para> + It is important that the administrator select appropriate settings for + <xref linkend="guc-max-standby-archive-delay"/> and <xref + linkend="guc-max-standby-streaming-delay"/>. The best choices vary + depending on business priorities. For example if the server is primarily + tasked as a High Availability server, then you will want low delay + settings, perhaps even zero, though that is a very aggressive setting. If + the standby server is tasked as an additional server for decision support + queries then it might be acceptable to set the maximum delay values to + many hours, or even -1 which means wait forever for queries to complete. + </para> + + <para> + Transaction status "hint bits" written on the primary are not WAL-logged, + so data on the standby will likely re-write the hints again on the standby. + Thus, the standby server will still perform disk writes even though + all users are read-only; no changes occur to the data values + themselves. Users will still write large sort temporary files and + re-generate relcache info files, so no part of the database + is truly read-only during hot standby mode. + Note also that writes to remote databases using + <application>dblink</application> module, and other operations outside the + database using PL functions will still be possible, even though the + transaction is read-only locally. + </para> + + <para> + The following types of administration commands are not accepted + during recovery mode: + + <itemizedlist> + <listitem> + <para> + Data Definition Language (DDL): e.g., <command>CREATE INDEX</command> + </para> + </listitem> + <listitem> + <para> + Privilege and Ownership: <command>GRANT</command>, <command>REVOKE</command>, + <command>REASSIGN</command> + </para> + </listitem> + <listitem> + <para> + Maintenance commands: <command>ANALYZE</command>, <command>VACUUM</command>, + <command>CLUSTER</command>, <command>REINDEX</command> + </para> + </listitem> + </itemizedlist> + </para> + + <para> + Again, note that some of these commands are actually allowed during + "read only" mode transactions on the primary. + </para> + + <para> + As a result, you cannot create additional indexes that exist solely + on the standby, nor statistics that exist solely on the standby. + If these administration commands are needed, they should be executed + on the primary, and eventually those changes will propagate to the + standby. + </para> + + <para> + <function>pg_cancel_backend()</function> + and <function>pg_terminate_backend()</function> will work on user backends, + but not the startup process, which performs + recovery. <structname>pg_stat_activity</structname> does not show + recovering transactions as active. As a result, + <structname>pg_prepared_xacts</structname> is always empty during + recovery. If you wish to resolve in-doubt prepared transactions, view + <literal>pg_prepared_xacts</literal> on the primary and issue commands to + resolve transactions there or resolve them after the end of recovery. + </para> + + <para> + <structname>pg_locks</structname> will show locks held by backends, + as normal. <structname>pg_locks</structname> also shows + a virtual transaction managed by the startup process that owns all + <literal>AccessExclusiveLocks</literal> held by transactions being replayed by recovery. + Note that the startup process does not acquire locks to + make database changes, and thus locks other than <literal>AccessExclusiveLocks</literal> + do not show in <structname>pg_locks</structname> for the Startup + process; they are just presumed to exist. + </para> + + <para> + The <productname>Nagios</productname> plugin <productname>check_pgsql</productname> will + work, because the simple information it checks for exists. + The <productname>check_postgres</productname> monitoring script will also work, + though some reported values could give different or confusing results. + For example, last vacuum time will not be maintained, since no + vacuum occurs on the standby. Vacuums running on the primary + do still send their changes to the standby. + </para> + + <para> + WAL file control commands will not work during recovery, + e.g., <function>pg_backup_start</function>, <function>pg_switch_wal</function> etc. + </para> + + <para> + Dynamically loadable modules work, including <structname>pg_stat_statements</structname>. + </para> + + <para> + Advisory locks work normally in recovery, including deadlock detection. + Note that advisory locks are never WAL logged, so it is impossible for + an advisory lock on either the primary or the standby to conflict with WAL + replay. Nor is it possible to acquire an advisory lock on the primary + and have it initiate a similar advisory lock on the standby. Advisory + locks relate only to the server on which they are acquired. + </para> + + <para> + Trigger-based replication systems such as <productname>Slony</productname>, + <productname>Londiste</productname> and <productname>Bucardo</productname> won't run on the + standby at all, though they will run happily on the primary server as + long as the changes are not sent to standby servers to be applied. + WAL replay is not trigger-based so you cannot relay from the + standby to any system that requires additional database writes or + relies on the use of triggers. + </para> + + <para> + New OIDs cannot be assigned, though some <acronym>UUID</acronym> generators may still + work as long as they do not rely on writing new status to the database. + </para> + + <para> + Currently, temporary table creation is not allowed during read-only + transactions, so in some cases existing scripts will not run correctly. + This restriction might be relaxed in a later release. This is + both an SQL standard compliance issue and a technical issue. + </para> + + <para> + <command>DROP TABLESPACE</command> can only succeed if the tablespace is empty. + Some standby users may be actively using the tablespace via their + <varname>temp_tablespaces</varname> parameter. If there are temporary files in the + tablespace, all active queries are canceled to ensure that temporary + files are removed, so the tablespace can be removed and WAL replay + can continue. + </para> + + <para> + Running <command>DROP DATABASE</command> or <command>ALTER DATABASE ... SET + TABLESPACE</command> on the primary + will generate a WAL entry that will cause all users connected to that + database on the standby to be forcibly disconnected. This action occurs + immediately, whatever the setting of + <varname>max_standby_streaming_delay</varname>. Note that + <command>ALTER DATABASE ... RENAME</command> does not disconnect users, which + in most cases will go unnoticed, though might in some cases cause a + program confusion if it depends in some way upon database name. + </para> + + <para> + In normal (non-recovery) mode, if you issue <command>DROP USER</command> or <command>DROP ROLE</command> + for a role with login capability while that user is still connected then + nothing happens to the connected user — they remain connected. The user cannot + reconnect however. This behavior applies in recovery also, so a + <command>DROP USER</command> on the primary does not disconnect that user on the standby. + </para> + + <para> + The cumulative statistics system is active during recovery. All scans, + reads, blocks, index usage, etc., will be recorded normally on the + standby. However, WAL replay will not increment relation and database + specific counters. I.e. replay will not increment pg_stat_all_tables + columns (like n_tup_ins), nor will reads or writes performed by the + startup process be tracked in the pg_statio views, nor will associated + pg_stat_database columns be incremented. + </para> + + <para> + Autovacuum is not active during recovery. It will start normally at the + end of recovery. + </para> + + <para> + The checkpointer process and the background writer process are active during + recovery. The checkpointer process will perform restartpoints (similar to + checkpoints on the primary) and the background writer process will perform + normal block cleaning activities. This can include updates of the hint bit + information stored on the standby server. + The <command>CHECKPOINT</command> command is accepted during recovery, + though it performs a restartpoint rather than a new checkpoint. + </para> + </sect2> + + <sect2 id="hot-standby-parameters"> + <title>Hot Standby Parameter Reference</title> + + <para> + Various parameters have been mentioned above in + <xref linkend="hot-standby-conflict"/> and + <xref linkend="hot-standby-admin"/>. + </para> + + <para> + On the primary, the <xref linkend="guc-wal-level"/> parameter can be used. + <xref linkend="guc-max-standby-archive-delay"/> and + <xref linkend="guc-max-standby-streaming-delay"/> have no effect if set on + the primary. + </para> + + <para> + On the standby, parameters <xref linkend="guc-hot-standby"/>, + <xref linkend="guc-max-standby-archive-delay"/> and + <xref linkend="guc-max-standby-streaming-delay"/> can be used. + </para> + </sect2> + + <sect2 id="hot-standby-caveats"> + <title>Caveats</title> + + <para> + There are several limitations of hot standby. + These can and probably will be fixed in future releases: + + <itemizedlist> + <listitem> + <para> + Full knowledge of running transactions is required before snapshots + can be taken. Transactions that use large numbers of subtransactions + (currently greater than 64) will delay the start of read-only + connections until the completion of the longest running write transaction. + If this situation occurs, explanatory messages will be sent to the server log. + </para> + </listitem> + <listitem> + <para> + Valid starting points for standby queries are generated at each + checkpoint on the primary. If the standby is shut down while the primary + is in a shutdown state, it might not be possible to re-enter hot standby + until the primary is started up, so that it generates further starting + points in the WAL logs. This situation isn't a problem in the most + common situations where it might happen. Generally, if the primary is + shut down and not available anymore, that's likely due to a serious + failure that requires the standby being converted to operate as + the new primary anyway. And in situations where the primary is + being intentionally taken down, coordinating to make sure the standby + becomes the new primary smoothly is also standard procedure. + </para> + </listitem> + <listitem> + <para> + At the end of recovery, <literal>AccessExclusiveLocks</literal> held by prepared transactions + will require twice the normal number of lock table entries. If you plan + on running either a large number of concurrent prepared transactions + that normally take <literal>AccessExclusiveLocks</literal>, or you plan on having one + large transaction that takes many <literal>AccessExclusiveLocks</literal>, you are + advised to select a larger value of <varname>max_locks_per_transaction</varname>, + perhaps as much as twice the value of the parameter on + the primary server. You need not consider this at all if + your setting of <varname>max_prepared_transactions</varname> is 0. + </para> + </listitem> + <listitem> + <para> + The Serializable transaction isolation level is not yet available in hot + standby. (See <xref linkend="xact-serializable"/> and + <xref linkend="serializable-consistency"/> for details.) + An attempt to set a transaction to the serializable isolation level in + hot standby mode will generate an error. + </para> + </listitem> + </itemizedlist> + + </para> + </sect2> + + </sect1> + +</chapter> |