This is another bit of the syncrep patch split out. I will revisit the replication timeout one Real Soon, I promise -- but I have a couple things to do today that may delay that until the evening.
https://github.com/fdr/postgres/commit/ad3ce9ac62f0e128d7d1fd20d47184f867056af1 Context diff supplied here. Note that this information is not exposed via catalog in the original syncrep patch, and is not here. Do we want that kind of reporting? -- fdr
*** a/doc/src/sgml/config.sgml --- b/doc/src/sgml/config.sgml *************** *** 2029,2034 **** SET ENABLE_SEQSCAN TO OFF; --- 2029,2038 ---- This parameter can only be set in the <filename>postgresql.conf</> file or on the server command line. </para> + <para> + You should also consider setting <varname>hot_standby_feedback</> + as an alternative to using this parameter. + </para> </listitem> </varlistentry> </variablelist> *************** *** 2121,2126 **** SET ENABLE_SEQSCAN TO OFF; --- 2125,2145 ---- </listitem> </varlistentry> + <varlistentry id="guc-hot-standby-feedback" xreflabel="hot_standby"> + <term><varname>hot_standby_feedback</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>hot_standby_feedback</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Specifies whether or not a hot standby will send feedback to the primary + about queries currently executing on the standby. This parameter can + be used to eliminate query cancels caused by cleanup records, though + it can cause database bloat on the primary for some workloads. + The default value is <literal>off</literal>. + This parameter can only be set at server start. It only has effect + if <varname>hot_standby</> is enabled. + <varlistentry id="guc-replication-timeout-server" xreflabel="replication_timeout_server"> <term><varname>replication_timeout_server</varname> (<type>integer</type>)</term> <indexterm> *** a/doc/src/sgml/high-availability.sgml --- b/doc/src/sgml/high-availability.sgml *************** *** 1393,1403 **** if (!triggered) These conflicts are <emphasis>hard conflicts</> in the sense that queries might need to be cancelled 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</> commands and various <acronym>DDL</> actions, conflict with table accesses in standby queries. --- 1393,1410 ---- These conflicts are <emphasis>hard conflicts</> in the sense that queries might need to be cancelled and, in some cases, sessions disconnected to resolve them. The user is provided with several ways to handle these ! conflicts. Conflict cases in order of likely frequency are: <itemizedlist> <listitem> <para> + Application of a vacuum cleanup record from WAL conflicts with + standby transactions whose snapshots can still <quote>see</> any of + the rows to be removed. + </para> + </listitem> + <listitem> + <para> Access Exclusive locks taken on the primary server, including both explicit <command>LOCK</> commands and various <acronym>DDL</> actions, conflict with table accesses in standby queries. *************** *** 1417,1432 **** if (!triggered) </listitem> <listitem> <para> ! Application of a vacuum cleanup record from WAL conflicts with ! standby transactions whose snapshots can still <quote>see</> 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> --- 1424,1433 ---- </listitem> <listitem> <para> ! Buffer pin deadlock caused by 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> *************** *** 1539,1555 **** if (!triggered) <para> Remedial possibilities exist if the number of standby-query cancellations ! is found to be unacceptable. The first option is to connect to the ! primary server and keep a query active for as long as needed to ! run queries on the standby. This prevents <command>VACUUM</> from removing ! recently-dead rows and so cleanup conflicts do not occur. ! This could be done using <xref linkend="dblink"> and ! <function>pg_sleep()</>, or via other mechanisms. 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. <varname>max_standby_archive_delay</> must be kept large in this case, because delayed WAL files might already contain entries that conflict with the desired standby queries. --- 1540,1555 ---- <para> Remedial possibilities exist if the number of standby-query cancellations ! is found to be unacceptable. Typically the best option is to enable ! <varname>hot_standby_feedback</>. This prevents <command>VACUUM</> 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. You are still getting the benefit ! of off-loading execution onto the standby and the query may complete ! faster than it would have done on the primary server. <varname>max_standby_archive_delay</> must be kept large in this case, because delayed WAL files might already contain entries that conflict with the desired standby queries. *** a/src/backend/access/transam/xlog.c --- b/src/backend/access/transam/xlog.c *************** *** 76,81 **** bool fullPageWrites = true; --- 76,82 ---- bool log_checkpoints = false; int sync_method = DEFAULT_SYNC_METHOD; int wal_level = WAL_LEVEL_MINIMAL; + bool hot_standby_feedback; #ifdef WAL_DEBUG bool XLOG_DEBUG = false; *************** *** 6159,6164 **** StartupXLOG(void) --- 6160,6172 ---- if (XLByteLT(ControlFile->minRecoveryPoint, checkPoint.redo)) ControlFile->minRecoveryPoint = checkPoint.redo; } + else + { + /* + * No need to calculate feedback if we're not in Hot Standby. + */ + hot_standby_feedback = false; + } /* * set backupStartupPoint if we're starting archive recovery from a *** a/src/backend/replication/walreceiver.c --- b/src/backend/replication/walreceiver.c *************** *** 38,43 **** --- 38,44 ---- #include <signal.h> #include <unistd.h> + #include "access/transam.h" #include "access/xlog_internal.h" #include "libpq/pqsignal.h" #include "miscadmin.h" *************** *** 45,50 **** --- 46,52 ---- #include "replication/walreceiver.h" #include "storage/ipc.h" #include "storage/pmsignal.h" + #include "storage/procarray.h" #include "utils/builtins.h" #include "utils/guc.h" #include "utils/memutils.h" *************** *** 609,614 **** XLogWalRcvSendReply(void) --- 611,620 ---- reply_message.flush = LogstreamResult.Flush; reply_message.apply = GetXLogReplayRecPtr(); reply_message.sendTime = now; + if (hot_standby_feedback) + reply_message.xmin = GetOldestXmin(true, false); + else + reply_message.xmin = InvalidTransactionId; elog(DEBUG2, "sending write %X/%X flush %X/%X apply %X/%X", reply_message.write.xlogid, reply_message.write.xrecoff, *** a/src/backend/replication/walsender.c --- b/src/backend/replication/walsender.c *************** *** 551,556 **** ProcessStandbyReplyMessage(void) --- 551,559 ---- walsnd->write = reply.write; walsnd->flush = reply.flush; walsnd->apply = reply.apply; + if (TransactionIdIsValid(reply.xmin) && + TransactionIdPrecedes(MyProc->xmin, reply.xmin)) + MyProc->xmin = reply.xmin; SpinLockRelease(&walsnd->mutex); } } *** a/src/include/access/xlog.h --- b/src/include/access/xlog.h *************** *** 326,329 **** extern void do_pg_abort_backup(void); --- 326,332 ---- #define BACKUP_LABEL_FILE "backup_label" #define BACKUP_LABEL_OLD "backup_label.old" + /* Indicates that the hot standby should send feedback */ + extern bool hot_standby_feedback; + #endif /* XLOG_H */ *** a/src/include/replication/walprotocol.h --- b/src/include/replication/walprotocol.h *************** *** 56,61 **** typedef struct --- 56,68 ---- XLogRecPtr flush; XLogRecPtr apply; + /* + * The current xmin from the standby, for Hot Standby feedback. + * This may be invalid if the standby-side does not support feedback, + * or Hot Standby is not yet available. + */ + TransactionId xmin; + /* Sender's system clock at the time of transmission */ TimestampTz sendTime; } StandbyReplyMessage;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers