From fbcbc5d06f53aea412130deb52e216aa3883fb8d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 25 Jun 2005 22:47:29 +0000
Subject: [PATCH] Force a checkpoint before committing a CREATE DATABASE
 command.  This should fix the recent reports of "index is not a btree"
 failures, as well as preventing a more obscure race condition involving
 changes to a template database just after copying it with CREATE DATABASE.

---
 doc/src/sgml/backup.sgml          | 14 +++++++++++++-
 src/backend/commands/dbcommands.c | 32 ++++++++++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index ba55eb634ae..01cdae83d69 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.68 2005/06/21 20:45:43 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.69 2005/06/25 22:47:28 tgl Exp $
 -->
 <chapter id="backup">
  <title>Backup and Restore</title>
@@ -1119,6 +1119,18 @@ restore_command = 'copy /mnt/server/archivedir/%f "%p"'  # Windows
     </para>
    </listitem>
 
+   <listitem>
+    <para>
+     If a <command>CREATE DATABASE</> command is executed while a base
+     backup is being taken, and then the template database that the
+     <command>CREATE DATABASE</> copied is modified while the base backup
+     is still in progress, it is possible that recovery will cause those
+     modifications to be propagated into the created database as well.
+     This is of course undesirable.  To avoid this risk, it is best not to
+     modify any template databases while taking a base backup.
+    </para>
+   </listitem>
+
    <listitem>
     <para>
      <command>CREATE TABLESPACE</> commands are WAL-logged with the literal
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 135c8a73f53..6fa6aa5b44b 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.160 2005/06/21 04:02:31 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.161 2005/06/25 22:47:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -514,6 +514,36 @@ createdb(const CreatedbStmt *stmt)
 	/* Close pg_database, but keep exclusive lock till commit */
 	heap_close(pg_database_rel, NoLock);
 
+	/*
+	 * We force a checkpoint before committing.  This effectively means
+	 * that committed XLOG_DBASE_CREATE operations will never need to be
+	 * replayed (at least not in ordinary crash recovery; we still have
+	 * to make the XLOG entry for the benefit of PITR operations).
+	 * This avoids two nasty scenarios:
+	 *
+	 * #1: When PITR is off, we don't XLOG the contents of newly created
+	 * indexes; therefore the drop-and-recreate-whole-directory behavior
+	 * of DBASE_CREATE replay would lose such indexes.
+	 *
+	 * #2: Since we have to recopy the source database during DBASE_CREATE
+	 * replay, we run the risk of copying changes in it that were committed
+	 * after the original CREATE DATABASE command but before the system
+	 * crash that led to the replay.  This is at least unexpected and at
+	 * worst could lead to inconsistencies, eg duplicate table names.
+	 *
+	 * (Both of these were real bugs in releases 8.0 through 8.0.3.)
+	 *
+	 * In PITR replay, the first of these isn't an issue, and the second
+	 * is only a risk if the CREATE DATABASE and subsequent template
+	 * database change both occur while a base backup is being taken.
+	 * There doesn't seem to be much we can do about that except document
+	 * it as a limitation.
+	 *
+	 * Perhaps if we ever implement CREATE DATABASE in a less cheesy
+	 * way, we can avoid this.
+	 */
+	RequestCheckpoint(true);
+
 	/*
 	 * Set flag to update flat database file at commit.
 	 */
-- 
GitLab