mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
The txid_XXX family of fmgr functions exposes 64 bit transaction IDs to users as int8. Now that we have an SQL type xid8 for FullTransactionId, define a new set of functions including pg_current_xact_id() and pg_current_snapshot() based on that. Keep the old functions around too, for now. It's a bit sneaky to use the same C functions for both, but since the binary representation is identical except for the signedness of the type, and since older functions are the ones using the wrong signedness, and since we'll presumably drop the older ones after a reasonable period of time, it seems reasonable to switch to FullTransactionId internally and share the code for both. Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com> Reviewed-by: Takao Fujii <btfujiitkp@oss.nttdata.com> Reviewed-by: Yoshikazu Imai <imai.yoshikazu@fujitsu.com> Reviewed-by: Mark Dilger <mark.dilger@enterprisedb.com> Discussion: https://postgr.es/m/20190725000636.666m5mad25wfbrri%40alap3.anarazel.de
150 lines
4.9 KiB
Perl
150 lines
4.9 KiB
Perl
# Testing of commit timestamps preservation across 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', '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, 0, 'getting ts of BootstrapTransactionId succeeds');
|
|
is($stdout, '', 'timestamp of BootstrapTransactionId is null');
|
|
|
|
($ret, $stdout, $stderr) =
|
|
$node_master->psql('postgres', qq[SELECT pg_xact_commit_timestamp('2');]);
|
|
is($ret, 0, 'getting ts of FrozenTransactionId succeeds');
|
|
is($stdout, '', 'timestamp of FrozenTransactionId is null');
|
|
|
|
# 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 pg_current_xact_id()::xid;
|
|
COMMIT;
|
|
]);
|
|
|
|
my $before_restart_ts = $node_master->safe_psql('postgres',
|
|
qq[SELECT pg_xact_commit_timestamp('$xid');]);
|
|
ok($before_restart_ts ne '' && $before_restart_ts ne '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', '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 pg_current_xact_id()';
|
|
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');
|
|
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 pg_current_xact_id();
|
|
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', 'track_commit_timestamp = on');
|
|
|
|
# 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');
|
|
|
|
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;
|