@@ -4617,23 +4617,44 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
46174617}
46184618
46194619/* Make sure files supposed to be dropped are dropped */
4620- for ( i = 0 ; i < nrels ; i ++ )
4620+ if ( nrels > 0 )
46214621{
4622- SMgrRelation srel = smgropen (xnodes [i ],InvalidBackendId );
4623- ForkNumber fork ;
4622+ /*
4623+ * First update minimum recovery point to cover this WAL record. Once
4624+ * a relation is deleted, there's no going back. The buffer manager
4625+ * enforces the WAL-first rule for normal updates to relation files,
4626+ * so that the minimum recovery point is always updated before the
4627+ * corresponding change in the data file is flushed to disk, but we
4628+ * have to do the same here since we're bypassing the buffer manager.
4629+ *
4630+ * Doing this before deleting the files means that if a deletion fails
4631+ * for some reason, you cannot start up the system even after restart,
4632+ * until you fix the underlying situation so that the deletion will
4633+ * succeed. Alternatively, we could update the minimum recovery point
4634+ * after deletion, but that would leave a small window where the
4635+ * WAL-first rule would be violated.
4636+ */
4637+ XLogFlush (lsn );
46244638
4625- for (fork = 0 ;fork <=MAX_FORKNUM ;fork ++ )
4626- XLogDropRelation (xnodes [i ],fork );
4627- smgrdounlink (srel , true);
4628- smgrclose (srel );
4639+ for (i = 0 ;i < nrels ;i ++ )
4640+ {
4641+ SMgrRelation srel = smgropen (xnodes [i ],InvalidBackendId );
4642+ ForkNumber fork ;
4643+
4644+ for (fork = 0 ;fork <=MAX_FORKNUM ;fork ++ )
4645+ XLogDropRelation (xnodes [i ],fork );
4646+ smgrdounlink (srel , true);
4647+ smgrclose (srel );
4648+ }
46294649}
46304650
46314651/*
46324652 * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
4633- * in normal operation. For example, in DROP DATABASE, we delete all the
4634- * files belonging to the database, and then commit the transaction. If we
4635- * crash after all the files have been deleted but before the commit, you
4636- * have an entry in pg_database without any files. To minimize the window
4653+ * in normal operation. For example, in CREATE DATABASE, we copy all files
4654+ * from the template database, and then commit the transaction. If we
4655+ * crash after all the files have been copied but before the commit, you
4656+ * have files in the data directory without an entry in pg_database. To
4657+ * minimize the window
46374658 * for that, we use ForceSyncCommit() to rush the commit record to disk as
46384659 * quick as possible. We have the same window during recovery, and forcing
46394660 * an XLogFlush() (which updates minRecoveryPoint during recovery) helps