Re: Track Oldest Initialized WAL Buffer Page - Mailing list pgsql-hackers
From | Bharath Rupireddy |
---|---|
Subject | Re: Track Oldest Initialized WAL Buffer Page |
Date | |
Msg-id | CALj2ACVFSirOFiABrNVAA6JtPHvA9iu+wp=qkM9pdLZ5mwLaFg@mail.gmail.com Whole thread Raw |
In response to | Re: Track Oldest Initialized WAL Buffer Page (Heikki Linnakangas <hlinnaka@iki.fi>) |
List | pgsql-hackers |
On Mon, Jul 3, 2023 at 6:57 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote: > Thanks a lot for responding. Sorry for being late. > On 07/02/2023 16:00, Bharath Rupireddy wrote: > > Hi, > > > > While working on [1], I was looking for a quick way to tell if a WAL > > record is present in the WAL buffers array without scanning but I > > couldn't find one. > > /* The end-ptr of the page that contains the record */ > expectedEndPtr += XLOG_BLCKSZ - recptr % XLOG_BLCKSZ; > > /* get the buffer where the record is, if it's in WAL buffers at all */ > idx = XLogRecPtrToBufIdx(recptr); > > /* prevent the WAL buffer from being evicted while we look at it */ > LWLockAcquire(WALBufMappingLock, LW_SHARED); > > /* Check if the page we're interested in is in the buffer */ > found = XLogCtl->xlblocks[idx] == expectedEndPtr; > > LWLockRelease(WALBufMappingLock, LW_SHARED); This is exactly what I'm doing in the 0001 patch here https://www.postgresql.org/message-id/CALj2ACU3ZYzjOv4vZTR+LFk5PL4ndUnbLS6E1vG2dhDBjQGy2A@mail.gmail.com. My bad! I should have mentioned the requirement properly - I want to avoid taking WALBufMappingLock to peek into wal_buffers to determine if the WAL buffer page containing the required WAL record exists. > You actually hint at the above solution here, so I'm confused. If you're > OK with slightly stale results, you can skip the WALBufferMappingLock > above too, and perform an atomic read of xlblocks[idx] instead. I get that and I see GetXLogBuffer first reading xlblocks without lock and then to confirm it anyways takes the lock again in AdvanceXLInsertBuffer. * However, we don't hold a lock while we read the value. If someone has * just initialized the page, it's possible that we get a "torn read" of * the XLogRecPtr if 64-bit fetches are not atomic on this platform. In * that case we will see a bogus value. That's ok, we'll grab the mapping * lock (in AdvanceXLInsertBuffer) and retry if we see anything else than * the page we're looking for. But it means that when we do this unlocked * read, we might see a value that appears to be ahead of the page we're * looking for. Don't PANIC on that, until we've verified the value while * holding the lock. */ The the 0001 patch at https://www.postgresql.org/message-id/CALj2ACU3ZYzjOv4vZTR+LFk5PL4ndUnbLS6E1vG2dhDBjQGy2A@mail.gmail.com reads the WAL buffer page with WALBufMappingLock. So, the patch can avoid WALBufMappingLock and do something like [1]: [1] { idx = XLogRecPtrToBufIdx(ptr); expectedEndPtr = ptr; expectedEndPtr += XLOG_BLCKSZ - ptr % XLOG_BLCKSZ; /* * Do a stale read of xlblocks without WALBufMappingLock. All the callers * of this function are expected to read WAL that's already flushed to disk * from WAL buffers. If this stale read says the requested WAL buffer page * doesn't exist, it means that the WAL buffer page either is being or has * already been replaced for reuse. If this stale read says the requested * WAL buffer page exists, we then take WALBufMappingLock and re-read the * xlblocks to ensure the WAL buffer page really exists and nobody is * replacing it meanwhile. */ endptr = XLogCtl->xlblocks[idx]; /* Requested WAL isn't available in WAL buffers. */ if (expectedEndPtr != endptr) break; /* * Requested WAL is available in WAL buffers, so recheck the existence * under the WALBufMappingLock and read if the page still exists, otherwise * return. */ LWLockAcquire(WALBufMappingLock, LW_SHARED); endptr = XLogCtl->xlblocks[idx]; /* Requested WAL isn't available in WAL buffers. */ if (expectedEndPtr != endptr) break; /* * We found the WAL buffer page containing the given XLogRecPtr. Get starting * address of the page and a pointer to the right location given * XLogRecPtr in that page. */ page = XLogCtl->pages + idx * (Size) XLOG_BLCKSZ; data = page + ptr % XLOG_BLCKSZ; return data; } -- Bharath Rupireddy PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
pgsql-hackers by date: