@@ -4617,23 +4617,44 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
4617
4617
}
4618
4618
4619
4619
/* Make sure files supposed to be dropped are dropped */
4620
- for ( i = 0 ; i < nrels ; i ++ )
4620
+ if ( nrels > 0 )
4621
4621
{
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 );
4624
4638
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
+ }
4629
4649
}
4630
4650
4631
4651
/*
4632
4652
* 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
4637
4658
* for that, we use ForceSyncCommit() to rush the commit record to disk as
4638
4659
* quick as possible. We have the same window during recovery, and forcing
4639
4660
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
0 commit comments