@@ -4637,23 +4637,44 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
46374637}
46384638
46394639/* Make sure files supposed to be dropped are dropped */
4640- for ( i = 0 ; i < nrels ; i ++ )
4640+ if ( nrels > 0 )
46414641{
4642- SMgrRelation srel = smgropen (xnodes [i ],InvalidBackendId );
4643- ForkNumber fork ;
4642+ /*
4643+ * First update minimum recovery point to cover this WAL record. Once
4644+ * a relation is deleted, there's no going back. The buffer manager
4645+ * enforces the WAL-first rule for normal updates to relation files,
4646+ * so that the minimum recovery point is always updated before the
4647+ * corresponding change in the data file is flushed to disk, but we
4648+ * have to do the same here since we're bypassing the buffer manager.
4649+ *
4650+ * Doing this before deleting the files means that if a deletion fails
4651+ * for some reason, you cannot start up the system even after restart,
4652+ * until you fix the underlying situation so that the deletion will
4653+ * succeed. Alternatively, we could update the minimum recovery point
4654+ * after deletion, but that would leave a small window where the
4655+ * WAL-first rule would be violated.
4656+ */
4657+ XLogFlush (lsn );
46444658
4645- for (fork = 0 ;fork <=MAX_FORKNUM ;fork ++ )
4646- XLogDropRelation (xnodes [i ],fork );
4647- smgrdounlink (srel , true);
4648- smgrclose (srel );
4659+ for (i = 0 ;i < nrels ;i ++ )
4660+ {
4661+ SMgrRelation srel = smgropen (xnodes [i ],InvalidBackendId );
4662+ ForkNumber fork ;
4663+
4664+ for (fork = 0 ;fork <=MAX_FORKNUM ;fork ++ )
4665+ XLogDropRelation (xnodes [i ],fork );
4666+ smgrdounlink (srel , true);
4667+ smgrclose (srel );
4668+ }
46494669}
46504670
46514671/*
46524672 * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
4653- * in normal operation. For example, in DROP DATABASE, we delete all the
4654- * files belonging to the database, and then commit the transaction. If we
4655- * crash after all the files have been deleted but before the commit, you
4656- * have an entry in pg_database without any files. To minimize the window
4673+ * in normal operation. For example, in CREATE DATABASE, we copy all files
4674+ * from the template database, and then commit the transaction. If we
4675+ * crash after all the files have been copied but before the commit, you
4676+ * have files in the data directory without an entry in pg_database. To
4677+ * minimize the window
46574678 * for that, we use ForceSyncCommit() to rush the commit record to disk as
46584679 * quick as possible. We have the same window during recovery, and forcing
46594680 * an XLogFlush() (which updates minRecoveryPoint during recovery) helps