Commit 00f15338 authored by Alvaro Herrera's avatar Alvaro Herrera

Preserve commit timestamps across clean restart

An oversight in setting the boundaries of known commit timestamps during
startup caused old commit timestamps to become inaccessible after a
server restart.

Author and reporter: Julien Rouhaud
Review, test code: Craig Ringer
parent 7d80417d
...@@ -844,6 +844,8 @@ SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact) ...@@ -844,6 +844,8 @@ SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
else else
{ {
Assert(ShmemVariableCache->newestCommitTsXid == InvalidTransactionId); Assert(ShmemVariableCache->newestCommitTsXid == InvalidTransactionId);
ShmemVariableCache->oldestCommitTsXid = oldestXact;
ShmemVariableCache->newestCommitTsXid = newestXact;
} }
LWLockRelease(CommitTsLock); LWLockRelease(CommitTsLock);
} }
......
# Testing of commit timestamps preservation across clean restarts
use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 16;
my $node_master = get_new_node('master');
$node_master->init(allows_streaming => 1);
$node_master->append_conf(
'postgresql.conf', qq(
track_commit_timestamp = on
));
$node_master->start;
my ($ret, $stdout, $stderr);
($ret, $stdout, $stderr) =
$node_master->psql('postgres', qq[SELECT pg_xact_commit_timestamp('0');]);
is($ret, 3, 'getting ts of InvalidTransactionId reports error');
like(
$stderr,
qr/cannot retrieve commit timestamp for transaction/,
'expected error from InvalidTransactionId');
($ret, $stdout, $stderr) =
$node_master->psql('postgres', qq[SELECT pg_xact_commit_timestamp('1');]);
is($ret, 3, 'getting ts of BootstrapTransactionId reports error');
like(
$stderr,
qr/cannot retrieve commit timestamp for transaction/,
'expected error from BootstrapTransactionId');
($ret, $stdout, $stderr) =
$node_master->psql('postgres', qq[SELECT pg_xact_commit_timestamp('2');]);
is($ret, 3, 'getting ts of FrozenTransactionId reports error');
like(
$stderr,
qr/cannot retrieve commit timestamp for transaction/,
'expected error from FrozenTransactionId');
# Since FirstNormalTransactionId will've occurred during initdb, long before we
# enabled commit timestamps, it'll be null since we have no cts data for it but
# cts are enabled.
is( $node_master->safe_psql(
'postgres', qq[SELECT pg_xact_commit_timestamp('3');]),
'',
'committs for FirstNormalTransactionId is null');
$node_master->safe_psql('postgres',
qq[CREATE TABLE committs_test(x integer, y timestamp with time zone);]);
my $xid = $node_master->safe_psql(
'postgres', qq[
BEGIN;
INSERT INTO committs_test(x, y) VALUES (1, current_timestamp);
SELECT txid_current();
COMMIT;
]);
my $before_restart_ts = $node_master->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid');]);
ok($before_restart_ts != '' && $before_restart_ts != 'null',
'commit timestamp recorded');
$node_master->stop('immediate');
$node_master->start;
my $after_crash_ts = $node_master->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid');]);
is($after_crash_ts, $before_restart_ts,
'timestamps before and after crash are equal');
$node_master->stop('fast');
$node_master->start;
my $after_restart_ts = $node_master->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid');]);
is($after_restart_ts, $before_restart_ts,
'timestamps before and after restart are equal');
# Now disable commit timestamps
$node_master->append_conf(
'postgresql.conf', qq(
track_commit_timestamp = off
));
$node_master->stop('fast');
$node_master->start;
($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');
like(
$stderr,
qr/could not get commit timestamp data/,
'expected error from enabled tx when committs disabled');
# Do a tx while cts disabled
my $xid_disabled = $node_master->safe_psql(
'postgres', qq[
BEGIN;
INSERT INTO committs_test(x, y) VALUES (2, current_timestamp);
SELECT txid_current();
COMMIT;
]);
# Should be inaccessible
($ret, $stdout, $stderr) = $node_master->psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid_disabled');]);
is($ret, 3, 'no commit timestamp when disabled');
like(
$stderr,
qr/could not get commit timestamp data/,
'expected error from disabled tx when committs disabled');
# Re-enable, restart and ensure we can still get the old timestamps
$node_master->append_conf(
'postgresql.conf', qq(
track_commit_timestamp = on
));
$node_master->stop('fast');
$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');
my $after_enable_disabled_ts = $node_master->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid_disabled');]);
is($after_enable_disabled_ts, '',
'timestamp of disabled tx null after re-enable');
$node_master->stop;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment