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
This commit is contained in:
parent
7d80417d3d
commit
00f15338b2
@ -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);
|
||||||
}
|
}
|
||||||
|
137
src/test/modules/commit_ts/t/004_restart.pl
Normal file
137
src/test/modules/commit_ts/t/004_restart.pl
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# 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;
|
Loading…
x
Reference in New Issue
Block a user