Skip to content

Commit 47e5969

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 aa86edb commit 47e5969

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
@@ -172,6 +172,7 @@ typedef struct Archive
172172
int verbose;
173173
char *remoteVersionStr; /* server's version string */
174174
int remoteVersion; /* same in numeric form */
175+
bool isStandby; /* is server a standby node */
175176

176177
int minRemoteVersion; /* allowable range */
177178
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
@@ -255,7 +255,6 @@ static bool nonemptyReloptions(const char *reloptions);
255255
static void fmtReloptionsArray(Archive *fout, PQExpBuffer buffer,
256256
const char *reloptions, const char *prefix);
257257
static char *get_synchronized_snapshot(Archive *fout);
258-
static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
259258
static void setupDumpWorker(Archive *AHX);
260259

261260

@@ -647,23 +646,11 @@ main(int argc, char **argv)
647646
dopt.no_security_labels = 1;
648647

649648
/*
650-
* When running against 9.0 or later, check if we are in recovery mode,
651-
* which means we are on a hot standby.
649+
* On hot standby slaves, never try to dump unlogged table data, since it
650+
* will just throw an error.
652651
*/
653-
if (fout->remoteVersion >= 90000)
654-
{
655-
PGresult *res = ExecuteSqlQueryForSingleRow(fout, "SELECT pg_catalog.pg_is_in_recovery()");
656-
657-
if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
658-
{
659-
/*
660-
* On hot standby slaves, never try to dump unlogged table data,
661-
* since it will just throw an error.
662-
*/
663-
dopt.no_unlogged_table_data = true;
664-
}
665-
PQclear(res);
666-
}
652+
if (fout->isStandby)
653+
dopt.no_unlogged_table_data = true;
667654

668655
/* Select the appropriate subquery to convert user IDs to names */
669656
if (fout->remoteVersion >= 80100)
@@ -1088,7 +1075,16 @@ setup_connection(Archive *AH, const char *dumpencoding,
10881075
else if (AH->numWorkers > 1 &&
10891076
AH->remoteVersion >= 90200 &&
10901077
!dopt->no_synchronized_snapshots)
1078+
{
1079+
if (AH->isStandby)
1080+
exit_horribly(NULL,
1081+
"Synchronized snapshots are not supported on standby servers.\n"
1082+
"Run with --no-synchronized-snapshots instead if you do not need\n"
1083+
"synchronized snapshots.\n");
1084+
1085+
10911086
AH->sync_snapshot_id = get_synchronized_snapshot(AH);
1087+
}
10921088
}
10931089

10941090
static void
@@ -16559,26 +16555,3 @@ fmtReloptionsArray(Archive *fout, PQExpBuffer buffer, const char *reloptions,
1655916555
if (options)
1656016556
free(options);
1656116557
}
16562-
16563-
/*
16564-
* Execute an SQL query and verify that we got exactly one row back.
16565-
*/
16566-
static PGresult *
16567-
ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
16568-
{
16569-
PGresult *res;
16570-
int ntups;
16571-
16572-
res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
16573-
16574-
/* Expecting a single result only */
16575-
ntups = PQntuples(res);
16576-
if (ntups != 1)
16577-
exit_horribly(NULL,
16578-
ngettext("query returned %d row instead of one: %s\n",
16579-
"query returned %d rows instead of one: %s\n",
16580-
ntups),
16581-
ntups, query);
16582-
16583-
return res;
16584-
}

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