postgres.git / summary / log / commit / refs
commit e646450e609d690ced30d9e8e3fdc27ee6c3ff4c
Author: Nathan Bossart <nathan@postgresql.org>
Date: Fri Mar 20 19:15:33 2026 +0000
Add percentage of available IDs to wraparound warnings.
This commit adds DETAIL messages to the existing wraparound
WARNINGs that include the percentage of transaction/multixact IDs
that remain available for use. The hope is that this more clearly
expresses the urgency of the situation.
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: wenhui qiu <qiuwenhuifx@gmail.com>
Discussion: https://postgr.es/m/aRdhSSFb9zZH_0zc%40nathan
doc/src/sgml/maintenance.sgml | 1 +
src/backend/access/transam/multixact.c | 8 ++++++++
src/backend/access/transam/varsup.c | 8 ++++++++
3 files changed, 17 insertions(+)
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 7c958b06273..f146e14d3d6 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -674,6 +674,7 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
<programlisting>
WARNING: database "mydb" must be vacuumed within 39985967 transactions
+DETAIL: Approximately 1.86% of transaction IDs are available for use.
HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.
</programlisting>
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 34d7b586bec..95d1d265c55 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1059,6 +1059,8 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datname,
multiWrapLimit - result),
+ errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ (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, or drop stale replication slots.")));
else
@@ -1068,6 +1070,8 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
multiWrapLimit - result,
oldest_datoid,
multiWrapLimit - result),
+ errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ (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, or drop stale replication slots.")));
}
@@ -2196,6 +2200,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datname,
multiWrapLimit - curMulti),
+ errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ (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, or drop stale replication slots.")));
else
@@ -2205,6 +2211,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWrapLimit - curMulti,
oldest_datoid,
multiWrapLimit - curMulti),
+ errdetail("Approximately %.2f%% of MultiXactIds are available for use.",
+ (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, or drop stale replication slots.")));
}
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index 3e95d4cfd16..2921148ceba 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -175,6 +175,8 @@ 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.",
+ (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.")));
else
@@ -182,6 +184,8 @@ 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.",
+ (double) (xidWrapLimit - xid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID 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.")));
}
@@ -490,6 +494,8 @@ 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.",
+ (double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID 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
@@ -497,6 +503,8 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
(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.",
+ (double) (xidWrapLimit - curXid) / (MaxTransactionId / 2) * 100),
errhint("To avoid XID 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.")));
}
[parent: 733f20df5372]