@@ -4489,25 +4489,46 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
4489
4489
}
4490
4490
4491
4491
/* Make sure files supposed to be dropped are dropped */
4492
- for ( i = 0 ; i < xlrec -> nrels ; i ++ )
4492
+ if ( xlrec -> nrels > 0 )
4493
4493
{
4494
- SMgrRelation srel = smgropen (xlrec -> xnodes [i ]);
4495
- ForkNumber fork ;
4494
+ /*
4495
+ * First update minimum recovery point to cover this WAL record. Once
4496
+ * a relation is deleted, there's no going back. The buffer manager
4497
+ * enforces the WAL-first rule for normal updates to relation files,
4498
+ * so that the minimum recovery point is always updated before the
4499
+ * corresponding change in the data file is flushed to disk, but we
4500
+ * have to do the same here since we're bypassing the buffer manager.
4501
+ *
4502
+ * Doing this before deleting the files means that if a deletion fails
4503
+ * for some reason, you cannot start up the system even after restart,
4504
+ * until you fix the underlying situation so that the deletion will
4505
+ * succeed. Alternatively, we could update the minimum recovery point
4506
+ * after deletion, but that would leave a small window where the
4507
+ * WAL-first rule would be violated.
4508
+ */
4509
+ XLogFlush (lsn );
4496
4510
4497
- for (fork = 0 ; fork <= MAX_FORKNUM ; fork ++ )
4511
+ for (i = 0 ; i < xlrec -> nrels ; i ++ )
4498
4512
{
4499
- XLogDropRelation (xlrec -> xnodes [i ], fork );
4500
- smgrdounlink (srel , fork , false, true);
4513
+ SMgrRelation srel = smgropen (xlrec -> xnodes [i ]);
4514
+ ForkNumber fork ;
4515
+
4516
+ for (fork = 0 ; fork <= MAX_FORKNUM ; fork ++ )
4517
+ {
4518
+ XLogDropRelation (xlrec -> xnodes [i ], fork );
4519
+ smgrdounlink (srel , fork , false, true);
4520
+ }
4521
+ smgrclose (srel );
4501
4522
}
4502
- smgrclose (srel );
4503
4523
}
4504
4524
4505
4525
/*
4506
4526
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
4507
- * in normal operation. For example, in DROP DATABASE, we delete all the
4508
- * files belonging to the database, and then commit the transaction. If we
4509
- * crash after all the files have been deleted but before the commit, you
4510
- * have an entry in pg_database without any files. To minimize the window
4527
+ * in normal operation. For example, in CREATE DATABASE, we copy all files
4528
+ * from the template database, and then commit the transaction. If we
4529
+ * crash after all the files have been copied but before the commit, you
4530
+ * have files in the data directory without an entry in pg_database. To
4531
+ * minimize the window
4511
4532
* for that, we use ForceSyncCommit() to rush the commit record to disk as
4512
4533
* quick as possible. We have the same window during recovery, and forcing
4513
4534
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
0 commit comments