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
This commit is contained in:
Nathan Bossart 2026-03-20 14:15:33 -05:00
parent 733f20df53
commit e646450e60
3 changed files with 17 additions and 0 deletions

View file

@ -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>

View file

@ -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.")));
}

View file

@ -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.")));
}