]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add percentage of available IDs to wraparound warnings.
authorNathan Bossart <nathan@postgresql.org>
Fri, 20 Mar 2026 19:15:33 +0000 (14:15 -0500)
committerNathan Bossart <nathan@postgresql.org>
Fri, 20 Mar 2026 19:15:33 +0000 (14:15 -0500)
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
src/backend/access/transam/multixact.c
src/backend/access/transam/varsup.c

index 7c958b062731615f3fec6ed8d849f8d3148e7309..f146e14d3d6a9b975084d928c727f977ef2e5e70 100644 (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>
 
index 34d7b586bec5914a6b7aacac12bcd6852a214d62..95d1d265c558991201359e91f25cab7fcc147109 100644 (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.")));
        }
index 3e95d4cfd164e7d285549623243f73c739e40986..2921148ceba2db7d232ea2b96660c7918a0ad2bd 100644 (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.")));
        }