Skip to content

Commit 96a7128

Browse files
committed
Sync pg_dump and pg_dumpall output
Before exiting any files are fsync'ed. A --no-sync option is also provided for a faster exit if desired. Michael Paquier. Reviewed by Albe Laurenz Discussion: https://postgr.es/m/CAB7nPqS1uZ=Ov+UruW6jr3vB-S_DLVMPc0dQpV-fTDjmm0ZQMg@mail.gmail.com
1 parent 9b013dc commit 96a7128

File tree

12 files changed

+103
-8
lines changed

12 files changed

+103
-8
lines changed

doc/src/sgml/ref/pg_dump.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,20 @@ PostgreSQL documentation
859859
</listitem>
860860
</varlistentry>
861861

862+
<varlistentry>
863+
<term><option>--no-sync</option></term>
864+
<listitem>
865+
<para>
866+
By default, <command>pg_dump</command> will wait for all files
867+
to be written safely to disk. This option causes
868+
<command>pg_dump</command> to return without waiting, which is
869+
faster, but means that a subsequent operating system crash can leave
870+
the dump corrupt. Generally, this option is useful for testing
871+
but should not be used when dumping data from production installation.
872+
</para>
873+
</listitem>
874+
</varlistentry>
875+
862876
<varlistentry>
863877
<term><option>--quote-all-identifiers</></term>
864878
<listitem>

doc/src/sgml/ref/pg_dumpall.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,20 @@ PostgreSQL documentation
354354
</listitem>
355355
</varlistentry>
356356

357+
<varlistentry>
358+
<term><option>--no-sync</option></term>
359+
<listitem>
360+
<para>
361+
By default, <command>pg_dumpall</command> will wait for all files
362+
to be written safely to disk. This option causes
363+
<command>pg_dumpall</command> to return without waiting, which is
364+
faster, but means that a subsequent operating system crash can leave
365+
the dump corrupt. Generally, this option is useful for testing
366+
but should not be used when dumping data from production installation.
367+
</para>
368+
</listitem>
369+
</varlistentry>
370+
357371
<varlistentry>
358372
<term><option>--no-tablespaces</option></term>
359373
<listitem>

src/bin/pg_dump/pg_backup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ extern Archive *OpenArchive(const char *FileSpec, const ArchiveFormat fmt);
276276

277277
/* Create a new archive */
278278
extern Archive *CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
279-
const int compression, ArchiveMode mode,
279+
const int compression, bool dosync, ArchiveMode mode,
280280
SetupWorkerPtr setupDumpWorker);
281281

282282
/* The --list option */

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ static const char *modulename = gettext_noop("archiver");
5454

5555

5656
static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
57-
const int compression, ArchiveMode mode, SetupWorkerPtr setupWorkerPtr);
57+
const int compression, bool dosync, ArchiveMode mode,
58+
SetupWorkerPtr setupWorkerPtr);
5859
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
5960
ArchiveHandle *AH);
6061
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass);
@@ -202,10 +203,12 @@ setupRestoreWorker(Archive *AHX)
202203
/* Public */
203204
Archive *
204205
CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
205-
const int compression, ArchiveMode mode, SetupWorkerPtr setupDumpWorker)
206+
const int compression, bool dosync, ArchiveMode mode,
207+
SetupWorkerPtr setupDumpWorker)
206208

207209
{
208-
ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, mode, setupDumpWorker);
210+
ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, dosync,
211+
mode, setupDumpWorker);
209212

210213
return (Archive *) AH;
211214
}
@@ -215,7 +218,7 @@ CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
215218
Archive *
216219
OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
217220
{
218-
ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, archModeRead, setupRestoreWorker);
221+
ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, true, archModeRead, setupRestoreWorker);
219222

220223
return (Archive *) AH;
221224
}
@@ -2269,7 +2272,8 @@ _discoverArchiveFormat(ArchiveHandle *AH)
22692272
*/
22702273
static ArchiveHandle *
22712274
_allocAH(const char *FileSpec, const ArchiveFormat fmt,
2272-
const int compression, ArchiveMode mode, SetupWorkerPtr setupWorkerPtr)
2275+
const int compression, bool dosync, ArchiveMode mode,
2276+
SetupWorkerPtr setupWorkerPtr)
22732277
{
22742278
ArchiveHandle *AH;
22752279

@@ -2323,6 +2327,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
23232327

23242328
AH->mode = mode;
23252329
AH->compression = compression;
2330+
AH->dosync = dosync;
23262331

23272332
memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
23282333

src/bin/pg_dump/pg_backup_archiver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ struct _archiveHandle
312312
* values for compression: -1
313313
* Z_DEFAULT_COMPRESSION 0 COMPRESSION_NONE
314314
* 1-9 levels for gzip compression */
315+
bool dosync; /* data requested to be synced on sight */
315316
ArchiveMode mode; /* File mode - r or w */
316317
void *formatData; /* Header data specific to file format */
317318

src/bin/pg_dump/pg_backup_custom.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "compress_io.h"
2929
#include "parallel.h"
3030
#include "pg_backup_utils.h"
31+
#include "common/file_utils.h"
3132

3233
/*--------
3334
* Routines in the format interface
@@ -721,6 +722,10 @@ _CloseArchive(ArchiveHandle *AH)
721722
if (fclose(AH->FH) != 0)
722723
exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
723724

725+
/* Sync the output file if one is defined */
726+
if (AH->dosync && AH->mode == archModeWrite && AH->fSpec)
727+
(void) fsync_fname(AH->fSpec, false, progname);
728+
724729
AH->FH = NULL;
725730
}
726731

src/bin/pg_dump/pg_backup_directory.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "compress_io.h"
3838
#include "parallel.h"
3939
#include "pg_backup_utils.h"
40+
#include "common/file_utils.h"
4041

4142
#include <dirent.h>
4243
#include <sys/stat.h>
@@ -593,6 +594,13 @@ _CloseArchive(ArchiveHandle *AH)
593594
WriteDataChunks(AH, ctx->pstate);
594595

595596
ParallelBackupEnd(AH, ctx->pstate);
597+
598+
/*
599+
* In directory mode, there is no need to sync all the entries
600+
* individually. Just recurse once through all the files generated.
601+
*/
602+
if (AH->dosync)
603+
fsync_dir_recurse(ctx->directory, progname);
596604
}
597605
AH->FH = NULL;
598606
}

src/bin/pg_dump/pg_backup_tar.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "pg_backup_tar.h"
3434
#include "pg_backup_utils.h"
3535
#include "pgtar.h"
36+
#include "common/file_utils.h"
3637
#include "fe_utils/string_utils.h"
3738

3839
#include <sys/stat.h>
@@ -901,6 +902,10 @@ _CloseArchive(ArchiveHandle *AH)
901902
if (fputc(0, ctx->tarFH) == EOF)
902903
WRITE_ERROR_EXIT;
903904
}
905+
906+
/* Sync the output file if one is defined */
907+
if (AH->dosync && AH->fSpec)
908+
(void) fsync_fname(AH->fSpec, false, progname);
904909
}
905910

906911
AH->FH = NULL;

src/bin/pg_dump/pg_dump.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ typedef enum OidOptions
8989
/* global decls */
9090
bool g_verbose; /* User wants verbose narration of our
9191
* activities. */
92+
static bool dosync = true; /* Issue fsync() to make dump durable
93+
* on disk. */
9294

9395
/* subquery used to convert user ID (eg, datdba) to user name */
9496
static const char *username_subquery;
@@ -353,6 +355,7 @@ main(int argc, char **argv)
353355
{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
354356
{"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1},
355357
{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
358+
{"no-sync", no_argument, NULL, 7},
356359

357360
{NULL, 0, NULL, 0}
358361
};
@@ -533,6 +536,10 @@ main(int argc, char **argv)
533536
dumpsnapshot = pg_strdup(optarg);
534537
break;
535538

539+
case 7: /* no-sync */
540+
dosync = false;
541+
break;
542+
536543
default:
537544
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
538545
exit_nicely(1);
@@ -632,8 +639,8 @@ main(int argc, char **argv)
632639
exit_horribly(NULL, "parallel backup only supported by the directory format\n");
633640

634641
/* Open the output file */
635-
fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode,
636-
setupDumpWorker);
642+
fout = CreateArchive(filename, archiveFormat, compressLevel, dosync,
643+
archiveMode, setupDumpWorker);
637644

638645
/* Make dump options accessible right away */
639646
SetArchiveOptions(fout, &dopt, NULL);
@@ -914,6 +921,7 @@ help(const char *progname)
914921
printf(_(" -V, --version output version information, then exit\n"));
915922
printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
916923
printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
924+
printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
917925
printf(_(" -?, --help show this help, then exit\n"));
918926

919927
printf(_("\nOptions controlling the output content:\n"));

src/bin/pg_dump/pg_dumpall.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "dumputils.h"
2424
#include "pg_backup.h"
25+
#include "common/file_utils.h"
2526
#include "fe_utils/string_utils.h"
2627

2728
/* version string we expect back from pg_dump */
@@ -63,6 +64,7 @@ static PQExpBuffer pgdumpopts;
6364
static char *connstr = "";
6465
static bool skip_acls = false;
6566
static bool verbose = false;
67+
static bool dosync = true;
6668

6769
static int binary_upgrade = 0;
6870
static int column_inserts = 0;
@@ -127,6 +129,7 @@ main(int argc, char *argv[])
127129
{"role", required_argument, NULL, 3},
128130
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
129131
{"no-security-labels", no_argument, &no_security_labels, 1},
132+
{"no-sync", no_argument, NULL, 4},
130133
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
131134
{"no-role-passwords", no_argument, &no_role_passwords, 1},
132135

@@ -297,6 +300,11 @@ main(int argc, char *argv[])
297300
appendShellString(pgdumpopts, use_role);
298301
break;
299302

303+
case 4:
304+
dosync = false;
305+
appendPQExpBufferStr(pgdumpopts, " --no-sync");
306+
break;
307+
300308
default:
301309
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
302310
exit_nicely(1);
@@ -549,8 +557,14 @@ main(int argc, char *argv[])
549557
fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
550558

551559
if (filename)
560+
{
552561
fclose(OPF);
553562

563+
/* sync the resulting file, errors are not fatal */
564+
if (dosync)
565+
(void) fsync_fname(filename, false, progname);
566+
}
567+
554568
exit_nicely(0);
555569
}
556570

@@ -586,6 +600,7 @@ help(void)
586600
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
587601
printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
588602
printf(_(" --no-security-labels do not dump security label assignments\n"));
603+
printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
589604
printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
590605
printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
591606
printf(_(" --no-role-passwords do not dump passwords for roles\n"));

src/common/file_utils.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,25 @@ fsync_pgdata(const char *pg_data,
115115
walkdir(pg_tblspc, fsync_fname, true, progname);
116116
}
117117

118+
/*
119+
* Issue fsync recursively on the given directory and all its contents.
120+
*
121+
* This is a convenient wrapper on top of walkdir().
122+
*/
123+
void
124+
fsync_dir_recurse(const char *dir, const char *progname)
125+
{
126+
/*
127+
* If possible, hint to the kernel that we're soon going to fsync the data
128+
* directory and its contents.
129+
*/
130+
#ifdef PG_FLUSH_DATA_WORKS
131+
walkdir(dir, pre_sync_fname, false, progname);
132+
#endif
133+
134+
walkdir(dir, fsync_fname, false, progname);
135+
}
136+
118137
/*
119138
* walkdir: recursively walk a directory, applying the action to each
120139
* regular file and directory (including the named directory itself).

src/include/common/file_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern int fsync_fname(const char *fname, bool isdir,
1919
const char *progname);
2020
extern void fsync_pgdata(const char *pg_data, const char *progname,
2121
int serverVersion);
22+
extern void fsync_dir_recurse(const char *dir, const char *progname);
2223
extern int durable_rename(const char *oldfile, const char *newfile,
2324
const char *progname);
2425
extern int fsync_parent_path(const char *fname, const char *progname);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy