Commit be1cc8f4 authored by Simon Riggs's avatar Simon Riggs

Add pg_dump --snapshot option

Allows pg_dump to use a snapshot previously defined by a concurrent
session that has either used pg_export_snapshot() or obtained a
snapshot when creating a logical slot. When this option is used with
parallel pg_dump, the snapshot defined by this option is used and no
new snapshot is taken.

Simon Riggs and Michael Paquier
parent 83205404
...@@ -847,6 +847,27 @@ PostgreSQL documentation ...@@ -847,6 +847,27 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--snapshot=<replaceable class="parameter">snapshotname</replaceable></option></term>
<listitem>
<para>
Use the specifed synchronized snapshot when making a dump of the
database (see
<xref linkend="functions-snapshot-synchronization-table"> for more
details).
</para>
<para>
This option is useful when needing to synchronize the dump with
a logical replication slot (see <xref linkend="logicaldecoding">)
or with a concurrent session.
</para>
<para>
In the case of a parallel dump, the snapshot name defined by this
option is used rather than taking a new snapshot.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--serializable-deferrable</option></term> <term><option>--serializable-deferrable</option></term>
<listitem> <listitem>
......
...@@ -126,7 +126,8 @@ static const CatalogId nilCatalogId = {0, 0}; ...@@ -126,7 +126,8 @@ static const CatalogId nilCatalogId = {0, 0};
static void help(const char *progname); static void help(const char *progname);
static void setup_connection(Archive *AH, DumpOptions *dopt, static void setup_connection(Archive *AH, DumpOptions *dopt,
const char *dumpencoding, char *use_role); const char *dumpencoding, const char *dumpsnapshot,
char *use_role);
static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode); static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
static void expand_schema_name_patterns(Archive *fout, static void expand_schema_name_patterns(Archive *fout,
SimpleStringList *patterns, SimpleStringList *patterns,
...@@ -269,6 +270,7 @@ main(int argc, char **argv) ...@@ -269,6 +270,7 @@ main(int argc, char **argv)
RestoreOptions *ropt; RestoreOptions *ropt;
Archive *fout; /* the script file */ Archive *fout; /* the script file */
const char *dumpencoding = NULL; const char *dumpencoding = NULL;
const char *dumpsnapshot = NULL;
char *use_role = NULL; char *use_role = NULL;
int numWorkers = 1; int numWorkers = 1;
trivalue prompt_password = TRI_DEFAULT; trivalue prompt_password = TRI_DEFAULT;
...@@ -329,6 +331,7 @@ main(int argc, char **argv) ...@@ -329,6 +331,7 @@ main(int argc, char **argv)
{"role", required_argument, NULL, 3}, {"role", required_argument, NULL, 3},
{"section", required_argument, NULL, 5}, {"section", required_argument, NULL, 5},
{"serializable-deferrable", no_argument, &dopt->serializable_deferrable, 1}, {"serializable-deferrable", no_argument, &dopt->serializable_deferrable, 1},
{"snapshot", required_argument, NULL, 6},
{"use-set-session-authorization", no_argument, &dopt->use_setsessauth, 1}, {"use-set-session-authorization", no_argument, &dopt->use_setsessauth, 1},
{"no-security-labels", no_argument, &dopt->no_security_labels, 1}, {"no-security-labels", no_argument, &dopt->no_security_labels, 1},
{"no-synchronized-snapshots", no_argument, &dopt->no_synchronized_snapshots, 1}, {"no-synchronized-snapshots", no_argument, &dopt->no_synchronized_snapshots, 1},
...@@ -506,6 +509,10 @@ main(int argc, char **argv) ...@@ -506,6 +509,10 @@ main(int argc, char **argv)
set_dump_section(optarg, &dopt->dumpSections); set_dump_section(optarg, &dopt->dumpSections);
break; break;
case 6: /* snapshot */
dumpsnapshot = pg_strdup(optarg);
break;
default: default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit_nicely(1); exit_nicely(1);
...@@ -614,7 +621,7 @@ main(int argc, char **argv) ...@@ -614,7 +621,7 @@ main(int argc, char **argv)
* death. * death.
*/ */
ConnectDatabase(fout, dopt->dbname, dopt->pghost, dopt->pgport, dopt->username, prompt_password); ConnectDatabase(fout, dopt->dbname, dopt->pghost, dopt->pgport, dopt->username, prompt_password);
setup_connection(fout, dopt, dumpencoding, use_role); setup_connection(fout, dopt, dumpencoding, dumpsnapshot, use_role);
/* /*
* Disable security label support if server version < v9.1.x (prevents * Disable security label support if server version < v9.1.x (prevents
...@@ -658,6 +665,11 @@ main(int argc, char **argv) ...@@ -658,6 +665,11 @@ main(int argc, char **argv)
"Run with --no-synchronized-snapshots instead if you do not need\n" "Run with --no-synchronized-snapshots instead if you do not need\n"
"synchronized snapshots.\n"); "synchronized snapshots.\n");
/* check the version when a snapshot is explicitly specified by user */
if (dumpsnapshot && fout->remoteVersion < 90200)
exit_horribly(NULL,
"Exported snapshots are not supported by this server version.\n");
/* Find the last built-in OID, if needed */ /* Find the last built-in OID, if needed */
if (fout->remoteVersion < 70300) if (fout->remoteVersion < 70300)
{ {
...@@ -888,6 +900,7 @@ help(const char *progname) ...@@ -888,6 +900,7 @@ help(const char *progname)
printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n")); printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n"));
printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n")); printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
printf(_(" --snapshot=SNAPSHOT use given synchronous snapshot for the dump\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead of\n" " use SET SESSION AUTHORIZATION commands instead of\n"
" ALTER OWNER commands to set ownership\n")); " ALTER OWNER commands to set ownership\n"));
...@@ -907,7 +920,8 @@ help(const char *progname) ...@@ -907,7 +920,8 @@ help(const char *progname)
} }
static void static void
setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding, char *use_role) setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding,
const char *dumpsnapshot, char *use_role)
{ {
PGconn *conn = GetConnection(AH); PGconn *conn = GetConnection(AH);
const char *std_strings; const char *std_strings;
...@@ -1015,22 +1029,25 @@ setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding, char ...@@ -1015,22 +1029,25 @@ setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding, char
ExecuteSqlStatement(AH, ExecuteSqlStatement(AH,
"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
/*
* define an export snapshot, either chosen by user or needed for
* parallel dump.
*/
if (dumpsnapshot)
AH->sync_snapshot_id = strdup(dumpsnapshot);
if (AH->sync_snapshot_id)
if (AH->numWorkers > 1 && AH->remoteVersion >= 90200 && !dopt->no_synchronized_snapshots)
{ {
if (AH->sync_snapshot_id) PQExpBuffer query = createPQExpBuffer();
{ appendPQExpBuffer(query, "SET TRANSACTION SNAPSHOT ");
PQExpBuffer query = createPQExpBuffer(); appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
ExecuteSqlStatement(AH, query->data);
appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT "); destroyPQExpBuffer(query);
appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
ExecuteSqlStatement(AH, query->data);
destroyPQExpBuffer(query);
}
else
AH->sync_snapshot_id = get_synchronized_snapshot(AH);
} }
else if (AH->numWorkers > 1 &&
AH->remoteVersion >= 90200 &&
!dopt->no_synchronized_snapshots)
AH->sync_snapshot_id = get_synchronized_snapshot(AH);
if (AH->remoteVersion >= 90500) if (AH->remoteVersion >= 90500)
{ {
...@@ -1044,7 +1061,7 @@ setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding, char ...@@ -1044,7 +1061,7 @@ setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding, char
static void static void
setupDumpWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt) setupDumpWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt)
{ {
setup_connection(AHX, dopt, NULL, NULL); setup_connection(AHX, dopt, NULL, NULL, NULL);
} }
static char * static char *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment