atomicLSN-v3-Use-atomic-ops-for-unloggedLSNs.patch
application/octet-stream
Filename: atomicLSN-v3-Use-atomic-ops-for-unloggedLSNs.patch
Type: application/octet-stream
Part: 0
Message:
Re: Atomic ops for unlogged LSN
Patch
Format: format-patch
Series: patch v3
Subject: Use atomic increment instead of a lock when advancing the unlogged LSN
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 24 | 24 |
From 479bfdc34f6dc79cf31cdaac355465117b7a1992 Mon Sep 17 00:00:00 2001
From: John Morris <john.morris@crunchydata.com>
Date: Wed, 1 Nov 2023 13:16:38 -0700
Subject: [PATCH] Use atomic increment instead of a lock when advancing the
unlogged LSN
---
src/backend/access/transam/xlog.c | 48 +++++++++++++++----------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b541be8eec..d903f7280f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -469,9 +469,8 @@ typedef struct XLogCtlData
XLogSegNo lastRemovedSegNo; /* latest removed/recycled XLOG segment */
- /* Fake LSN counter, for unlogged relations. Protected by ulsn_lck. */
- XLogRecPtr unloggedLSN;
- slock_t ulsn_lck;
+ /* Fake LSN counter for unlogged relations. Updated atomically. */
+ pg_atomic_uint64 unloggedLSN;
/* Time and LSN of last xlog segment switch. Protected by WALWriteLock. */
pg_time_t lastSegSwitchTime;
@@ -4287,21 +4286,16 @@ DataChecksumsEnabled(void)
*
* Each call generates an LSN that is greater than any previous value
* returned. The current counter value is saved and restored across clean
- * shutdowns, but like unlogged relations, does not survive a crash. This can
- * be used in lieu of real LSN values returned by XLogInsert, if you need an
- * LSN-like increasing sequence of numbers without writing any WAL.
+ * shutdowns, but it is reset after a crash. Consequently, it should
+ * only be used for unlogged relations or for data which does not survive
+ * a crash. An unlogged LSN may be used in lieu of real LSN values
+ * returned by XLogInsert, if you need an LSN-like increasing sequence
+ * of numbers without writing any WAL.
*/
XLogRecPtr
GetFakeLSNForUnloggedRel(void)
{
- XLogRecPtr nextUnloggedLSN;
-
- /* increment the unloggedLSN counter, need SpinLock */
- SpinLockAcquire(&XLogCtl->ulsn_lck);
- nextUnloggedLSN = XLogCtl->unloggedLSN++;
- SpinLockRelease(&XLogCtl->ulsn_lck);
-
- return nextUnloggedLSN;
+ return pg_atomic_fetch_add_u64(&XLogCtl->unloggedLSN, 1);
}
/*
@@ -4714,7 +4708,6 @@ XLOGShmemInit(void)
SpinLockInit(&XLogCtl->Insert.insertpos_lck);
SpinLockInit(&XLogCtl->info_lck);
- SpinLockInit(&XLogCtl->ulsn_lck);
}
/*
@@ -5319,9 +5312,9 @@ StartupXLOG(void)
* the unlogged LSN counter can be reset too.
*/
if (ControlFile->state == DB_SHUTDOWNED)
- XLogCtl->unloggedLSN = ControlFile->unloggedLSN;
+ pg_atomic_init_u64(&XLogCtl->unloggedLSN, ControlFile->unloggedLSN);
else
- XLogCtl->unloggedLSN = FirstNormalUnloggedLSN;
+ pg_atomic_init_u64(&XLogCtl->unloggedLSN, FirstNormalUnloggedLSN);
/*
* Copy any missing timeline history files between 'now' and the recovery
@@ -6899,13 +6892,20 @@ CreateCheckPoint(int flags)
ControlFile->minRecoveryPointTLI = 0;
/*
- * Persist unloggedLSN value. It's reset on crash recovery, so this goes
- * unused on non-shutdown checkpoints, but seems useful to store it always
- * for debugging purposes.
- */
- SpinLockAcquire(&XLogCtl->ulsn_lck);
- ControlFile->unloggedLSN = XLogCtl->unloggedLSN;
- SpinLockRelease(&XLogCtl->ulsn_lck);
+ * Persist the unloggedLSN.
+ * We have two cases to consider:
+ * 1) We are shutting down. All other backends have finished, and
+ * the unloggedLSN isn't being updated any more. There are no race
+ * conditions. We just save the current value and restore it
+ * when we are restarting.
+ * 2) We are actively running, say during a checkpoint.
+ * The unloggedLSN is being updated by other backends,
+ * but the value we write out doesn't matter.
+ * The unloggedLSN will be reset on crash recovery.
+ * We could simply write a zero, but the current value
+ * might be useful for debugging.
+ */
+ ControlFile->unloggedLSN = pg_atomic_read_u64(&XLogCtl->unloggedLSN);
UpdateControlFile();
LWLockRelease(ControlFileLock);
--
2.33.0