Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rZwPR-007GBi-Du for pgsql-hackers@arkaria.postgresql.org; Tue, 13 Feb 2024 17:17:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rZwPP-001BhD-FM for pgsql-hackers@arkaria.postgresql.org; Tue, 13 Feb 2024 17:17:27 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rZwPP-001Bh2-5n for pgsql-hackers@lists.postgresql.org; Tue, 13 Feb 2024 17:17:27 +0000 Received: from mail-lj1-x231.google.com ([2a00:1450:4864:20::231]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rZwPI-006ZbU-1c for pgsql-hackers@lists.postgresql.org; Tue, 13 Feb 2024 17:17:25 +0000 Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2d090c83d45so60951031fa.3 for ; Tue, 13 Feb 2024 09:17:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707844638; x=1708449438; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=iXMxjVwlso4p3os/ZRRGvVzZ2PugqogLLkM2PgIeTL4=; b=ArCN4pdjHHIwOjDaqv2PtpRyBUMdVTotR5UvwPhIgxatII1VuGE4EOlsXTpyD6cz03 5NPJNSjNQOkz2fmHDE+KiHsMiQxnQ73LdAx7KHC6o7+XtpUNOl0RsuaSWpKa4QZT4cHR GCZh01dnp/NthbdgMc6iCs65qrZ2D9qf6epbT7lpYGR51GyKAZylHgbkBXzw8b60TsEU OA/gF72A1eqebUkg5vfWfBYFM/ko8hO0ZvWXyPZrhFCpodUW/2asTdXhPNjE9Vx9k5dv 4iwNCC2VH7Qa/99Roxf1FsvQIRj0m7e1wq0oKjfx4VO6T8u2tpfrz3uvmF88LnVWf8V4 6zwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707844638; x=1708449438; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iXMxjVwlso4p3os/ZRRGvVzZ2PugqogLLkM2PgIeTL4=; b=TPGU3t5fQ4HFY0eK9egilx3wtrz1RcyraogMW1i+awqGKIQhRzftR5QXTc3vMdX3D/ /NfhPJx8IMOmZDLketWgfRL3uGcmLXvgc7Hkz7khmFN8wVZtu4D+X8LvbC9FnfpmS8Y3 n2i25TgNDomHnsajHx5u4dDkprnfMyEPGDG/ay1o857gYsqB+CnPM2xC/QDt5XJRWxov EkwAPjlX9PhfHVk4mRaTfcH4JTJYKGqIsO0KNqsf65TOGG4CklnIrzLuKycMumdRLwWK WY2/W/iQwbpDnW+iK0FsQYBEOIjeKwbPtEAKqvsYTJ6HHN8L6xqeBn5gWxoHy3OuG4Jt sFSA== X-Gm-Message-State: AOJu0Yw8rHYykc/n4j/u3FeB4Kmm+LsQ4KyxGjpXTIobdvROmR38eXG6 DqBbjThgybLxNMpMxiyrd/a3OU+MrKAM5+cpLBpV183kxfBf16YAZ9DG/jZU505zfx2gki2+d4P ihiUAwkpYu6AdMfCFPjD73GpLBQA= X-Google-Smtp-Source: AGHT+IGsP8fZhdAw2j4yxMEndmyXphvAg2K5oZbmPlX5RAjqsgVQocuSuXAgdaWeeu+1W4kFr1oGCg2TQM7+60E9cAo= X-Received: by 2002:a05:651c:1406:b0:2d0:f46f:75e9 with SMTP id u6-20020a05651c140600b002d0f46f75e9mr187594lje.19.1707844638088; Tue, 13 Feb 2024 09:17:18 -0800 (PST) MIME-Version: 1.0 References: <202401301731.o3cthlcry4ve@alvherre.pgsql> <20240212201853.r6dl25onohrwagxt@awork3.anarazel.de> <20240212233648.4ephivkh7ukkiv2k@awork3.anarazel.de> In-Reply-To: <20240212233648.4ephivkh7ukkiv2k@awork3.anarazel.de> From: Bharath Rupireddy Date: Tue, 13 Feb 2024 22:47:06 +0530 Message-ID: Subject: Re: Improve WALRead() to suck data directly from WAL buffers when possible To: Andres Freund Cc: Jeff Davis , Alvaro Herrera , Dilip Kumar , Kyotaro Horiguchi , pgsql-hackers@lists.postgresql.org, Nathan Bossart , Masahiko Sawada Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Feb 13, 2024 at 5:06=E2=80=AFAM Andres Freund = wrote: > > I doubt there's a sane way to use WALRead() without *first* ensuring that= the > range of data is valid. I think we're better of moving that responsibilit= y > explicitly to the caller and adding an assertion verifying that. > > It doesn't really seem like a necessary, or even particularly useful, > part. You couldn't just call WALRead() for that, since the caller would n= eed > to know the range up to which WAL is valid but not yet flushed as well. T= hus > the caller would need to first use WaitXLogInsertionsToFinish() or someth= ing > like it anyway - and then there's no point in doing the WALRead() anymore= . > > Note that for replicating unflushed data, we *still* might need to fall b= ack > to reading WAL data from disk. In which case not asserting in WALRead() w= ould > just make it hard to find bugs, because not using WaitXLogInsertionsToFin= ish() > would appear to work as long as data is in wal buffers, but as soon as we= 'd > fall back to on-disk (but unflushed) data, we'd send bogus WAL. Callers of WALRead() do a good amount of work to figure out what's been flushed out but they read the un-flushed and/or invalid data see the comment [1] around WALRead() call sites as well as a recent thread [2] for more details. IIUC, here's the summary of the discussion that has happened so far: a) If only replicating flushed data, then ensure all the WALRead() callers read how much ever is valid out of startptr+count. Fix provided in [2] can help do that. b) If only replicating flushed data, then ensure all the WALReadFromBuffers() callers read how much ever is valid out of startptr+count. Current and expected WALReadFromBuffers() callers will anyway determine how much of it is flushed and can validly be read. c) If planning to replicate unflushed data, then ensure all the WALRead() callers wait until startptr+count is past the current insert position with WaitXLogInsertionsToFinish(). d) If planning to replicate unflushed data, then ensure all the WALReadFromBuffers() callers wait until startptr+count is past the current insert position with WaitXLogInsertionsToFinish(). Adding an assertion or error in WALReadFromBuffers() for ensuring the callers do follow the above set of rules is easy. We can just do Assert(startptr+count <=3D LogwrtResult.Flush). However, adding a similar assertion or error in WALRead() gets trickier as it's being called from many places - walsenders, backends, external tools etc. even when the server is in recovery. Therefore, determining the actual valid LSN is a bit of a challenge. What I think is the best way: - Try and get the fix provided for (a) at [2]. - Implement both (c) and (d). - Have the assertion in WALReadFromBuffers() ensuring the callers wait until startptr+count is past the current insert position with WaitXLogInsertionsToFinish(). - Have a comment around WALRead() to ensure the callers are requesting the WAL that's written to the disk because it's hard to determine what's written to disk as this gets called in many scenarios - when server is in recovery, for walsummarizer etc. - In the new test module, demonstrate how one can implement reading unflushed data with WALReadFromBuffers() and/or WALRead() + WaitXLogInsertionsToFinish(). Thoughts? [1] /* * Even though we just determined how much of the page can be validly read * as 'count', read the whole page anyway. It's guaranteed to be * zero-padded up to the page boundary if it's incomplete. */ if (!WALRead(state, cur_page, targetPagePtr, XLOG_BLCKSZ, tli, &errinfo)) [2] https://www.postgresql.org/message-id/CALj2ACWBRFac2TingD3PE3w2EBHXUHY3= %3DAEEZPJmqhpEOBGExg%40mail.gmail.com -- Bharath Rupireddy PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com