Make pg_createsubscriber warn if publisher has two-phase commit enabled.
authorTom Lane <[email protected]>
Sun, 30 Jun 2024 18:24:14 +0000 (14:24 -0400)
committerTom Lane <[email protected]>
Sun, 30 Jun 2024 18:24:14 +0000 (14:24 -0400)
pg_createsubscriber currently always sets up logical replication
with two-phase commit disabled.  Improving that is not going to
happen for v17.  In the meantime, document the deficiency, and
adjust pg_createsubscriber so that it will emit a warning if
the source installation has max_prepared_transactions > 0.

Hayato Kuroda (some mods by Amit Kapila and me), per complaint from
Noah Misch

Discussion: https://postgr.es/m/20240623062157[email protected]

doc/src/sgml/ref/pg_createsubscriber.sgml
src/bin/pg_basebackup/pg_createsubscriber.c

index 2ee6eee9e35f72a774f90ccdf347a2fc538291f5..87a9d3db28e5d6e017ec9b5eefa9690784ee1046 100644 (file)
@@ -353,6 +353,17 @@ PostgreSQL documentation
     <application>pg_createsubscriber</application>.
    </para>
 
+   <para>
+    <application>pg_createsubscriber</application> sets up logical
+    replication with two-phase commit disabled.  This means that any
+    prepared transactions will be replicated at the time
+    of <command>COMMIT PREPARED</command>, without advance preparation.
+    Once setup is complete, you can manually drop and re-create the
+    subscription(s) with
+    the <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
+    option enabled.
+   </para>
+
    <para>
     <application>pg_createsubscriber</application> changes the system
     identifier using <application>pg_resetwal</application>.  It would avoid
index 7c943317860c45b8b7ff6b0d35c56152af5ed86d..fecf5db3653940df663bd5e28a510064803c056c 100644 (file)
@@ -823,6 +823,7 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
    int         cur_repslots;
    int         max_walsenders;
    int         cur_walsenders;
+   int         max_prepared_transactions;
 
    pg_log_info("checking settings on publisher");
 
@@ -849,23 +850,12 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
     * -----------------------------------------------------------------------
     */
    res = PQexec(conn,
-                "WITH wl AS "
-                "(SELECT setting AS wallevel FROM pg_catalog.pg_settings "
-                "WHERE name = 'wal_level'), "
-                "total_mrs AS "
-                "(SELECT setting AS tmrs FROM pg_catalog.pg_settings "
-                "WHERE name = 'max_replication_slots'), "
-                "cur_mrs AS "
-                "(SELECT count(*) AS cmrs "
-                "FROM pg_catalog.pg_replication_slots), "
-                "total_mws AS "
-                "(SELECT setting AS tmws FROM pg_catalog.pg_settings "
-                "WHERE name = 'max_wal_senders'), "
-                "cur_mws AS "
-                "(SELECT count(*) AS cmws FROM pg_catalog.pg_stat_activity "
-                "WHERE backend_type = 'walsender') "
-                "SELECT wallevel, tmrs, cmrs, tmws, cmws "
-                "FROM wl, total_mrs, cur_mrs, total_mws, cur_mws");
+                "SELECT pg_catalog.current_setting('wal_level'),"
+                " pg_catalog.current_setting('max_replication_slots'),"
+                " (SELECT count(*) FROM pg_catalog.pg_replication_slots),"
+                " pg_catalog.current_setting('max_wal_senders'),"
+                " (SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type = 'walsender'),"
+                " pg_catalog.current_setting('max_prepared_transactions')");
 
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
@@ -879,6 +869,7 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
    cur_repslots = atoi(PQgetvalue(res, 0, 2));
    max_walsenders = atoi(PQgetvalue(res, 0, 3));
    cur_walsenders = atoi(PQgetvalue(res, 0, 4));
+   max_prepared_transactions = atoi(PQgetvalue(res, 0, 5));
 
    PQclear(res);
 
@@ -887,6 +878,8 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
    pg_log_debug("publisher: current replication slots: %d", cur_repslots);
    pg_log_debug("publisher: max_wal_senders: %d", max_walsenders);
    pg_log_debug("publisher: current wal senders: %d", cur_walsenders);
+   pg_log_debug("publisher: max_prepared_transactions: %d",
+                max_prepared_transactions);
 
    disconnect_database(conn, false);
 
@@ -914,6 +907,13 @@ check_publisher(const struct LogicalRepInfo *dbinfo)
        failed = true;
    }
 
+   if (max_prepared_transactions != 0)
+   {
+       pg_log_warning("two_phase option will not be enabled for slots");
+       pg_log_warning_detail("Subscriptions will be created with the two_phase option disabled.  "
+                             "Prepared transactions will be replicated at COMMIT PREPARED.");
+   }
+
    pg_free(wal_level);
 
    if (failed)