diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/transam/xlog.c | 57 | ||||
-rw-r--r-- | src/backend/replication/slotfuncs.c | 39 |
2 files changed, 62 insertions, 34 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 34ede80c44f..e455384b5b0 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -9488,15 +9488,20 @@ CreateRestartPoint(int flags) * (typically a slot's restart_lsn) * * Returns one of the following enum values: - * * WALAVAIL_NORMAL means targetLSN is available because it is in the range - * of max_wal_size. * - * * WALAVAIL_PRESERVED means it is still available by preserving extra + * * WALAVAIL_RESERVED means targetLSN is available and it is in the range of + * max_wal_size. + * + * * WALAVAIL_EXTENDED means it is still available by preserving extra * segments beyond max_wal_size. If max_slot_wal_keep_size is smaller * than max_wal_size, this state is not returned. * - * * WALAVAIL_REMOVED means it is definitely lost. A replication stream on - * a slot with this LSN cannot continue. + * * WALAVAIL_UNRESERVED means it is being lost and the next checkpoint will + * remove reserved segments. The walsender using this slot may return to the + * above. + * + * * WALAVAIL_REMOVED means it has been removed. A replication stream on + * a slot with this LSN cannot continue after a restart. * * * WALAVAIL_INVALID_LSN means the slot hasn't been set to reserve WAL. */ @@ -9512,13 +9517,18 @@ GetWALAvailability(XLogRecPtr targetLSN) * slot */ uint64 keepSegs; - /* slot does not reserve WAL. Either deactivated, or has never been active */ + /* + * slot does not reserve WAL. Either deactivated, or has never been active + */ if (XLogRecPtrIsInvalid(targetLSN)) return WALAVAIL_INVALID_LSN; currpos = GetXLogWriteRecPtr(); - /* calculate oldest segment currently needed by slots */ + /* + * calculate the oldest segment currently reserved by all slots, + * considering wal_keep_segments and max_slot_wal_keep_size + */ XLByteToSeg(targetLSN, targetSeg, wal_segment_size); KeepLogSeg(currpos, &oldestSlotSeg); @@ -9529,10 +9539,9 @@ GetWALAvailability(XLogRecPtr targetLSN) */ oldestSeg = XLogGetLastRemovedSegno() + 1; - /* calculate oldest segment by max_wal_size and wal_keep_segments */ + /* calculate oldest segment by max_wal_size */ XLByteToSeg(currpos, currSeg, wal_segment_size); - keepSegs = ConvertToXSegs(Max(max_wal_size_mb, wal_keep_segments), - wal_segment_size) + 1; + keepSegs = ConvertToXSegs(max_wal_size_mb, wal_segment_size) + 1; if (currSeg > keepSegs) oldestSegMaxWalSize = currSeg - keepSegs; @@ -9540,27 +9549,23 @@ GetWALAvailability(XLogRecPtr targetLSN) oldestSegMaxWalSize = 1; /* - * If max_slot_wal_keep_size has changed after the last call, the segment - * that would been kept by the current setting might have been lost by the - * previous setting. No point in showing normal or keeping status values - * if the targetSeg is known to be lost. + * No point in returning reserved or extended status values if the + * targetSeg is known to be lost. */ - if (targetSeg >= oldestSeg) + if (targetSeg >= oldestSlotSeg) { - /* - * show "normal" when targetSeg is within max_wal_size, even if - * max_slot_wal_keep_size is smaller than max_wal_size. - */ - if ((max_slot_wal_keep_size_mb <= 0 || - max_slot_wal_keep_size_mb >= max_wal_size_mb) && - oldestSegMaxWalSize <= targetSeg) - return WALAVAIL_NORMAL; - - /* being retained by slots */ - if (oldestSlotSeg <= targetSeg) + /* show "reserved" when targetSeg is within max_wal_size */ + if (targetSeg >= oldestSegMaxWalSize) return WALAVAIL_RESERVED; + + /* being retained by slots exceeding max_wal_size */ + return WALAVAIL_EXTENDED; } + /* WAL segments are no longer retained but haven't been removed yet */ + if (targetSeg >= oldestSeg) + return WALAVAIL_UNRESERVED; + /* Definitely lost */ return WALAVAIL_REMOVED; } diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 3fc54cb9bab..df854bc6e3f 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -359,24 +359,47 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) nulls[i++] = true; break; - case WALAVAIL_NORMAL: - values[i++] = CStringGetTextDatum("normal"); - break; - case WALAVAIL_RESERVED: values[i++] = CStringGetTextDatum("reserved"); break; + case WALAVAIL_EXTENDED: + values[i++] = CStringGetTextDatum("extended"); + break; + + case WALAVAIL_UNRESERVED: + values[i++] = CStringGetTextDatum("unreserved"); + break; + case WALAVAIL_REMOVED: + + /* + * If we read the restart_lsn long enough ago, maybe that file + * has been removed by now. However, the walsender could have + * moved forward enough that it jumped to another file after + * we looked. If checkpointer signalled the process to + * termination, then it's definitely lost; but if a process is + * still alive, then "unreserved" seems more appropriate. + */ + if (!XLogRecPtrIsInvalid(slot_contents.data.restart_lsn)) + { + int pid; + + SpinLockAcquire(&slot->mutex); + pid = slot->active_pid; + SpinLockRelease(&slot->mutex); + if (pid != 0) + { + values[i++] = CStringGetTextDatum("unreserved"); + break; + } + } values[i++] = CStringGetTextDatum("lost"); break; - - default: - elog(ERROR, "invalid walstate: %d", (int) walstate); } if (max_slot_wal_keep_size_mb >= 0 && - (walstate == WALAVAIL_NORMAL || walstate == WALAVAIL_RESERVED) && + (walstate == WALAVAIL_RESERVED || walstate == WALAVAIL_EXTENDED) && ((last_removed_seg = XLogGetLastRemovedSegno()) != 0)) { XLogRecPtr min_safe_lsn; |