From 4f3924d9cd438ba4e6fd639460f8c859c65d45a3 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 9 Mar 2015 17:44:00 -0300 Subject: Keep CommitTs module in sync in standby and master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allow this module to be turned off on restarts, so a restart time check is enough to activate or deactivate the module; however, if there is a standby replaying WAL emitted from a master which is restarted, but the standby isn't, the state in the standby becomes inconsistent and can easily be crashed. Fix by activating and deactivating the module during WAL replay on parameter change as well as on system start. Problem reported by Fujii Masao in http://www.postgresql.org/message-id/CAHGQGwFhJ3CnHo1CELEfay18yg_RA-XZT-7D8NuWUoYSZ90r4Q@mail.gmail.com Author: Petr JelĂ­nek --- src/backend/access/transam/xlog.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src/backend/access/transam/xlog.c') diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index a28155f977d..71cbe0ef687 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5688,6 +5688,19 @@ do { \ minValue))); \ } while(0) +#define RecoveryRequiresBoolParameter(param_name, currValue, masterValue) \ +do { \ + bool _currValue = (currValue); \ + bool _masterValue = (masterValue); \ + if (_currValue != _masterValue) \ + ereport(ERROR, \ + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), \ + errmsg("hot standby is not possible because it requires \"%s\" to be same on master and standby (master has \"%s\", standby has \"%s\")", \ + param_name, \ + _masterValue ? "true" : "false", \ + _currValue ? "true" : "false"))); \ +} while(0) + /* * Check to see if required parameters are set high enough on this server * for various aspects of recovery operation. @@ -5730,6 +5743,9 @@ CheckRequiredParameterValues(void) RecoveryRequiresIntParameter("max_locks_per_transaction", max_locks_per_xact, ControlFile->max_locks_per_xact); + RecoveryRequiresBoolParameter("track_commit_timestamp", + track_commit_timestamp, + ControlFile->track_commit_timestamp); } } @@ -9118,7 +9134,6 @@ xlog_redo(XLogReaderState *record) ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact; ControlFile->wal_level = xlrec.wal_level; ControlFile->wal_log_hints = xlrec.wal_log_hints; - ControlFile->track_commit_timestamp = xlrec.track_commit_timestamp; /* * Update minRecoveryPoint to ensure that if recovery is aborted, we @@ -9136,6 +9151,25 @@ xlog_redo(XLogReaderState *record) ControlFile->minRecoveryPointTLI = ThisTimeLineID; } + /* + * Update the commit timestamp tracking. If there was a change + * it needs to be activated or deactivated accordingly. + */ + if (track_commit_timestamp != xlrec.track_commit_timestamp) + { + track_commit_timestamp = xlrec.track_commit_timestamp; + ControlFile->track_commit_timestamp = track_commit_timestamp; + if (track_commit_timestamp) + ActivateCommitTs(); + else + /* + * We can't create a new WAL record here, but that's OK as + * master did the WAL logging already and we will replay the + * record from master in case we crash. + */ + DeactivateCommitTs(false); + } + UpdateControlFile(); LWLockRelease(ControlFileLock); -- cgit v1.2.3