Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qGJae-0001oW-G3 for pgsql-hackers@arkaria.postgresql.org; Mon, 03 Jul 2023 13:27:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1qGJad-0003z0-C0 for pgsql-hackers@arkaria.postgresql.org; Mon, 03 Jul 2023 13:27:39 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qGJac-0003ub-VU for pgsql-hackers@lists.postgresql.org; Mon, 03 Jul 2023 13:27:39 +0000 Received: from meesny.iki.fi ([2001:67c:2b0:1c1::201]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qGJaW-001o5s-Qs for pgsql-hackers@lists.postgresql.org; Mon, 03 Jul 2023 13:27:37 +0000 Received: from [192.168.1.115] (dsl-hkibng22-54f8db-125.dhcp.inet.fi [84.248.219.125]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hlinnaka) by meesny.iki.fi (Postfix) with ESMTPSA id 4Qvmtl5j0dzybb; Mon, 3 Jul 2023 16:27:27 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1688390848; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NJj/iNSgfZIx2VPMbgmByIJglS8XHxjJKJZMwqx6sSY=; b=lUdFO1TrEm8DomkLfBSiR+Oeg12PsDSLuWpR+HqaX8oQU7bTEbG8STVKAbXHtf+NGPuA/8 hi0FQQU4eity8id4Y5WIqD/Vjo8gLLXs5o/8M//d9q1jRZQazGYsXKT/KWdzVm9UN5gEO9 AwcU7TR8F7MHPhnggFrl0pveZLFth1E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1688390848; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NJj/iNSgfZIx2VPMbgmByIJglS8XHxjJKJZMwqx6sSY=; b=ly7nP42bud13K9y+wV9pYFe/rbqQFj6ZD7gc6o9jPiK0tkTU2pFEXJ7qbQSrITbMr0yNDp CiDNn5g51TDn3ywyaLLRvwrjN4iKpb4ok8N6hP4wH1CPfFqBheBJwTxu5lT+/z5u0Qgl6E R+h8ItAfV46wlr0nmzJ4ZzxGXg/0XsU= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=hlinnaka smtp.mailfrom=hlinnaka@iki.fi ARC-Seal: i=1; s=meesny; d=iki.fi; t=1688390848; a=rsa-sha256; cv=none; b=SSAeWZoMgHaWK2p83WJ6fHi26J0lIhSGQMJjSKta/pCpmY8lFthLvEZd/PMVk35Rjo/7sq qY775wLQzrt6+JiR+wD5k2PaG0YchuRv/usKW4Z/3g3GvOFBTXjgYXDVhVzTEJsYa8LZQG 7L2saese/c3/ULFm+z4D7SKp2Y2d0a0= Message-ID: <82dad3ca-035c-c5f3-d230-ff7d11b6e573@iki.fi> Date: Mon, 3 Jul 2023 16:27:27 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.12.0 Subject: Re: Track Oldest Initialized WAL Buffer Page Content-Language: en-US To: Bharath Rupireddy , PostgreSQL Hackers , Nathan Bossart References: From: Heikki Linnakangas In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk 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); > Hence, I put up a patch that basically tracks the > oldest initialized WAL buffer page, named OldestInitializedPage, in > XLogCtl. With OldestInitializedPage, we can easily illustrate WAL > buffers array properties: > > 1) At any given point of time, pages in the WAL buffers array are > sorted in an ascending order from OldestInitializedPage till > InitializedUpTo. Note that we verify this property for assert-only > builds, see IsXLogBuffersArraySorted() in the patch for more details. > > 2) OldestInitializedPage is monotonically increasing (by virtue of how > postgres generates WAL records), that is, its value never decreases. > This property lets someone read its value without a lock. There's no > problem even if its value is slightly stale i.e. concurrently being > updated. One can still use it for finding if a given WAL record is > available in WAL buffers. At worst, one might get false positives > (i.e. OldestInitializedPage may tell that the WAL record is available > in WAL buffers, but when one actually looks at it, it isn't really > available). This is more efficient and performant than acquiring a > lock for reading. Note that we may not need a lock to read > OldestInitializedPage but we need to update it holding > WALBufMappingLock. 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. > 3) One can start traversing WAL buffers from OldestInitializedPage > till InitializedUpTo to list out all valid WAL records and stats, and > expose them via SQL-callable functions to users, for instance, as > pg_walinspect functions. > > 4) WAL buffers array is inherently organized as a circular, sorted and > rotated array with OldestInitializedPage as pivot/first element of the > array with the property where LSN of previous buffer page (if valid) > is greater than OldestInitializedPage and LSN of the next buffer page > (if > valid) is greater than OldestInitializedPage. These properties are true, maybe we should document them explicitly in a comment. But I don't see the point of tracking OldestInitializedPage. It seems cheap enough that we could, if there's a need for it, but I don't see the need. -- Heikki Linnakangas Neon (https://neon.tech)