mirror of https://github.com/postgres/postgres
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 Ringerpull/17/head
parent
7d80417d3d
commit
00f15338b2
@ -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…
Reference in new issue