From ef5448479cea756c349ab2b46138477250cbac8e Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Mon, 1 May 2023 19:07:37 +0700
Subject: [PATCH v8 3/3] Rough draft of complete steps to recover from (M)XID
 generation failure

---
 doc/src/sgml/maintenance.sgml | 53 +++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 116d6187cd..8b9f34074b 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -678,6 +678,20 @@ HINT:  Execute a database-wide VACUUM in that database.
     The <command>VACUUM</command> command can still be run normally to recover.
          <!-- v12 and v13 need VACUUM (TRUNCATE off, INDEX_CLEANUP off); -->
          <!-- v11 maybe mention that it will often succed, but will need S-U if truncation happens -->
+
+    However, it is first necessary to remove obstacles to advancing the XID horizon:
+
+    <orderedlist>
+     <listitem>
+      <simpara>Commit or rollback any prepared transactions</simpara>
+     </listitem>
+     <listitem>
+      <simpara>Terminate any sessions that might have open transactions</simpara>
+     </listitem>
+     <listitem>
+      <simpara>Drop any old replication slots</simpara>
+     </listitem>
+    </orderedlist>
    </para>
 
    <note>
@@ -763,6 +777,45 @@ HINT:  Execute a database-wide VACUUM in that database.
      have the oldest multixact-age.  Both of these kinds of aggressive
      scans will occur even if autovacuum is nominally disabled.
     </para>
+
+<!-- WIP: Lot's of stuff identical to the XID case, can we abbreviate? -->
+   <para>
+    If for some reason autovacuum fails to clear old MXIDs from a table, the
+    system will begin to emit warning messages like this when the database's
+    oldest XIDs reach forty million transactions from the wraparound point:
+
+<programlisting>
+WARNING:  database "mydb" must be vacuumed within 39985967 transactions
+HINT:  To prevent MultiXactId generation failure, execute a database-wide VACUUM in that database.
+</programlisting>
+
+<!-- WIP: not sure about system catalogs -->
+    (A manual <command>VACUUM</command> should fix the problem, as suggested by the
+    hint; but note that the <command>VACUUM</command> must be performed by a
+    superuser, else it will fail to process system catalogs and thus not
+    be able to advance the database's <structfield>datfrozenxid</structfield>.)
+    If these warnings are
+    ignored, the system will refuse to generate new MXIDs once there are
+    fewer than three million left until wraparound:
+
+<programlisting>
+ERROR:  database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database "mydb"
+HINT:  Execute a database-wide VACUUM in that database.
+</programlisting>
+   </para>
+
+   <para>
+    To restore normal operation, it is first necessary to remove obstacles to advancing the MXID horizon:
+    <orderedlist>
+     <listitem>
+      <simpara>Commit or rollback each prepared transaction that might appear in a multixact</simpara>
+     </listitem>
+     <listitem>
+      <simpara>Resolve each transaction that might appear in a multixact</simpara>
+     </listitem>
+    </orderedlist>
+   </para>
+
    </sect3>
   </sect2>
 
-- 
2.39.2

