summaryrefslogtreecommitdiff
path: root/src/backend/commands/dbcommands.c
diff options
context:
space:
mode:
authorAndres Freund2014-10-20 21:43:46 +0000
committerAndres Freund2014-10-20 21:43:46 +0000
commit7dbb60693820c20b562c12f58040c9871d6ab787 (patch)
tree2acdf8ba1660906f170dae3641cd9540d46fdec0 /src/backend/commands/dbcommands.c
parent83dc5908c207bc0ff4256eb862f6a211ad5596ec (diff)
Flush unlogged table's buffers when copying or moving databases.
CREATE DATABASE and ALTER DATABASE .. SET TABLESPACE copy the source database directory on the filesystem level. To ensure the on disk state is consistent they block out users of the affected database and force a checkpoint to flush out all data to disk. Unfortunately, up to now, that checkpoint didn't flush out dirty buffers from unlogged relations. That bug means there could be leftover dirty buffers in either the template database, or the database in its old location. Leading to problems when accessing relations in an inconsistent state; and to possible problems during shutdown in the SET TABLESPACE case because buffers belonging files that don't exist anymore are flushed. This was reported in bug #10675 by Maxim Boguk. Fix by Pavan Deolasee, modified somewhat by me. Reviewed by MauMau and Fujii Masao. Backpatch to 9.1 where unlogged tables were introduced.
Diffstat (limited to 'src/backend/commands/dbcommands.c')
-rw-r--r--src/backend/commands/dbcommands.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index b52e6b9bc07..1c56b4de0d2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -549,15 +549,17 @@ createdb(const CreatedbStmt *stmt)
InvokeObjectPostCreateHook(DatabaseRelationId, dboid, 0);
/*
- * Force a checkpoint before starting the copy. This will force dirty
- * buffers out to disk, to ensure source database is up-to-date on disk
- * for the copy. FlushDatabaseBuffers() would suffice for that, but we
- * also want to process any pending unlink requests. Otherwise, if a
- * checkpoint happened while we're copying files, a file might be deleted
- * just when we're about to copy it, causing the lstat() call in copydir()
- * to fail with ENOENT.
+ * Force a checkpoint before starting the copy. This will force all dirty
+ * buffers, including those of unlogged tables, out to disk, to ensure
+ * source database is up-to-date on disk for the copy.
+ * FlushDatabaseBuffers() would suffice for that, but we also want
+ * to process any pending unlink requests. Otherwise, if a checkpoint
+ * happened while we're copying files, a file might be deleted just when
+ * we're about to copy it, causing the lstat() call in copydir() to fail
+ * with ENOENT.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+ RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
+ | CHECKPOINT_FLUSH_ALL);
/*
* Once we start copying subdirectories, we need to be able to clean 'em
@@ -1138,8 +1140,9 @@ movedb(const char *dbname, const char *tblspcname)
dst_dbpath = GetDatabasePath(db_id, dst_tblspcoid);
/*
- * Force a checkpoint before proceeding. This will force dirty buffers out
- * to disk, to ensure source database is up-to-date on disk for the copy.
+ * Force a checkpoint before proceeding. This will force all dirty
+ * buffers, including those of unlogged tables, out to disk, to ensure
+ * source database is up-to-date on disk for the copy.
* FlushDatabaseBuffers() would suffice for that, but we also want to
* process any pending unlink requests. Otherwise, the check for existing
* files in the target directory might fail unnecessarily, not to mention
@@ -1147,7 +1150,8 @@ movedb(const char *dbname, const char *tblspcname)
* On Windows, this also ensures that background procs don't hold any open
* files, which would cause rmdir() to fail.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+ RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
+ | CHECKPOINT_FLUSH_ALL);
/*
* Check for existence of files in the target directory, i.e., objects of