aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-06-25 22:47:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-06-25 22:47:29 +0000
commitfbcbc5d06f53aea412130deb52e216aa3883fb8d (patch)
tree3c3fde8c9ab650b7db44ccdc1bc7fad0986c8126
parent3acca18d2869282890c180d176259d5e5fcbdd62 (diff)
downloadpostgresql-fbcbc5d06f53aea412130deb52e216aa3883fb8d.tar.gz
postgresql-fbcbc5d06f53aea412130deb52e216aa3883fb8d.zip
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.
-rw-r--r--doc/src/sgml/backup.sgml14
-rw-r--r--src/backend/commands/dbcommands.c32
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>
@@ -1121,6 +1121,18 @@ restore_command = 'copy /mnt/server/archivedir/%f "%p"' # Windows
<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
absolute path, and will therefore be replayed as tablespace creations
with the same absolute path. This might be undesirable if the log is
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 $
*
*-------------------------------------------------------------------------
*/
@@ -515,6 +515,36 @@ createdb(const CreatedbStmt *stmt)
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.
*/
database_file_update_needed();