diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index 73fac1ba81..599203c96c 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -573,10 +573,9 @@ CompleteCommitTsInitialization(void) * any leftover data. * * Conversely, we activate the module if the feature is enabled. This is - * not necessary in a master system because we already did it earlier, but - * if we're in a standby server that got promoted which had the feature - * enabled and was following a master that had the feature disabled, this - * is where we turn it on locally. + * necessary for primary and standby as the activation depends on the + * control file contents at the beginning of recovery or when a + * XLOG_PARAMETER_CHANGE is replayed. */ if (!track_commit_timestamp) DeactivateCommitTs(); @@ -586,7 +585,7 @@ CompleteCommitTsInitialization(void) /* * Activate or deactivate CommitTs' upon reception of a XLOG_PARAMETER_CHANGE - * XLog record in a standby. + * XLog record during recovery. */ void CommitTsParameterChange(bool newvalue, bool oldvalue) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 986e8195a3..9331306cba 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6775,11 +6775,12 @@ StartupXLOG(void) StartupMultiXact(); /* - * Ditto commit timestamps. In a standby, we do it if setting is enabled - * in ControlFile; in a master we base the decision on the GUC itself. + * Ditto for commit timestamps. Activate the facility if the setting is + * enabled in the control file, as there should be no tracking of commit + * timestamps done when the setting was disabled. This facility can be + * started or stopped when replaying a XLOG_PARAMETER_CHANGE record. */ - if (ArchiveRecoveryRequested ? - ControlFile->track_commit_timestamp : track_commit_timestamp) + if (ControlFile->track_commit_timestamp) StartupCommitTs(); /* diff --git a/src/test/modules/commit_ts/t/004_restart.pl b/src/test/modules/commit_ts/t/004_restart.pl index daf42d3a02..241b0b08dc 100644 --- a/src/test/modules/commit_ts/t/004_restart.pl +++ b/src/test/modules/commit_ts/t/004_restart.pl @@ -1,4 +1,4 @@ -# Testing of commit timestamps preservation across clean restarts +# Testing of commit timestamps preservation across restarts use strict; use warnings; use PostgresNode; @@ -71,12 +71,36 @@ is($after_restart_ts, $before_restart_ts, 'timestamps before and after restart are equal'); # Now disable commit timestamps - $node_master->append_conf('postgresql.conf', 'track_commit_timestamp = off'); - $node_master->stop('fast'); + +# Start the server, which generates a XLOG_PARAMETER_CHANGE record where +# the parameter change is registered. $node_master->start; +# Now restart again the server so as no XLOG_PARAMETER_CHANGE record are +# replayed with the follow-up immediate shutdown. +$node_master->restart; + +# Move commit timestamps across page boundaries. Things should still +# be able to work across restarts with those transactions committed while +# track_commit_timestamp is disabled. +$node_master->safe_psql('postgres', +qq(CREATE PROCEDURE consume_xid(cnt int) +AS \$\$ +DECLARE + i int; + BEGIN + FOR i in 1..cnt LOOP + EXECUTE 'SELECT txid_current()'; + COMMIT; + END LOOP; + END; +\$\$ +LANGUAGE plpgsql; +)); +$node_master->safe_psql('postgres', 'CALL consume_xid(2000)'); + ($ret, $stdout, $stderr) = $node_master->psql('postgres', qq[SELECT pg_xact_commit_timestamp('$xid');]); is($ret, 3, 'no commit timestamp from enable tx when cts disabled'); @@ -106,10 +130,12 @@ like( # Re-enable, restart and ensure we can still get the old timestamps $node_master->append_conf('postgresql.conf', 'track_commit_timestamp = on'); -$node_master->stop('fast'); +# An immediate shutdown is used here. At next startup recovery will +# replay transactions which committed when track_commit_timestamp was +# disabled, and the facility should be able to work properly. +$node_master->stop('immediate'); $node_master->start; - my $after_enable_ts = $node_master->safe_psql('postgres', qq[SELECT pg_xact_commit_timestamp('$xid');]); is($after_enable_ts, '', 'timestamp of enabled tx null after re-enable');