Commit 0dc848b0 authored by Peter Eisentraut's avatar Peter Eisentraut

pg_basebackup: Add --slot option

This option specifies a replication slot for WAL streaming (-X stream),
so that there can be continuous replication slot use between WAL
streaming during the base backup and the start of regular streaming
replication.
Reviewed-by: default avatarMichael Paquier <michael.paquier@gmail.com>
parent 90102bb5
......@@ -215,14 +215,35 @@ PostgreSQL documentation
<listitem>
<para>
Write a minimal <filename>recovery.conf</filename> in the output directory (or into
the base archive file when using tar format) to ease setting
up a standby server.
Write a minimal <filename>recovery.conf</filename> in the output
directory (or into the base archive file when using tar format) to
ease setting up a standby server.
The <filename>recovery.conf</filename> file will record the connection
settings and, if specified, the replication slot
that <application>pg_basebackup</application> is using, so that the
streaming replication will use the same settings later on.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-S <replaceable>slotname</replaceable></option></term>
<term><option>--slot=<replaceable class="parameter">slotname</replaceable></option></term>
<listitem>
<para>
This option can only be used together with <literal>-X
stream</literal>. It causes the WAL streaming to use the specified
replication slot. If the base backup is intended to be used as a
streaming replication standby using replication slots, it should then
use the same replication slot name
in <filename>recovery.conf</filename>. That way, it is ensured that
the server does not remove any necessary WAL data in the time between
the end of the base backup and the start of streaming replication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-T <replaceable class="parameter">olddir</replaceable>=<replaceable class="parameter">newdir</replaceable></option></term>
<term><option>--tablespace-mapping=<replaceable class="parameter">olddir</replaceable>=<replaceable class="parameter">newdir</replaceable></option></term>
......
......@@ -239,6 +239,7 @@ usage(void)
" (in kB/s, or use suffix \"k\" or \"M\")\n"));
printf(_(" -R, --write-recovery-conf\n"
" write recovery.conf after backup\n"));
printf(_(" -S, --slot=SLOTNAME replication slot to use\n"));
printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
" relocate tablespace in OLDDIR to NEWDIR\n"));
printf(_(" -x, --xlog include required WAL files in backup (fetch mode)\n"));
......@@ -1536,6 +1537,13 @@ GenerateRecoveryConf(PGconn *conn)
appendPQExpBuffer(recoveryconfcontents, "primary_conninfo = '%s'\n", escaped);
free(escaped);
if (replication_slot)
{
escaped = escape_quotes(replication_slot);
appendPQExpBuffer(recoveryconfcontents, "primary_slot_name = '%s'\n", replication_slot);
free(escaped);
}
if (PQExpBufferBroken(recoveryconfcontents) ||
PQExpBufferDataBroken(conninfo_buf))
{
......@@ -1934,6 +1942,7 @@ main(int argc, char **argv)
{"checkpoint", required_argument, NULL, 'c'},
{"max-rate", required_argument, NULL, 'r'},
{"write-recovery-conf", no_argument, NULL, 'R'},
{"slot", required_argument, NULL, 'S'},
{"tablespace-mapping", required_argument, NULL, 'T'},
{"xlog", no_argument, NULL, 'x'},
{"xlog-method", required_argument, NULL, 'X'},
......@@ -1974,7 +1983,7 @@ main(int argc, char **argv)
}
}
while ((c = getopt_long(argc, argv, "D:F:r:RT:xX:l:zZ:d:c:h:p:U:s:wWvP",
while ((c = getopt_long(argc, argv, "D:F:r:RT:xX:l:zZ:d:c:h:p:U:s:S:wWvP",
long_options, &option_index)) != -1)
{
switch (c)
......@@ -2001,6 +2010,9 @@ main(int argc, char **argv)
case 'R':
writerecoveryconf = true;
break;
case 'S':
replication_slot = pg_strdup(optarg);
break;
case 'T':
tablespace_list_append(optarg);
break;
......@@ -2165,6 +2177,16 @@ main(int argc, char **argv)
exit(1);
}
if (replication_slot && !streamwal)
{
fprintf(stderr,
_("%s: replication slots can only be used with WAL streaming\n"),
progname);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
progname);
exit(1);
}
if (strcmp(xlog_dir, "") != 0)
{
if (format != 'p')
......
......@@ -2,7 +2,7 @@ use strict;
use warnings;
use Cwd;
use TestLib;
use Test::More tests => 44;
use Test::More tests => 51;
program_help_ok('pg_basebackup');
program_version_ok('pg_basebackup');
......@@ -37,6 +37,7 @@ command_fails(
'pg_basebackup fails because of WAL configuration');
open CONF, ">>$tempdir/pgdata/postgresql.conf";
print CONF "max_replication_slots = 10\n";
print CONF "max_wal_senders = 10\n";
print CONF "wal_level = archive\n";
close CONF;
......@@ -156,3 +157,22 @@ ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxf/pg_xlog")), 'WAL files co
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupxs", '-X', 'stream' ],
'pg_basebackup -X stream runs');
ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxf/pg_xlog")), 'WAL files copied');
command_fails([ 'pg_basebackup', '-D', "$tempdir/fail", '-S', 'slot1' ],
'pg_basebackup with replication slot fails without -X stream');
command_fails([ 'pg_basebackup', '-D', "$tempdir/backupxs_sl_fail", '-X', 'stream', '-S', 'slot1' ],
'pg_basebackup fails with nonexistent replication slot');
psql 'postgres', q{SELECT * FROM pg_create_physical_replication_slot('slot1')};
my $lsn = psql 'postgres', q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'};
is($lsn, '', 'restart LSN of new slot is null');
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupxs_sl", '-X', 'stream', '-S', 'slot1' ],
'pg_basebackup -X stream with replication slot runs');
$lsn = psql 'postgres', q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'};
like($lsn, qr!^0/[0-9A-Z]{8}$!, 'restart LSN of slot has advanced');
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupxs_sl_R", '-X', 'stream', '-S', 'slot1', '-R' ],
'pg_basebackup with replication slot and -R runs');
like(slurp_file("$tempdir/backupxs_sl_R/recovery.conf"),
qr/^primary_slot_name = 'slot1'$/m,
'recovery.conf sets primary_slot_name');
......@@ -173,8 +173,11 @@ END
sub psql
{
my ($dbname, $sql) = @_;
my ($stdout, $stderr);
print("# Running SQL command: $sql\n");
run [ 'psql', '-X', '-q', '-d', $dbname, '-f', '-' ], '<', \$sql or die;
run [ 'psql', '-X', '-A', '-t', '-q', '-d', $dbname, '-f', '-' ], '<', \$sql, '>', \$stdout, '2>', \$stderr or die;
chomp $stdout;
return $stdout;
}
sub slurp_dir
......
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