Commit 0eb59c45 authored by Magnus Hagander's avatar Magnus Hagander

Backend support for streaming base backups

Add BASE_BACKUP command to walsender, allowing it to stream a
base backup to the client (in tar format). The syntax is still
far from ideal, that will be fixed in the switch to use a proper
grammar for walsender.

No client included yet, will come as a separate commit.

Magnus Hagander and Heikki Linnakangas
parent be0c3ea2
...@@ -1458,6 +1458,98 @@ The commands accepted in walsender mode are: ...@@ -1458,6 +1458,98 @@ The commands accepted in walsender mode are:
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>BASE_BACKUP <replaceable>options</><literal>;</><replaceable>label</></term>
<listitem>
<para>
Instructs the server to start streaming a base backup.
The system will automatically be put in backup mode with the label
specified in <replaceable>label</> before the backup is started, and
taken out of it when the backup is complete. The following options
are accepted:
<variablelist>
<varlistentry>
<term><literal>PROGRESS</></term>
<listitem>
<para>
Request information required to generate a progress report. This will
send back an approximate size in the header of each tablespace, which
can be used to calculate how far along the stream is done. This is
calculated by enumerating all the file sizes once before the transfer
is even started, and may as such have a negative impact on the
performance - in particular it may take longer before the first data
is streamed. Since the database files can change during the backup,
the size is only approximate and may both grow and shrink between
the time of approximation and the sending of the actual files.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
When the backup is started, the server will first send a header in
ordinary result set format, followed by one or more CopyResponse
results, one for PGDATA and one for each additional tablespace other
than <literal>pg_default</> and <literal>pg_global</>. The data in
the CopyResponse results will be a tar format (using ustar00
extensions) dump of the tablespace contents.
</para>
<para>
The header is an ordinary resultset with one row for each tablespace.
The fields in this row are:
<variablelist>
<varlistentry>
<term>spcoid</term>
<listitem>
<para>
The oid of the tablespace, or <literal>NULL</> if it's the base
directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>spclocation</term>
<listitem>
<para>
The full path of the tablespace directory, or <literal>NULL</>
if it's the base directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>size</term>
<listitem>
<para>
The approximate size of the tablespace, if progress report has
been requested; otherwise it's <literal>NULL</>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The tar archive for the data directory and each tablespace will contain
all files in the directories, regardless of whether they are
<productname>PostgreSQL</> files or other files added to the same
directory. The only excluded files are:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
<filename>postmaster.pid</>
</para>
</listitem>
<listitem>
<para>
<filename>pg_xlog</> (including subdirectories)
</para>
</listitem>
</itemizedlist>
Owner, group and file mode are set if the underlying filesystem on
the server supports it.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
......
...@@ -12,6 +12,6 @@ subdir = src/backend/replication ...@@ -12,6 +12,6 @@ subdir = src/backend/replication
top_builddir = ../../.. top_builddir = ../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = walsender.o walreceiverfuncs.o walreceiver.o OBJS = walsender.o walreceiverfuncs.o walreceiver.o basebackup.o
include $(top_srcdir)/src/backend/common.mk include $(top_srcdir)/src/backend/common.mk
This diff is collapsed.
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "replication/basebackup.h"
#include "replication/walprotocol.h" #include "replication/walprotocol.h"
#include "replication/walsender.h" #include "replication/walsender.h"
#include "storage/fd.h" #include "storage/fd.h"
...@@ -54,6 +55,7 @@ ...@@ -54,6 +55,7 @@
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/ps_status.h" #include "utils/ps_status.h"
#include "utils/resowner.h"
/* Array of WalSnds in shared memory */ /* Array of WalSnds in shared memory */
...@@ -136,6 +138,9 @@ WalSenderMain(void) ...@@ -136,6 +138,9 @@ WalSenderMain(void)
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(walsnd_context); MemoryContextSwitchTo(walsnd_context);
/* Set up resource owner */
CurrentResourceOwner = ResourceOwnerCreate(NULL, "walsender top-level resource owner");
/* Unblock signals (they were blocked when the postmaster forked us) */ /* Unblock signals (they were blocked when the postmaster forked us) */
PG_SETMASK(&UnBlockSig); PG_SETMASK(&UnBlockSig);
...@@ -305,6 +310,15 @@ WalSndHandshake(void) ...@@ -305,6 +310,15 @@ WalSndHandshake(void)
/* break out of the loop */ /* break out of the loop */
replication_started = true; replication_started = true;
} }
else if (strncmp(query_string, "BASE_BACKUP ", 12) == 0)
{
/* Command is BASE_BACKUP <options>;<label> */
SendBaseBackup(query_string + strlen("BASE_BACKUP "));
/* Send CommandComplete and ReadyForQuery messages */
EndCommand("SELECT", DestRemote);
ReadyForQuery(DestRemote);
/* ReadyForQuery did pq_flush for us */
}
else else
{ {
ereport(FATAL, ereport(FATAL,
......
/*-------------------------------------------------------------------------
*
* basebackup.h
* Exports from replication/basebackup.c.
*
* Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
*
* src/include/replication/walsender.h
*
*-------------------------------------------------------------------------
*/
#ifndef _BASEBACKUP_H
#define _BASEBACKUP_H
extern void SendBaseBackup(const char *options);
#endif /* _BASEBACKUP_H */
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