diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c index 8b996f4..32de351 100644 --- a/src/bin/pg_dump/parallel.c +++ b/src/bin/pg_dump/parallel.c @@ -834,6 +834,48 @@ } + +/** + * This function issue shared locks for all tables to be dumped + */ +static void +LockEarly(ArchiveHandle *AH) +{ + TocEntry *tocEntry; + char* tableNamespace; + char* tableName; + PQExpBuffer query; + PGresult *res; + + query = createPQExpBuffer(); + resetPQExpBuffer(query); + + for( tocEntry = AH->toc->next; tocEntry != AH->toc; tocEntry = tocEntry->next ) + { + + if( tocEntry->desc && strcmp( tocEntry->desc, "TABLE DATA") == 0 ) + { + tableNamespace = tocEntry->namespace; + tableName = tocEntry->tag; + + appendPQExpBuffer(query, + "lock table %s.%s in access share mode nowait;\n", + PQescapeIdentifier(AH->connection,tableNamespace,strlen(tableNamespace)), + PQescapeIdentifier(AH->connection,tableName,strlen(tableName)) + ); + } + } + + res = PQexec( AH->connection, query->data ); + if( !res || PQresultStatus(res) != PGRES_COMMAND_OK ) + { + exit_horribly(modulename,"Could not lock the tables to begin the backup job\n\n"); + } + + PQclear( res ); + destroyPQExpBuffer(query); +} + /* * This function is called by both Unix and Windows variants to set up * and run a worker process. Caller should exit the process (or thread) @@ -867,6 +909,14 @@ */ (AH->SetupWorkerPtr) ((Archive *) AH); + /* + * Issue shared locks if --lock-early option is issued at command line + */ + if( ((Archive*)AH)->dopt->lock_early ) + { + LockEarly(AH); + } + /* * Execute commands until done. */ diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index ce3100f..26e2580 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -158,6 +158,7 @@ int use_setsessauth; int enable_row_security; int load_via_partition_root; + int lock_early; /* default, if no "inclusion" switches appear, is to dump everything */ bool include_everything; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 8733426..a9ce96f 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -362,6 +362,7 @@ {"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1}, {"no-subscriptions", no_argument, &dopt.no_subscriptions, 1}, {"no-sync", no_argument, NULL, 7}, + {"lock-early", no_argument, &dopt.lock_early, 1}, {NULL, 0, NULL, 0} }; @@ -603,6 +604,15 @@ if (dopt.if_exists && !dopt.outputClean) exit_horribly(NULL, "option --if-exists requires option -c/--clean\n"); + /* Basic checks for lock-early logic */ + if( numWorkers <= 1 ) + { + if( dopt.lock_early ) + { + exit_horribly(NULL, "lock early only works for parallel backup\n" ); + } + } + /* Identify archive format to emit */ archiveFormat = parseArchiveFormat(format, &archiveMode); @@ -924,6 +934,8 @@ printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" " plain text (default))\n")); printf(_(" -j, --jobs=NUM use this many parallel jobs to dump\n")); + printf(_(" --lock-early issue shared locks as early as possible for all\n" + " tables on all parallel backup workers\n" )); printf(_(" -v, --verbose verbose mode\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));