Re: Buffer locking is special (hints, checksums, AIO writes)
Andres Freund <andres@anarazel.de>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Require share-exclusive lock to set hint bits and to flush
- 82467f627bd4 19 (unreleased) landed
-
lwlock: Remove ForEachLWLockHeldByMe
- 55fbfb738b00 19 (unreleased) landed
-
bufmgr: Implement buffer content locks independently of lwlocks
- fcb9c977aa5f 19 (unreleased) landed
-
bufmgr: Change BufferDesc.state to be a 64-bit atomic
- dac328c8a682 19 (unreleased) landed
-
heapam: Add batch mode mvcc check and use it in page mode
- 0b96e734c590 19 (unreleased) landed
-
freespace: Don't modify page without any lock
- 45f658dacb9c 19 (unreleased) landed
-
heapam: Move logic to handle HEAP_MOVED into a helper function
- 548de59d93d5 19 (unreleased) landed
-
bufmgr: Optimize & harmonize LockBufHdr(), LWLockWaitListLock()
- 09ae2c8bac8d 19 (unreleased) landed
-
bufmgr: Add one-entry cache for private refcount
- 30df61990c67 19 (unreleased) landed
-
bufmgr: Separate keys for private refcount infrastructure
- edbaaea0a95e 19 (unreleased) landed
-
Add pg_atomic_unlocked_write_u64
- 7902a47c20b1 19 (unreleased) landed
-
Rename BUFFERPIN wait event class to BUFFER
- 6c5c393b7403 19 (unreleased) landed
-
bufmgr: Turn BUFFER_LOCK_* into an enum
- 156680055dc5 19 (unreleased) landed
-
lwlock: Fix, currently harmless, bug in LWLockWakeup()
- 81f773895321 19 (unreleased) landed
- da3971496531 15.16 landed
- 89c8a1b9069f 16.12 landed
- 427e886a79a5 17.8 landed
- 332693e75969 14.21 landed
- 8082b759d9b5 18.2 landed
-
bufmgr: Use atomic sub for unpinning buffers
- 5310fac6e0fc 19 (unreleased) landed
-
bufmgr: Allow some buffer state modifications while holding header lock
- c75ebc657ffc 19 (unreleased) landed
-
bufmgr: Fix valgrind checking for buffers pinned in StrategyGetBuffer()
- c819d1017ddb 19 (unreleased) landed
-
bufmgr: Don't lock buffer header in StrategyGetBuffer()
- 5e8998592879 19 (unreleased) landed
-
bufmgr: fewer calls to BufferDescriptorGetContentLock
- 3baae90013df 19 (unreleased) landed
-
bufmgr: Fix signedness of mask variable in BufferSync()
- 2a2e1b470b9b 19 (unreleased) landed
-
bufmgr: Introduce FlushUnlockedBuffer
- 3c2b97b29ee3 19 (unreleased) landed
-
Improve ReadRecentBuffer() scalability
- 819dc118c0f6 19 (unreleased) landed
Hi,
On 2025-08-27 12:14:41 -0700, Noah Misch wrote:
> On Wed, Aug 27, 2025 at 12:18:27PM -0400, Andres Freund wrote:
> > One way to do that would be to maintain a back-pointer from the BufferDesc to
> > the BufferLookupEnt, since the latter *already* contains the BufferTag. We
> > probably don't want to add another indirection to the buffer mapping hash
> > table, otherwise we could deduplicate the other way round and just put padding
> > between the modified and read-only part of a buffer desc.
>
> I think you're saying clients would save the back-pointer once and dereference
> it many times, with each dereference of a saved back-pointer avoiding a shmem
> read of BufferDesc.tag. Is that right?
I was thinking that we'd not have BufferDesc.tag, instead just storing it
solely in BufferLookupEnt. To get the tag of a BufferDesc, you'd every time
have to follow the back-reference. But that's actually why it doesn't work -
reading the back-reference pointer would have the same issue as just reading
BufferDesc.tag...
> > > On Tue, Aug 26, 2025 at 05:00:13PM -0400, Andres Freund wrote:
> > > > On 2025-08-26 16:21:36 -0400, Robert Haas wrote:
> > > > > On Fri, Aug 22, 2025 at 3:45 PM Andres Freund <andres@anarazel.de> wrote:
> > > > > > DOES ANYBODY HAVE A BETTER NAME THAN SHARE-EXCLUSIVE???!?
> >
> > > I would consider {AccessShare, Exclusive, AccessExclusive}.
> >
> > One thing I forgot to mention is that with the proposed re-architecture in
> > place, we could subsequently go further and make pinning just be a very
> > lightweight lock level, instead of that being a separate dedicated
> > infrstructure. One nice outgrowth of that would be that that acquiring a
> > cleanup lock would just be a real lock acquisition, instead of the dedicated
> > limited machinery we have right now.
> >
> > Which would leave us with:
> > - reference (pins today)
> > - share
> > - share-exclusive
> > - exclusive
> > - cleanup
> >
> > This doesn't quite seem to map onto the heavyweight lock levels in a sensible
> > way...
>
> Could map it like this:
>
> AccessShare - pins today
> RowShare - check tuple visibility (BUFFER_LOCK_SHARE today)
> Share - set hint bits
> ShareUpdateExclusive - clean/write out (borrowing Robert's idea)
> Exclusive - add tuples, change xmax, etc. (BUFFER_LOCK_EXCLUSIVE today)
> AccessExclusive - cleanup lock or evict the buffer
I tend think having things like RowShare for buffer locking is confusing
enough to actually make the similarity to the heavyweight locks to not be a
win...
> That has a separate level for hint bits vs. I/O, so multiple backends could
> set hint bits. I don't know whether the benchmarks would favor maintaining
> that distinction.
I don't think it would - I actually found multiple backends setting the same
hint bits to *hurt* performance a bit. But what's more important, we don't
have the space for it, I think. Every lock that can be acquired multiple
times needs a lock count of 18 bits. And we need to store the buffer state
flags (10 bits). There's just not enough space in 64bit to have three 18bit
counters as well as flag bits etc.
> Compared to share-exclusive, I think I'd prefer a name that describes the use
> cases, "set-hints-or-write" (or separate "write" and "set-hints" levels).
I would too, I just couldn't come up with something that conveys the meanings
in a sufficiently concise way :)
> What do you think of that? I don't know whether that should win vs. names
> like ShareUpdateExclusive, though.
I think it'd be a win compared to the heavyweight lock names...
Greetings,
Andres Freund