@@ -4544,25 +4544,46 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
4544
4544
}
4545
4545
4546
4546
/* Make sure files supposed to be dropped are dropped */
4547
- for ( i = 0 ; i < xlrec -> nrels ; i ++ )
4547
+ if ( xlrec -> nrels > 0 )
4548
4548
{
4549
- SMgrRelation srel = smgropen (xlrec -> xnodes [i ], InvalidBackendId );
4550
- ForkNumber fork ;
4549
+ /*
4550
+ * First update minimum recovery point to cover this WAL record. Once
4551
+ * a relation is deleted, there's no going back. The buffer manager
4552
+ * enforces the WAL-first rule for normal updates to relation files,
4553
+ * so that the minimum recovery point is always updated before the
4554
+ * corresponding change in the data file is flushed to disk, but we
4555
+ * have to do the same here since we're bypassing the buffer manager.
4556
+ *
4557
+ * Doing this before deleting the files means that if a deletion fails
4558
+ * for some reason, you cannot start up the system even after restart,
4559
+ * until you fix the underlying situation so that the deletion will
4560
+ * succeed. Alternatively, we could update the minimum recovery point
4561
+ * after deletion, but that would leave a small window where the
4562
+ * WAL-first rule would be violated.
4563
+ */
4564
+ XLogFlush (lsn );
4551
4565
4552
- for (fork = 0 ; fork <= MAX_FORKNUM ; fork ++ )
4566
+ for (i = 0 ; i < xlrec -> nrels ; i ++ )
4553
4567
{
4554
- XLogDropRelation (xlrec -> xnodes [i ], fork );
4555
- smgrdounlink (srel , fork , true);
4568
+ SMgrRelation srel = smgropen (xlrec -> xnodes [i ], InvalidBackendId );
4569
+ ForkNumber fork ;
4570
+
4571
+ for (fork = 0 ; fork <= MAX_FORKNUM ; fork ++ )
4572
+ {
4573
+ XLogDropRelation (xlrec -> xnodes [i ], fork );
4574
+ smgrdounlink (srel , fork , true);
4575
+ }
4576
+ smgrclose (srel );
4556
4577
}
4557
- smgrclose (srel );
4558
4578
}
4559
4579
4560
4580
/*
4561
4581
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
4562
- * in normal operation. For example, in DROP DATABASE, we delete all the
4563
- * files belonging to the database, and then commit the transaction. If we
4564
- * crash after all the files have been deleted but before the commit, you
4565
- * have an entry in pg_database without any files. To minimize the window
4582
+ * in normal operation. For example, in CREATE DATABASE, we copy all files
4583
+ * from the template database, and then commit the transaction. If we
4584
+ * crash after all the files have been copied but before the commit, you
4585
+ * have files in the data directory without an entry in pg_database. To
4586
+ * minimize the window
4566
4587
* for that, we use ForceSyncCommit() to rush the commit record to disk as
4567
4588
* quick as possible. We have the same window during recovery, and forcing
4568
4589
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
0 commit comments