1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Allow read only connections during recovery, known as Hot Standby.

Enabled by recovery_connections = on (default) and forcing archive recovery using a recovery.conf. Recovery processing now emulates the original transactions as they are replayed, providing full locking and MVCC behaviour for read only queries. Recovery must enter consistent state before connections are allowed, so there is a delay, typically short, before connections succeed. Replay of recovering transactions can conflict and in some cases deadlock with queries during recovery; these result in query cancellation after max_standby_delay seconds have expired. Infrastructure changes have minor effects on normal running, though introduce four new types of WAL record.

New test mode "make standbycheck" allows regression tests of static command behaviour on a standby server while in recovery. Typical and extreme dynamic behaviours have been checked via code inspection and manual testing. Few port specific behaviours have been utilised, though primary testing has been on Linux only so far.

This commit is the basic patch. Additional changes will follow in this release to enhance some aspects of behaviour, notably improved handling of conflicts, deadlock detection and query cancellation. Changes to VACUUM FULL are also required.

Simon Riggs, with significant and lengthy review by Heikki Linnakangas, including streamlined redesign of snapshot creation and two-phase commit.

Important contributions from Florian Pflug, Mark Kirkwood, Merlin Moncure, Greg Stark, Gianni Ciolli, Gabriele Bartolini, Hannu Krosing, Robert Haas, Tatsuo Ishii, Hiroyuki Yamada plus support and feedback from many other community members.
This commit is contained in:
Simon Riggs
2009-12-19 01:32:45 +00:00
parent 78a09145e0
commit efc16ea520
87 changed files with 6165 additions and 428 deletions

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.527 2009/12/11 03:34:56 itagaki Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.528 2009/12/19 01:32:37 sriggs Exp $
*
*--------------------------------------------------------------------
*/
@ -114,6 +114,9 @@ extern char *default_tablespace;
extern char *temp_tablespaces;
extern bool synchronize_seqscans;
extern bool fullPageWrites;
extern int vacuum_defer_cleanup_age;
int trace_recovery_messages = LOG;
#ifdef TRACE_SORT
extern bool trace_sort;
@ -1206,6 +1209,17 @@ static struct config_bool ConfigureNamesBool[] =
false, NULL, NULL
},
{
{"recovery_connections", PGC_POSTMASTER, WAL_SETTINGS,
gettext_noop("During recovery, allows connections and queries. "
" During normal running, causes additional info to be written"
" to WAL to enable hot standby mode on WAL standby nodes."),
NULL
},
&XLogRequestRecoveryConnections,
true, NULL, NULL
},
{
{"allow_system_table_mods", PGC_POSTMASTER, DEVELOPER_OPTIONS,
gettext_noop("Allows modifications of the structure of system tables."),
@ -1347,6 +1361,8 @@ static struct config_int ConfigureNamesInt[] =
* plus autovacuum_max_workers plus one (for the autovacuum launcher).
*
* Likewise we have to limit NBuffers to INT_MAX/2.
*
* See also CheckRequiredParameterValues() if this parameter changes
*/
{
{"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
@ -1357,6 +1373,15 @@ static struct config_int ConfigureNamesInt[] =
100, 1, INT_MAX / 4, assign_maxconnections, NULL
},
{
{"max_standby_delay", PGC_SIGHUP, WAL_SETTINGS,
gettext_noop("Sets the maximum delay to avoid conflict processing on Hot Standby servers."),
NULL
},
&MaxStandbyDelay,
30, -1, INT_MAX, NULL, NULL
},
{
{"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
gettext_noop("Sets the number of connection slots reserved for superusers."),
@ -1514,6 +1539,9 @@ static struct config_int ConfigureNamesInt[] =
1000, 25, INT_MAX, NULL, NULL
},
/*
* See also CheckRequiredParameterValues() if this parameter changes
*/
{
{"max_prepared_transactions", PGC_POSTMASTER, RESOURCES,
gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
@ -1572,6 +1600,18 @@ static struct config_int ConfigureNamesInt[] =
150000000, 0, 2000000000, NULL, NULL
},
{
{"vacuum_defer_cleanup_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
gettext_noop("Age by which VACUUM and HOT cleanup should be deferred, if any."),
NULL
},
&vacuum_defer_cleanup_age,
0, 0, 1000000, NULL, NULL
},
/*
* See also CheckRequiredParameterValues() if this parameter changes
*/
{
{"max_locks_per_transaction", PGC_POSTMASTER, LOCK_MANAGEMENT,
gettext_noop("Sets the maximum number of locks per transaction."),
@ -2684,6 +2724,16 @@ static struct config_enum ConfigureNamesEnum[] =
assign_session_replication_role, NULL
},
{
{"trace_recovery_messages", PGC_SUSET, LOGGING_WHEN,
gettext_noop("Sets the message levels that are logged during recovery."),
gettext_noop("Each level includes all the levels that follow it. The later"
" the level, the fewer messages are sent.")
},
&trace_recovery_messages,
DEBUG1, server_message_level_options, NULL, NULL
},
{
{"track_functions", PGC_SUSET, STATS_COLLECTOR,
gettext_noop("Collects function-level statistics on database activity."),
@ -7511,6 +7561,18 @@ assign_transaction_read_only(bool newval, bool doit, GucSource source)
if (source != PGC_S_OVERRIDE)
return false;
}
/* Can't go to r/w mode while recovery is still active */
if (newval == false && XactReadOnly && RecoveryInProgress())
{
ereport(GUC_complaint_elevel(source),
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot set transaction read-write mode during recovery")));
/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
if (source != PGC_S_OVERRIDE)
return false;
}
return true;
}