xlogflush-before-truncation-1.patch
text/x-diff
Filename: xlogflush-before-truncation-1.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/transam/xact.c | 32 | 0 |
| src/backend/catalog/storage.c | 17 | 0 |
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
***************
*** 4617,4639 **** xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
}
/* Make sure files supposed to be dropped are dropped */
! for (i = 0; i < nrels; i++)
{
! SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
! ForkNumber fork;
! for (fork = 0; fork <= MAX_FORKNUM; fork++)
! XLogDropRelation(xnodes[i], fork);
! smgrdounlink(srel, true);
! smgrclose(srel);
}
/*
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
! * in normal operation. For example, in DROP DATABASE, we delete all the
! * files belonging to the database, and then commit the transaction. If we
! * crash after all the files have been deleted but before the commit, you
! * have an entry in pg_database without any files. To minimize the window
* for that, we use ForceSyncCommit() to rush the commit record to disk as
* quick as possible. We have the same window during recovery, and forcing
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
--- 4617,4660 ----
}
/* Make sure files supposed to be dropped are dropped */
! if (nrels > 0)
{
! /*
! * First update minimum recovery point to cover this WAL record. Once
! * a relation is deleted, there's no going back. The buffer manager
! * enforces the WAL-first rule for normal updates to relation files,
! * so that the minimum recovery point is always updated before the
! * corresponding change in the data file is flushed to disk, but we
! * have to do the same here since we're bypassing the buffer manager.
! *
! * Doing this before the deleting the files means that if a deletion
! * fails for some reason, you cannot start up the system even after
! * restart, until you fix the underlying situation so that the
! * deletion will succeed. Alternatively, we could update the minimum
! * recovery point after deletion, but that would leave a small window
! * where the WAL-first rule would be violated.
! */
! XLogFlush(lsn);
! for (i = 0; i < nrels; i++)
! {
! SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
! ForkNumber fork;
!
! for (fork = 0; fork <= MAX_FORKNUM; fork++)
! XLogDropRelation(xnodes[i], fork);
! smgrdounlink(srel, true);
! smgrclose(srel);
! }
}
/*
* We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
! * in normal operation. For example, in CREATE DATABASE, we copy all the
! * files from the template database, and then commit the transaction. If we
! * crash after all the files have been copied but before the commit, you
! * have files in the data directory without an entry in pg_database.
! * To minimize the window
* for that, we use ForceSyncCommit() to rush the commit record to disk as
* quick as possible. We have the same window during recovery, and forcing
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps
*** a/src/backend/catalog/storage.c
--- b/src/backend/catalog/storage.c
***************
*** 482,487 **** smgr_redo(XLogRecPtr lsn, XLogRecord *record)
--- 482,504 ----
*/
smgrcreate(reln, MAIN_FORKNUM, true);
+ /*
+ * Before we perform the truncation, update minimum recovery point
+ * to cover this WAL record. Once the relation is truncated, there's
+ * no going back. The buffer manager enforces the WAL-first rule
+ * for normal updates to relation files, so that the minimum recovery
+ * point is always updated before the corresponding change in the
+ * data file is flushed to disk.
+ *
+ * Doing this before the truncation means that if the truncation fails
+ * for some reason, you cannot start up the system even after restart,
+ * until you fix the underlying situation so that the truncation will
+ * succeed. Alternatively, we could update the minimum recovery point
+ * after truncation, but that would leave a small window where the
+ * WAL-first rule could be violated.
+ */
+ XLogFlush(lsn);
+
smgrtruncate(reln, MAIN_FORKNUM, xlrec->blkno);
/* Also tell xlogutils.c about it */