@@ -4637,23 +4637,44 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
4637
4637
}
4638
4638
4639
4639
/* Make sure files supposed to be dropped are dropped */
4640
- for ( i = 0 ; i < nrels ; i ++ )
4640
+ if ( nrels > 0 )
4641
4641
{
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 );
4644
4658
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
+ }
4649
4669
}
4650
4670
4651
4671
/*
4652
4672
* 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
4657
4678
* for that, we use ForceSyncCommit() to rush the commit record to disk as
4658
4679
* quick as possible. We have the same window during recovery, and forcing
4659
4680
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
0 commit comments