From ff1715e22200f4a6f22486f9ce6b851b94e4899a Mon Sep 17 00:00:00 2001 From: Jingtang Zhang Date: Thu, 23 Jul 2026 00:13:23 +0800 Subject: [PATCH] vacuum: stop using stream ring after failsafe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure future heap reads stop using VACUUM’s buffer access strategy after wraparound failsafe activates, including when it activates during a round of index vacuuming. --- src/backend/access/heap/vacuumlazy.c | 7 +++++++ src/backend/storage/aio/read_stream.c | 21 +++++++++++++++++++-- src/include/storage/read_stream.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 39395aed0d5..9651b19b39a 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1385,6 +1385,13 @@ lazy_scan_heap(LVRelState *vacrel) PROGRESS_VACUUM_PHASE_SCAN_HEAP); } + /* + * Switch the stream's strategy after any check, including one that + * might have happened in lazy_vacuum(). + */ + if (VacuumFailsafeActive) + read_stream_set_strategy(stream, NULL); + buf = read_stream_next_buffer(stream, &per_buffer_data); /* The relation is exhausted. */ diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c index a318539e56c..93e5227cb70 100644 --- a/src/backend/storage/aio/read_stream.c +++ b/src/backend/storage/aio/read_stream.c @@ -123,6 +123,7 @@ struct ReadStream bool batch_mode; /* READ_STREAM_USE_BATCHING */ bool advice_enabled; bool temporary; + BufferAccessStrategy strategy; /* scan stats counters */ IOStats *stats; @@ -441,6 +442,7 @@ read_stream_start_pending_read(ReadStream *stream) while (stream->initialized_buffers < buffer_index + nblocks) stream->buffers[stream->initialized_buffers++] = InvalidBuffer; requested_nblocks = nblocks; + stream->ios[io_index].op.strategy = stream->strategy; need_wait = StartReadBuffers(&stream->ios[io_index].op, &stream->buffers[buffer_index], stream->pending_read_blocknum, @@ -931,6 +933,7 @@ read_stream_begin_impl(int flags, stream->seq_blocknum = InvalidBlockNumber; stream->seq_until_processed = InvalidBlockNumber; stream->temporary = SmgrIsTemp(smgr); + stream->strategy = strategy; stream->distance_decay_holdoff = 0; /* @@ -962,7 +965,6 @@ read_stream_begin_impl(int flags, stream->ios[i].op.smgr = smgr; stream->ios[i].op.persistence = persistence; stream->ios[i].op.forknum = forknum; - stream->ios[i].op.strategy = strategy; } return stream; @@ -1098,6 +1100,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) * held at the same time, the model used here is that the stream * holds only one, and the other now belongs to the caller. */ + stream->ios[0].op.strategy = stream->strategy; if (likely(!StartReadBuffer(&stream->ios[0].op, &stream->buffers[oldest_buffer_index], next_blocknum, @@ -1376,10 +1379,24 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) BlockNumber read_stream_next_block(ReadStream *stream, BufferAccessStrategy *strategy) { - *strategy = stream->ios[0].op.strategy; + *strategy = stream->strategy; return read_stream_get_block(stream, NULL); } +/* + * Change the buffer access strategy used for future reads. + * + * I/O operations may be in progress, so their ReadBuffersOperation must not + * be modified here. The new strategy is installed when an idle operation is + * reused to start another read. The pinned-buffer limit and queue capacity + * are fixed when the stream is created. + */ +void +read_stream_set_strategy(ReadStream *stream, BufferAccessStrategy strategy) +{ + stream->strategy = strategy; +} + /* * Temporarily stop consuming block numbers from the block number callback. * If called inside the block number callback, its return value should be diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h index 48995c6d534..6d43bfab3f8 100644 --- a/src/include/storage/read_stream.h +++ b/src/include/storage/read_stream.h @@ -100,6 +100,8 @@ extern ReadStream *read_stream_begin_smgr_relation(int flags, ReadStreamBlockNumberCB callback, void *callback_private_data, size_t per_buffer_data_size); +extern void read_stream_set_strategy(ReadStream *stream, + BufferAccessStrategy strategy); extern BlockNumber read_stream_pause(ReadStream *stream); extern void read_stream_resume(ReadStream *stream); extern void read_stream_reset(ReadStream *stream); -- 2.50.1 (Apple Git-155)