From 3d4216d85f42d9f011001367d5f962ca8d1d72e2 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Wed, 5 Aug 2026 11:34:29 +0900 Subject: [PATCH] Clarify wraparound warning percentage messages Commit e646450e609 added DETAIL messages for XID and MultiXactId wraparound warnings that described the reported percentage as the percentage of IDs available for use. However, the percentage is actually calculated from the remaining distance to the wraparound limit, not the stop limit where new IDs are refused. As a result, the wording could be misinterpreted as meaning that the reported percentage of IDs can still be allocated. Update the wording to clarify that the reported percentage represents the remaining transaction ID space or MultiXactId space before wraparound. Also update the related XID warning hints to use "transaction ID" terminology consistently. Backpatch to v19, where the DETAIL messages were added. Author: Fujii Masao Reviewed-by: Bharath Rupireddy Reviewed-by: Kyotaro Horiguchi Reviewed-by: Nathan Bossart Reviewed-by: Yugo Nagata Discussion: https://postgr.es/m/CAHGQGwHWZTsR6bjdfpa+pOkBPjoXXm2LuJ+5nh+CvdyqEASHcQ@mail.gmail.com Backpatch-through: 19 --- doc/src/sgml/maintenance.sgml | 4 ++-- src/backend/access/transam/multixact.c | 8 ++++---- src/backend/access/transam/varsup.c | 14 +++++++------- src/test/modules/xid_wraparound/t/002_limits.pl | 3 ++- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 0eec6e2e888..75749ea145c 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -674,8 +674,8 @@ SELECT datname, age(datfrozenxid) FROM pg_database; WARNING: database "mydb" must be vacuumed within 99985967 transactions -DETAIL: Approximately 4.66% of transaction IDs are available for use. -HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database. +DETAIL: Approximately 4.66% of transaction ID space remains before wraparound. +HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database. (A manual VACUUM should fix the problem, as suggested by the diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 8c694658132..424516dc106 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1070,7 +1070,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset) multiWrapLimit - result, oldest_datname, multiWrapLimit - result), - errdetail("Approximately %.2f%% of MultiXactIds are available for use.", + errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.", (double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100), errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions."))); @@ -1081,7 +1081,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset) multiWrapLimit - result, oldest_datoid, multiWrapLimit - result), - errdetail("Approximately %.2f%% of MultiXactIds are available for use.", + errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.", (double) (multiWrapLimit - result) / (MaxMultiXactId / 2) * 100), errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions."))); @@ -2208,7 +2208,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid) multiWrapLimit - curMulti, oldest_datname, multiWrapLimit - curMulti), - errdetail("Approximately %.2f%% of MultiXactIds are available for use.", + errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.", (double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100), errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions."))); @@ -2219,7 +2219,7 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid) multiWrapLimit - curMulti, oldest_datoid, multiWrapLimit - curMulti), - errdetail("Approximately %.2f%% of MultiXactIds are available for use.", + errdetail("Approximately %.2f%% of MultiXactId space remains before wraparound.", (double) (multiWrapLimit - curMulti) / (MaxMultiXactId / 2) * 100), errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions."))); diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index dc5e32d86f3..cb68d8fa974 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -166,7 +166,7 @@ GetNewTransactionId(bool isSubXact) (errmsg("database \"%s\" must be vacuumed within %u transactions", oldest_datname, xidWrapLimit - xid), - errdetail("Approximately %.2f%% of transaction IDs are available for use.", + errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.", (double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100), errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); @@ -175,9 +175,9 @@ GetNewTransactionId(bool isSubXact) (errmsg("database with OID %u must be vacuumed within %u transactions", oldest_datoid, xidWrapLimit - xid), - errdetail("Approximately %.2f%% of transaction IDs are available for use.", + errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.", (double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100), - errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" + errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); } @@ -485,18 +485,18 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid) (errmsg("database \"%s\" must be vacuumed within %u transactions", oldest_datname, xidWrapLimit - curXid), - errdetail("Approximately %.2f%% of transaction IDs are available for use.", + errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.", (double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100), - errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" + errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else ereport(WARNING, (errmsg("database with OID %u must be vacuumed within %u transactions", oldest_datoid, xidWrapLimit - curXid), - errdetail("Approximately %.2f%% of transaction IDs are available for use.", + errdetail("Approximately %.2f%% of transaction ID space remains before wraparound.", (double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100), - errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" + errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); } } diff --git a/src/test/modules/xid_wraparound/t/002_limits.pl b/src/test/modules/xid_wraparound/t/002_limits.pl index 86632a8d510..29d071a677b 100644 --- a/src/test/modules/xid_wraparound/t/002_limits.pl +++ b/src/test/modules/xid_wraparound/t/002_limits.pl @@ -70,7 +70,8 @@ $node->safe_psql('postgres', # the warning: # # WARNING: database "postgres" must be vacuumed within 3000024 transactions -# HINT: To avoid a database shutdown, execute a database-wide VACUUM in that database. +# DETAIL: Approximately 0.14% of transaction ID space remains before wraparound. +# HINT: To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database. # You might also need to commit or roll back old prepared transactions, or drop stale replication slots. my $stderr; my $warn_limit = 0;