From 6bdd3566e9252c4296b0c663786eba6e5bf95c12 Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Wed, 11 Jan 2023 18:07:10 +0300 Subject: [PATCH v2] 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. --- src/backend/utils/time/snapmgr.c | 36 +++++++++++++++----------------- src/include/utils/old_snapshot.h | 6 +++--- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 7d11ae34781..77f32ae468f 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -229,9 +229,8 @@ SnapMgrInit(void) SpinLockInit(&oldSnapshotControl->mutex_latest_xmin); 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 +1705,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,12 +1713,17 @@ GetOldSnapshotThresholdTimestamp(void) void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit) { - SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - Assert(oldSnapshotControl->threshold_timestamp <= ts); - Assert(TransactionIdPrecedesOrEquals(oldSnapshotControl->threshold_xid, xlimit)); - oldSnapshotControl->threshold_timestamp = ts; - oldSnapshotControl->threshold_xid = xlimit; - SpinLockRelease(&oldSnapshotControl->mutex_threshold); + TimestampTz threshold_timestamp; + TransactionId threshold_xid; + + 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); } /* @@ -1739,9 +1741,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); } /* @@ -1845,10 +1845,8 @@ TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, - (old_snapshot_threshold * USECS_PER_MINUTE); /* Check for fast exit without LW locking. */ - SpinLockAcquire(&oldSnapshotControl->mutex_threshold); - threshold_timestamp = oldSnapshotControl->threshold_timestamp; - threshold_xid = oldSnapshotControl->threshold_xid; - SpinLockRelease(&oldSnapshotControl->mutex_threshold); + threshold_timestamp = pg_atomic_read_u64(&oldSnapshotControl->threshold_timestamp); + threshold_xid = pg_atomic_read_u32(&oldSnapshotControl->threshold_xid); if (ts == threshold_timestamp) { diff --git a/src/include/utils/old_snapshot.h b/src/include/utils/old_snapshot.h index f1978a28e1c..979189a143f 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" /* @@ -32,9 +33,8 @@ typedef struct OldSnapshotControlData slock_t mutex_latest_xmin; /* protect latest_xmin and next_map_update */ 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.38.1