Hello, On 2024-Apr-03, Alexander Lakhin wrote:
> I've managed to trigger an assert added by 53c2a97a9. > Please try the following script against a server compiled with > -DTEST_SUMMARIZE_SERIAL (initially I observed this failure without the > define, it just simplifies reproducing...): Ah yes, absolutely, we're missing to trade the correct SLRU bank lock there. This rewrite of that small piece should fix it. Thanks for reporting this. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "Pido que me den el Nobel por razones humanitarias" (Nicanor Parra)
>From 44c39cf4bf258fb0b65aa1acc5f84e5d7f729eb1 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera <alvhe...@alvh.no-ip.org> Date: Wed, 3 Apr 2024 16:00:24 +0200 Subject: [PATCH] Fix zeroing of pg_serial page without SLRU bank lock --- src/backend/storage/lmgr/predicate.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 3f378c0099..d5bbfbd4c6 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -137,7 +137,7 @@ * SerialControlLock * - Protects SerialControlData members * - * SerialSLRULock + * SLRU per-bank locks * - Protects SerialSlruCtl * * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group @@ -908,20 +908,25 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) if (isNewPage) serialControl->headPage = targetPage; - LWLockAcquire(lock, LW_EXCLUSIVE); - if (isNewPage) { - /* Initialize intervening pages. */ - while (firstZeroPage != targetPage) + /* Initialize intervening pages; might involve trading locks */ + for (;;) { - (void) SimpleLruZeroPage(SerialSlruCtl, firstZeroPage); + lock = SimpleLruGetBankLock(SerialSlruCtl, firstZeroPage); + LWLockAcquire(lock, LW_EXCLUSIVE); + slotno = SimpleLruZeroPage(SerialSlruCtl, firstZeroPage); + if (firstZeroPage == targetPage) + break; firstZeroPage = SerialNextPage(firstZeroPage); + LWLockRelease(lock); } - slotno = SimpleLruZeroPage(SerialSlruCtl, targetPage); } else + { + LWLockAcquire(lock, LW_EXCLUSIVE); slotno = SimpleLruReadPage(SerialSlruCtl, targetPage, true, xid); + } SerialValue(slotno, xid) = minConflictCommitSeqNo; SerialSlruCtl->shared->page_dirty[slotno] = true; -- 2.39.2