Skip to content

Commit 43d3fbe

Browse files
committed
Clean up some minor inefficiencies in parallel dump/restore.
Parallel dump did a totally pointless query to find out the name of each table to be dumped, which it already knows. Parallel restore runs issued lots of redundant SET commands because _doSetFixedOutputState() was invoked once per TOC item rather than just once at connection start. While the extra queries are insignificant if you're dumping or restoring large tables, it still seems worth getting rid of them. Also, give the responsibility for selecting the right client_encoding for a parallel dump worker to setup_connection() where it naturally belongs, instead of having ad-hoc code for that in CloneArchive(). And fix some minor bugs like use of strdup() where pg_strdup() would be safer. Back-patch to 9.3, mostly to keep the branches in sync in an area that we're still finding bugs in. Discussion: <5086.1464793073@sss.pgh.pa.us>
1 parent 47215c1 commit 43d3fbe

File tree

3 files changed

+34
-50
lines changed

3 files changed

+34
-50
lines changed

src/bin/pg_dump/parallel.c

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,6 @@ IsEveryWorkerIdle(ParallelState *pstate)
801801
static void
802802
lockTableForWorker(ArchiveHandle *AH, TocEntry *te)
803803
{
804-
Archive *AHX = (Archive *) AH;
805804
const char *qualId;
806805
PQExpBuffer query;
807806
PGresult *res;
@@ -812,33 +811,10 @@ lockTableForWorker(ArchiveHandle *AH, TocEntry *te)
812811

813812
query = createPQExpBuffer();
814813

815-
/*
816-
* XXX this is an unbelievably expensive substitute for knowing how to dig
817-
* a table name out of a TocEntry.
818-
*/
819-
appendPQExpBuffer(query,
820-
"SELECT pg_namespace.nspname,"
821-
" pg_class.relname "
822-
" FROM pg_class "
823-
" JOIN pg_namespace on pg_namespace.oid = relnamespace "
824-
" WHERE pg_class.oid = %u", te->catalogId.oid);
825-
826-
res = PQexec(AH->connection, query->data);
827-
828-
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
829-
exit_horribly(modulename,
830-
"could not get relation name for OID %u: %s\n",
831-
te->catalogId.oid, PQerrorMessage(AH->connection));
832-
833-
resetPQExpBuffer(query);
834-
835-
qualId = fmtQualifiedId(AHX->remoteVersion,
836-
PQgetvalue(res, 0, 0),
837-
PQgetvalue(res, 0, 1));
814+
qualId = fmtQualifiedId(AH->public.remoteVersion, te->namespace, te->tag);
838815

839816
appendPQExpBuffer(query, "LOCK TABLE %s IN ACCESS SHARE MODE NOWAIT",
840817
qualId);
841-
PQclear(res);
842818

843819
res = PQexec(AH->connection, query->data);
844820

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,6 +3831,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
38313831
ropt->pghost, ropt->pgport, ropt->username,
38323832
ropt->promptPassword);
38333833

3834+
/* re-establish fixed state */
38343835
_doSetFixedOutputState(AH);
38353836

38363837
/*
@@ -4009,10 +4010,9 @@ parallel_restore(ParallelArgs *args)
40094010
TocEntry *te = args->te;
40104011
int status;
40114012

4012-
_doSetFixedOutputState(AH);
4013-
40144013
Assert(AH->connection != NULL);
40154014

4015+
/* Count only errors associated with this TOC entry */
40164016
AH->public.n_errors = 0;
40174017

40184018
/* Restore the TOC item */
@@ -4381,18 +4381,21 @@ CloneArchive(ArchiveHandle *AH)
43814381
RestoreOptions *ropt = AH->public.ropt;
43824382

43834383
Assert(AH->connection == NULL);
4384+
43844385
/* this also sets clone->connection */
43854386
ConnectDatabase((Archive *) clone, ropt->dbname,
43864387
ropt->pghost, ropt->pgport, ropt->username,
43874388
ropt->promptPassword);
4389+
4390+
/* re-establish fixed state */
4391+
_doSetFixedOutputState(clone);
43884392
}
43894393
else
43904394
{
43914395
char *dbname;
43924396
char *pghost;
43934397
char *pgport;
43944398
char *username;
4395-
const char *encname;
43964399

43974400
Assert(AH->connection != NULL);
43984401

@@ -4406,18 +4409,11 @@ CloneArchive(ArchiveHandle *AH)
44064409
pghost = PQhost(AH->connection);
44074410
pgport = PQport(AH->connection);
44084411
username = PQuser(AH->connection);
4409-
encname = pg_encoding_to_char(AH->public.encoding);
44104412

44114413
/* this also sets clone->connection */
44124414
ConnectDatabase((Archive *) clone, dbname, pghost, pgport, username, TRI_NO);
44134415

4414-
/*
4415-
* Set the same encoding, whatever we set here is what we got from
4416-
* pg_encoding_to_char(), so we really shouldn't run into an error
4417-
* setting that very same value. Also see the comment in
4418-
* SetupConnection().
4419-
*/
4420-
PQsetClientEncoding(clone->connection, encname);
4416+
/* setupDumpWorker will fix up connection state */
44214417
}
44224418

44234419
/* Let the format-specific code have a chance too */

src/bin/pg_dump/pg_dump.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -935,10 +935,7 @@ setup_connection(Archive *AH, const char *dumpencoding,
935935
const char *std_strings;
936936

937937
/*
938-
* Set the client encoding if requested. If dumpencoding == NULL then
939-
* either it hasn't been requested or we're a cloned connection and then
940-
* this has already been set in CloneArchive according to the original
941-
* connection encoding.
938+
* Set the client encoding if requested.
942939
*/
943940
if (dumpencoding)
944941
{
@@ -956,7 +953,11 @@ setup_connection(Archive *AH, const char *dumpencoding,
956953
std_strings = PQparameterStatus(conn, "standard_conforming_strings");
957954
AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
958955

959-
/* Set the role if requested */
956+
/*
957+
* Set the role if requested. In a parallel dump worker, we'll be passed
958+
* use_role == NULL, but AH->use_role is already set (if user specified it
959+
* originally) and we should use that.
960+
*/
960961
if (!use_role && AH->use_role)
961962
use_role = AH->use_role;
962963

@@ -969,9 +970,9 @@ setup_connection(Archive *AH, const char *dumpencoding,
969970
ExecuteSqlStatement(AH, query->data);
970971
destroyPQExpBuffer(query);
971972

972-
/* save this for later use on parallel connections */
973+
/* save it for possible later use by parallel workers */
973974
if (!AH->use_role)
974-
AH->use_role = strdup(use_role);
975+
AH->use_role = pg_strdup(use_role);
975976
}
976977

977978
/* Set the datestyle to ISO to ensure the dump's portability */
@@ -1057,11 +1058,12 @@ setup_connection(Archive *AH, const char *dumpencoding,
10571058
"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
10581059

10591060
/*
1060-
* define an export snapshot, either chosen by user or needed for parallel
1061-
* dump.
1061+
* If user specified a snapshot to use, select that. In a parallel dump
1062+
* worker, we'll be passed dumpsnapshot == NULL, but AH->sync_snapshot_id
1063+
* is already set (if the server can handle it) and we should use that.
10621064
*/
10631065
if (dumpsnapshot)
1064-
AH->sync_snapshot_id = strdup(dumpsnapshot);
1066+
AH->sync_snapshot_id = pg_strdup(dumpsnapshot);
10651067

10661068
if (AH->sync_snapshot_id)
10671069
{
@@ -1087,21 +1089,31 @@ setup_connection(Archive *AH, const char *dumpencoding,
10871089
}
10881090
}
10891091

1092+
/* Set up connection for a parallel worker process */
10901093
static void
1091-
setupDumpWorker(Archive *AHX)
1094+
setupDumpWorker(Archive *AH)
10921095
{
1093-
setup_connection(AHX, NULL, NULL, NULL);
1096+
/*
1097+
* We want to re-select all the same values the master connection is
1098+
* using. We'll have inherited directly-usable values in
1099+
* AH->sync_snapshot_id and AH->use_role, but we need to translate the
1100+
* inherited encoding value back to a string to pass to setup_connection.
1101+
*/
1102+
setup_connection(AH,
1103+
pg_encoding_to_char(AH->encoding),
1104+
NULL,
1105+
NULL);
10941106
}
10951107

10961108
static char *
10971109
get_synchronized_snapshot(Archive *fout)
10981110
{
1099-
char *query = "SELECT pg_export_snapshot()";
1111+
char *query = "SELECT pg_catalog.pg_export_snapshot()";
11001112
char *result;
11011113
PGresult *res;
11021114

11031115
res = ExecuteSqlQueryForSingleRow(fout, query);
1104-
result = strdup(PQgetvalue(res, 0, 0));
1116+
result = pg_strdup(PQgetvalue(res, 0, 0));
11051117
PQclear(res);
11061118

11071119
return result;

0 commit comments

Comments
 (0)