# Copyright (c) 2021-2025, PostgreSQL Global Development Group
# Testing of commit timestamps preservation across restarts
use strict;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
($ret, $stdout, $stderr) =
$node_primary->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_primary->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_primary->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_primary->safe_psql( 'postgres', qq[SELECT pg_xact_commit_timestamp('3');]), '', 'committs for FirstNormalTransactionId is null');
$node_primary->safe_psql('postgres',
qq[CREATE TABLE committs_test(x integer, y timestamp with time zone);]);
my $xid = $node_primary->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_primary->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid');]);
ok($before_restart_ts ne '' && $before_restart_ts ne 'null', 'commit timestamp recorded');
my $after_crash_ts = $node_primary->safe_psql('postgres',
qq[SELECT pg_xact_commit_timestamp('$xid');]);
is($after_crash_ts, $before_restart_ts, 'timestamps before and after crash are equal');
my $after_restart_ts = $node_primary->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_primary->append_conf('postgresql.conf', 'track_commit_timestamp = off');
$node_primary->stop('fast');
# Start the server, which generates a XLOG_PARAMETER_CHANGE record where # the parameter change is registered.
$node_primary->start;
# Now restart again the server so as no XLOG_PARAMETER_CHANGE record are # replayed with the follow-up immediate shutdown.
$node_primary->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_primary->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_primary->safe_psql('postgres', 'CALL consume_xid(2000)');
($ret, $stdout, $stderr) = $node_primary->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_primary->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_primary->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_primary->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_primary->stop('immediate');
$node_primary->start;
my $after_enable_ts = $node_primary->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_primary->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_primary->stop;
done_testing();
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-08-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.