Re: min_safe_lsn column in pg_replication_slots view - Mailing list pgsql-hackers
From | Kyotaro Horiguchi |
---|---|
Subject | Re: min_safe_lsn column in pg_replication_slots view |
Date | |
Msg-id | 20200615.163522.467860634263779015.horikyota.ntt@gmail.com Whole thread Raw |
In response to | Re: min_safe_lsn column in pg_replication_slots view (Michael Paquier <michael@paquier.xyz>) |
Responses |
Re: min_safe_lsn column in pg_replication_slots view
|
List | pgsql-hackers |
At Mon, 15 Jun 2020 13:44:31 +0900, Michael Paquier <michael@paquier.xyz> wrote in > On Mon, Jun 15, 2020 at 12:40:03PM +0900, Fujii Masao wrote: > > BTW, I just wonder why each row in pg_replication_slots needs to have > > min_safe_lsn column? Basically min_safe_lsn should be the same between > > every replication slots. > > Indeed, that's confusing in its current shape. I would buy putting > this value into pg_replication_slots if there were some consistency of > the data to worry about because of locking issues, but here this data > is controlled within info_lck, which is out of the the repslot LW > lock. So I think that it is incorrect to put this data in this view > and that we should remove it, and that instead we had better push for > a system view that maps with the contents of XLogCtl. It was once the difference from the safe_lsn to restart_lsn which is distinct among slots. Then it was changed to the safe_lsn. I agree to the discussion above, but it is needed anywhere since no one can know the margin until the slot goes to the "lost" state without it. (Note that currently even wal_status and min_safe_lsn can be inconsistent in a line.) Just for the need for table-consistency and in-line consistency, we could just remember the result of XLogGetLastRemovedSegno() around taking info_lock in the function. That doesn't make a practical difference but makes the view look consistent. regards. -- Kyotaro Horiguchi NTT Open Source Software Center diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index d6fe205eb4..f57d67a900 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -9498,7 +9498,7 @@ CreateRestartPoint(int flags) * * WALAVAIL_INVALID_LSN means the slot hasn't been set to reserve WAL. */ WALAvailability -GetWALAvailability(XLogRecPtr targetLSN) +GetWALAvailability(XLogRecPtr targetLSN, XLogSegNo last_removed_seg) { XLogRecPtr currpos; /* current write LSN */ XLogSegNo currSeg; /* segid of currpos */ @@ -9524,7 +9524,7 @@ GetWALAvailability(XLogRecPtr targetLSN) * the first WAL segment file since startup, which causes the status being * wrong under certain abnormal conditions but that doesn't actually harm. */ - oldestSeg = XLogGetLastRemovedSegno() + 1; + oldestSeg = last_removed_seg + 1; /* calculate oldest segment by max_wal_size and wal_keep_segments */ XLByteToSeg(currpos, currSeg, wal_segment_size); diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 1b929a603e..bd2e3e84ed 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -243,6 +243,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) MemoryContext per_query_ctx; MemoryContext oldcontext; int slotno; + XLogSegNo last_removed_seg; /* check to see if caller supports us returning a tuplestore */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) @@ -272,6 +273,14 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) rsinfo->setResult = tupstore; rsinfo->setDesc = tupdesc; + /* + * Remember the last removed segment at this point for the consistency in + * this table. Since there's no interlock between slot data and + * checkpointer, the segment can be removed in-between, but that doesn't + * make any practical difference. + */ + last_removed_seg = XLogGetLastRemovedSegno(); + MemoryContextSwitchTo(oldcontext); LWLockAcquire(ReplicationSlotControlLock, LW_SHARED); @@ -282,7 +291,6 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) Datum values[PG_GET_REPLICATION_SLOTS_COLS]; bool nulls[PG_GET_REPLICATION_SLOTS_COLS]; WALAvailability walstate; - XLogSegNo last_removed_seg; int i; if (!slot->in_use) @@ -342,7 +350,8 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) else nulls[i++] = true; - walstate = GetWALAvailability(slot_contents.data.restart_lsn); + walstate = GetWALAvailability(slot_contents.data.restart_lsn, + last_removed_seg); switch (walstate) { @@ -368,7 +377,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) if (max_slot_wal_keep_size_mb >= 0 && (walstate == WALAVAIL_NORMAL || walstate == WALAVAIL_RESERVED) && - ((last_removed_seg = XLogGetLastRemovedSegno()) != 0)) + (last_removed_seg != 0)) { XLogRecPtr min_safe_lsn; diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index e917dfe92d..c05a18148d 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -326,7 +326,8 @@ extern void ShutdownXLOG(int code, Datum arg); extern void InitXLOGAccess(void); extern void CreateCheckPoint(int flags); extern bool CreateRestartPoint(int flags); -extern WALAvailability GetWALAvailability(XLogRecPtr restart_lsn); +extern WALAvailability GetWALAvailability(XLogRecPtr targetLSN, + XLogSegNo last_removed_seg); extern XLogRecPtr CalculateMaxmumSafeLSN(void); extern void XLogPutNextOid(Oid nextOid); extern XLogRecPtr XLogRestorePoint(const char *rpName);
pgsql-hackers by date: