From 98fa70754a8c68cdfb20f27bd7f6e6e3e5f8ed92 Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Wed, 11 Jan 2023 18:07:10 +0300 Subject: [PATCH] [PGPRO-7624] use atomic old_snapshot_threshold Using spinlock to access old_snapshot_threshold lead to the bottleneck on replica, since GetOldSnapshotThresholdTimestamp is called too often. So, switch to an atomic values. tags: commitfest_hotfix --- src/backend/utils/time/snapmgr.c | 31 +++++++++++++++++-------------- src/include/utils/old_snapshot.h | 5 +++-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 7d11ae34781..0902e29f224 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -230,8 +230,8 @@ SnapMgrInit(void) oldSnapshotControl->latest_xmin = InvalidTransactionId; oldSnapshotControl->next_map_update = 0; SpinLockInit(&oldSnapshotControl->mutex_threshold); - oldSnapshotControl->threshold_timestamp = 0; - oldSnapshotControl->threshold_xid = InvalidTransactionId; + pg_atomic_init_u64(&oldSnapshotControl->threshold_timestamp, 0); + pg_atomic_init_u32(&oldSnapshotControl->threshold_xid, InvalidTransactionId); oldSnapshotControl->head_offset = 0; oldSnapshotControl->head_timestamp = 0; oldSnapshotControl->count_used = 0; @@ -1706,9 +1706,7 @@ GetOldSnapshotThresholdTimestamp(void) { TimestampTz threshold_timestamp; - SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - threshold_timestamp = oldSnapshotControl->threshold_timestamp; - SpinLockRelease(&oldSnapshotControl->mutex_threshold); + threshold_timestamp = pg_atomic_read_u64(&oldSnapshotControl->threshold_timestamp); return threshold_timestamp; } @@ -1716,11 +1714,18 @@ GetOldSnapshotThresholdTimestamp(void) void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit) { + TimestampTz threshold_timestamp; + TransactionId threshold_xid; + SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - Assert(oldSnapshotControl->threshold_timestamp <= ts); - Assert(TransactionIdPrecedesOrEquals(oldSnapshotControl->threshold_xid, xlimit)); - oldSnapshotControl->threshold_timestamp = ts; - oldSnapshotControl->threshold_xid = xlimit; + threshold_timestamp = pg_atomic_read_u64(&oldSnapshotControl->threshold_timestamp); + threshold_xid = pg_atomic_read_u32(&oldSnapshotControl->threshold_xid); + + Assert(threshold_timestamp <= ts); + Assert(TransactionIdPrecedesOrEquals(threshold_xid, xlimit)); + + pg_atomic_write_u64(&oldSnapshotControl->threshold_timestamp, ts); + pg_atomic_write_u32(&oldSnapshotControl->threshold_xid, xlimit); SpinLockRelease(&oldSnapshotControl->mutex_threshold); } @@ -1739,9 +1744,7 @@ SnapshotTooOldMagicForTest(void) ts -= 5 * USECS_PER_SEC; - SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - oldSnapshotControl->threshold_timestamp = ts; - SpinLockRelease(&oldSnapshotControl->mutex_threshold); + pg_atomic_write_u64(&oldSnapshotControl->threshold_timestamp, ts); } /* @@ -1846,8 +1849,8 @@ TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, /* Check for fast exit without LW locking. */ SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - threshold_timestamp = oldSnapshotControl->threshold_timestamp; - threshold_xid = oldSnapshotControl->threshold_xid; + threshold_timestamp = pg_atomic_read_u64(&oldSnapshotControl->threshold_timestamp); + threshold_xid = pg_atomic_read_u32(&oldSnapshotControl->threshold_xid); SpinLockRelease(&oldSnapshotControl->mutex_threshold); if (ts == threshold_timestamp) diff --git a/src/include/utils/old_snapshot.h b/src/include/utils/old_snapshot.h index f1978a28e1c..3dd31d721c7 100644 --- a/src/include/utils/old_snapshot.h +++ b/src/include/utils/old_snapshot.h @@ -16,6 +16,7 @@ #define OLD_SNAPSHOT_H #include "datatype/timestamp.h" +#include "port/atomics.h" #include "storage/s_lock.h" /* @@ -33,8 +34,8 @@ typedef struct OldSnapshotControlData TransactionId latest_xmin; /* latest snapshot xmin */ TimestampTz next_map_update; /* latest snapshot valid up to */ slock_t mutex_threshold; /* protect threshold fields */ - TimestampTz threshold_timestamp; /* earlier snapshot is old */ - TransactionId threshold_xid; /* earlier xid may be gone */ + pg_atomic_uint64 threshold_timestamp; /* earlier snapshot is old */ + pg_atomic_uint32 threshold_xid; /* earlier xid may be gone */ /* * Keep one xid per minute for old snapshot error handling. -- 2.34.1