]> granicus.if.org Git - postgresql/commitdiff
Make pg_dump error cleanly with -j against hot standby
authorMagnus Hagander <magnus@hagander.net>
Thu, 26 May 2016 20:14:23 +0000 (22:14 +0200)
committerMagnus Hagander <magnus@hagander.net>
Thu, 26 May 2016 20:14:23 +0000 (22:14 +0200)
Getting a synchronized snapshot is not supported on a hot standby node,
and is by default taken when using -j with multiple sessions. Trying to
do so still failed, but with a server error that would also go in the
log. Instead, proprely detect this case and give a better error message.

src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_backup_db.h
src/bin/pg_dump/pg_dump.c

index 83f6029c1fea6ec0111156d504095bf088652790..f94caa3cd43fa9f27c4257e354636680e9b39978 100644 (file)
@@ -173,6 +173,7 @@ typedef struct Archive
        int                     verbose;
        char       *remoteVersionStr;           /* server's version string */
        int                     remoteVersion;  /* same in numeric form */
+       bool            isStandby;              /* is server a standby node */
 
        int                     minRemoteVersion;               /* allowable range */
        int                     maxRemoteVersion;
index 35ce94592b5c5f10f19094bd4c4013e8b589d611..818bc9efe14a0c04b4678e5fa65b291ae7812c2d 100644 (file)
@@ -37,6 +37,7 @@ _check_database_version(ArchiveHandle *AH)
 {
        const char *remoteversion_str;
        int                     remoteversion;
+       PGresult   *res;
 
        remoteversion_str = PQparameterStatus(AH->connection, "server_version");
        remoteversion = PQserverVersion(AH->connection);
@@ -56,6 +57,20 @@ _check_database_version(ArchiveHandle *AH)
                                  remoteversion_str, progname, PG_VERSION);
                exit_horribly(NULL, "aborting because of server version mismatch\n");
        }
+
+       /*
+        * When running against 9.0 or later, check if we are in recovery mode,
+        * which means we are on a hot standby.
+        */
+       if (remoteversion >= 90000)
+       {
+               res = ExecuteSqlQueryForSingleRow((Archive *) AH, "SELECT pg_catalog.pg_is_in_recovery()");
+
+               AH->public.isStandby = (strcmp(PQgetvalue(res, 0, 0), "t") == 0);
+               PQclear(res);
+       }
+       else
+               AH->public.isStandby = false;
 }
 
 /*
@@ -388,6 +403,29 @@ ExecuteSqlQuery(Archive *AHX, const char *query, ExecStatusType status)
        return res;
 }
 
+/*
+ * Execute an SQL query and verify that we got exactly one row back.
+ */
+PGresult *
+ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
+{
+       PGresult   *res;
+       int                     ntups;
+
+       res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
+
+       /* Expecting a single result only */
+       ntups = PQntuples(res);
+       if (ntups != 1)
+               exit_horribly(NULL,
+                                         ngettext("query returned %d row instead of one: %s\n",
+                                                          "query returned %d rows instead of one: %s\n",
+                                                          ntups),
+                                         ntups, query);
+
+       return res;
+}
+
 /*
  * Convenience function to send a query.
  * Monitors result to detect COPY statements
index 6408f144ea127c4a1c650f071d12dfaf5af78c0d..527449e04401314006c00631d81b377663cf1e08 100644 (file)
@@ -16,6 +16,7 @@ extern int    ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen);
 extern void ExecuteSqlStatement(Archive *AHX, const char *query);
 extern PGresult *ExecuteSqlQuery(Archive *AHX, const char *query,
                                ExecStatusType status);
+extern PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
 
 extern void EndDBCopyMode(Archive *AHX, const char *tocEntryTag);
 
index a958225f1f854e62f7cb5c9a669aff099b3d0570..f85778dc780ff22436e9e06e263bd8ac42014fec 100644 (file)
@@ -264,7 +264,6 @@ static bool nonemptyReloptions(const char *reloptions);
 static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
                                                const char *prefix, Archive *fout);
 static char *get_synchronized_snapshot(Archive *fout);
-static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
 static void setupDumpWorker(Archive *AHX);
 
 
@@ -657,23 +656,11 @@ main(int argc, char **argv)
                dopt.no_security_labels = 1;
 
        /*
-        * When running against 9.0 or later, check if we are in recovery mode,
-        * which means we are on a hot standby.
+        * On hot standby slaves, never try to dump unlogged table data, since it
+        * will just throw an error.
         */
-       if (fout->remoteVersion >= 90000)
-       {
-               PGresult   *res = ExecuteSqlQueryForSingleRow(fout, "SELECT pg_catalog.pg_is_in_recovery()");
-
-               if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
-               {
-                       /*
-                        * On hot standby slaves, never try to dump unlogged table data,
-                        * since it will just throw an error.
-                        */
-                       dopt.no_unlogged_table_data = true;
-               }
-               PQclear(res);
-       }
+       if (fout->isStandby)
+               dopt.no_unlogged_table_data = true;
 
        /* Select the appropriate subquery to convert user IDs to names */
        if (fout->remoteVersion >= 80100)
@@ -1105,7 +1092,16 @@ setup_connection(Archive *AH, const char *dumpencoding,
        else if (AH->numWorkers > 1 &&
                         AH->remoteVersion >= 90200 &&
                         !dopt->no_synchronized_snapshots)
+       {
+               if (AH->isStandby)
+                       exit_horribly(NULL,
+                        "Synchronized snapshots are not supported on standby servers.\n"
+                                                 "Run with --no-synchronized-snapshots instead if you do not need\n"
+                                                 "synchronized snapshots.\n");
+
+
                AH->sync_snapshot_id = get_synchronized_snapshot(AH);
+       }
 }
 
 static void
@@ -17855,26 +17851,3 @@ appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
        if (!res)
                write_msg(NULL, "WARNING: could not parse reloptions array\n");
 }
-
-/*
- * Execute an SQL query and verify that we got exactly one row back.
- */
-static PGresult *
-ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
-{
-       PGresult   *res;
-       int                     ntups;
-
-       res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
-
-       /* Expecting a single result only */
-       ntups = PQntuples(res);
-       if (ntups != 1)
-               exit_horribly(NULL,
-                                         ngettext("query returned %d row instead of one: %s\n",
-                                                          "query returned %d rows instead of one: %s\n",
-                                                          ntups),
-                                         ntups, query);
-
-       return res;
-}