Skip to content

Commit d74048d

Browse files
committed
Make pg_dump error cleanly with -j against hot standby
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.
1 parent aeb9ae6 commit d74048d

File tree

4 files changed

+53
-40
lines changed

4 files changed

+53
-40
lines changed

src/bin/pg_dump/pg_backup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ typedef struct Archive
173173
int verbose;
174174
char *remoteVersionStr; /* server's version string */
175175
int remoteVersion; /* same in numeric form */
176+
bool isStandby; /* is server a standby node */
176177

177178
int minRemoteVersion; /* allowable range */
178179
int maxRemoteVersion;

src/bin/pg_dump/pg_backup_db.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ _check_database_version(ArchiveHandle *AH)
3737
{
3838
const char *remoteversion_str;
3939
int remoteversion;
40+
PGresult *res;
4041

4142
remoteversion_str = PQparameterStatus(AH->connection, "server_version");
4243
remoteversion = PQserverVersion(AH->connection);
@@ -56,6 +57,20 @@ _check_database_version(ArchiveHandle *AH)
5657
remoteversion_str, progname, PG_VERSION);
5758
exit_horribly(NULL, "aborting because of server version mismatch\n");
5859
}
60+
61+
/*
62+
* When running against 9.0 or later, check if we are in recovery mode,
63+
* which means we are on a hot standby.
64+
*/
65+
if (remoteversion >= 90000)
66+
{
67+
res = ExecuteSqlQueryForSingleRow((Archive *) AH, "SELECT pg_catalog.pg_is_in_recovery()");
68+
69+
AH->public.isStandby = (strcmp(PQgetvalue(res, 0, 0), "t") == 0);
70+
PQclear(res);
71+
}
72+
else
73+
AH->public.isStandby = false;
5974
}
6075

6176
/*
@@ -388,6 +403,29 @@ ExecuteSqlQuery(Archive *AHX, const char *query, ExecStatusType status)
388403
return res;
389404
}
390405

406+
/*
407+
* Execute an SQL query and verify that we got exactly one row back.
408+
*/
409+
PGresult *
410+
ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
411+
{
412+
PGresult *res;
413+
int ntups;
414+
415+
res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
416+
417+
/* Expecting a single result only */
418+
ntups = PQntuples(res);
419+
if (ntups != 1)
420+
exit_horribly(NULL,
421+
ngettext("query returned %d row instead of one: %s\n",
422+
"query returned %d rows instead of one: %s\n",
423+
ntups),
424+
ntups, query);
425+
426+
return res;
427+
}
428+
391429
/*
392430
* Convenience function to send a query.
393431
* Monitors result to detect COPY statements

src/bin/pg_dump/pg_backup_db.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen);
1616
extern void ExecuteSqlStatement(Archive *AHX, const char *query);
1717
extern PGresult *ExecuteSqlQuery(Archive *AHX, const char *query,
1818
ExecStatusType status);
19+
extern PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
1920

2021
extern void EndDBCopyMode(Archive *AHX, const char *tocEntryTag);
2122

src/bin/pg_dump/pg_dump.c

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,6 @@ static bool nonemptyReloptions(const char *reloptions);
264264
static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
265265
const char *prefix, Archive *fout);
266266
static char *get_synchronized_snapshot(Archive *fout);
267-
static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
268267
static void setupDumpWorker(Archive *AHX);
269268

270269

@@ -657,23 +656,11 @@ main(int argc, char **argv)
657656
dopt.no_security_labels = 1;
658657

659658
/*
660-
* When running against 9.0 or later, check if we are in recovery mode,
661-
* which means we are on a hot standby.
659+
* On hot standby slaves, never try to dump unlogged table data, since it
660+
* will just throw an error.
662661
*/
663-
if (fout->remoteVersion >= 90000)
664-
{
665-
PGresult *res = ExecuteSqlQueryForSingleRow(fout, "SELECT pg_catalog.pg_is_in_recovery()");
666-
667-
if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
668-
{
669-
/*
670-
* On hot standby slaves, never try to dump unlogged table data,
671-
* since it will just throw an error.
672-
*/
673-
dopt.no_unlogged_table_data = true;
674-
}
675-
PQclear(res);
676-
}
662+
if (fout->isStandby)
663+
dopt.no_unlogged_table_data = true;
677664

678665
/* Select the appropriate subquery to convert user IDs to names */
679666
if (fout->remoteVersion >= 80100)
@@ -1105,7 +1092,16 @@ setup_connection(Archive *AH, const char *dumpencoding,
11051092
else if (AH->numWorkers > 1 &&
11061093
AH->remoteVersion >= 90200 &&
11071094
!dopt->no_synchronized_snapshots)
1095+
{
1096+
if (AH->isStandby)
1097+
exit_horribly(NULL,
1098+
"Synchronized snapshots are not supported on standby servers.\n"
1099+
"Run with --no-synchronized-snapshots instead if you do not need\n"
1100+
"synchronized snapshots.\n");
1101+
1102+
11081103
AH->sync_snapshot_id = get_synchronized_snapshot(AH);
1104+
}
11091105
}
11101106

11111107
static void
@@ -17855,26 +17851,3 @@ appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
1785517851
if (!res)
1785617852
write_msg(NULL, "WARNING: could not parse reloptions array\n");
1785717853
}
17858-
17859-
/*
17860-
* Execute an SQL query and verify that we got exactly one row back.
17861-
*/
17862-
static PGresult *
17863-
ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
17864-
{
17865-
PGresult *res;
17866-
int ntups;
17867-
17868-
res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
17869-
17870-
/* Expecting a single result only */
17871-
ntups = PQntuples(res);
17872-
if (ntups != 1)
17873-
exit_horribly(NULL,
17874-
ngettext("query returned %d row instead of one: %s\n",
17875-
"query returned %d rows instead of one: %s\n",
17876-
ntups),
17877-
ntups, query);
17878-
17879-
return res;
17880-
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy