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 1uHMyr-000zMQ-AJ for pgsql-hackers@arkaria.postgresql.org; Tue, 20 May 2025 13:26:05 +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 1uHMyq-006l5v-BF for pgsql-hackers@arkaria.postgresql.org; Tue, 20 May 2025 13:26:04 +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 1uHMyp-006l5n-TM for pgsql-hackers@lists.postgresql.org; Tue, 20 May 2025 13:26:04 +0000 Received: from mail-pj1-x102f.google.com ([2607:f8b0:4864:20::102f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uHMyn-002l73-01 for pgsql-hackers@postgresql.org; Tue, 20 May 2025 13:26:03 +0000 Received: by mail-pj1-x102f.google.com with SMTP id 98e67ed59e1d1-30f0d8628c8so1471709a91.0 for ; Tue, 20 May 2025 06:26:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747747561; x=1748352361; darn=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=FmHBtZpsBIrWTXN1EzO1pSICL4Jn5YL6ChmiYp7rEAE=; b=bZHWw2De3fhwRZVJsNt0C/GztHF3jBDgFCsXjRwf6dEZ2ubARpux75gGQGzSSR2aMG Y/Q287blpi1HYvEb41Ilb+Gls1z0VbY9XtueJbrD/4nQHD3ggAqVolKZtFLuts2BAlu1 YRH5tgP8C8Pj9iw4zzNvAjRYhtP2pzRI8ApAvcYXDCwETbBX4UzJg/qARTKObOOAY/o3 sfTVbRDkgojkaYBbf4Z+kWGDooN3yf3aTw8lWmuwmcQrY4/prBSy3xuP7Sy2rNMzl+Cl Yu3Yf4bDmOfb9NU5ZkmZhL+5PJ+RHgGTvDNxIDFPgjK781mEGuUgZ4FAR34rMm4XHjb3 3Wrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747747561; x=1748352361; 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=FmHBtZpsBIrWTXN1EzO1pSICL4Jn5YL6ChmiYp7rEAE=; b=LOsizTGSHEkDMttj0eYWxAGXZtsSYLEfSt6NA6tVATw9CXLUjgtMutMgtZ5ixFzYVp j+kTmidPHShtSR2SCsim43KKdrm/w4l6mdMJg7zdSz4fRBTnZmfvKR2AW9P5XPGkUhz6 I32618rdawB9z+LqtcYo3VxCBKOSvafnoUMm7WIXHN7IJjj3J4iEZOK3bI8+/Xu5RMDb BB8Pnu8fVY5FMwXMyAgwes2VGxnP+tXj1pV3l/2mThV2qRUbIrmWoHRSTjChOreSbk+x EC8h0bhocLPpXlB+NTNrbHAamkhEf8pymHZ/roLW5FpjHDPeShRxy+MVmUX1nJStxPEc QhsA== X-Forwarded-Encrypted: i=1; AJvYcCXiqoz/g1fDqAhSiT40ghD6Y9A1jldxkSaLtCCY8oBZtQTmHviOw9tsQwYW7+Rc96TfrhcR6zaYKbzhzaVr@postgresql.org X-Gm-Message-State: AOJu0YzW6R8mA8mSkCqC+ZjVsF3lm4z07OIaNi9LTji4s2P2sAl8R+4+ 4hoMIWpGHgUvkXRRsL4IVfT1eMN9aDo8/mOASAE1lWGvrpb1l8Axz1MfJqfqu8hWiMPlzqj3I1d U3rAcMisIQptZPMDcnFpqYT3GDxS+rOs= X-Gm-Gg: ASbGncvhtoKCtUap2G17z5cRmhtekixtouv8GjyhJ3XtXfdoSYAIAMWeqpXHEhv4aPq XvHZlsd503SxqERQIrj1HEgBMXABQiqwlu3oHEIUU5qwoSNK3H/BrdKba6nV/sL2qEc45dxmpyS q2zHP90YRMwudZAwFCwpS+3UxLVpxFlhWbpPBdIN3zXidO X-Google-Smtp-Source: AGHT+IEw8NTFev3BvY80pXMa/9EtqdIxiNfcC0ENqLDJIGvTZLxbU7I7HRe/XZMK4qX5SH0Zr7XLCcGUVepveK5Cx00= X-Received: by 2002:a17:90b:524c:b0:2fa:42f3:e3e4 with SMTP id 98e67ed59e1d1-30e4dac99b4mr28939149a91.3.1747747560539; Tue, 20 May 2025 06:26:00 -0700 (PDT) MIME-Version: 1.0 References: <54c35fb9-da3a-4754-ab8c-46ed0b612465@vondra.me> <684c70d7-180e-461d-9377-600c2db581ba@vondra.me> <605328.1747710381@sss.pgh.pa.us> In-Reply-To: <605328.1747710381@sss.pgh.pa.us> From: Amit Langote Date: Tue, 20 May 2025 22:25:41 +0900 X-Gm-Features: AX0GCFukxkXY0hD3hMLGDXmxPpvWEyJk2vtOXw_JsLQc5eoe7_TH2WZLRcV9mVQ Message-ID: Subject: Re: generic plans and "initial" pruning To: Tom Lane Cc: Tender Wang , Alexander Lakhin , Tomas Vondra , Robert Haas , Alvaro Herrera , Andres Freund , Daniel Gustafsson , David Rowley , PostgreSQL Hackers , Thom Brown 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 Hi Tom, On Tue, May 20, 2025 at 12:06=E2=80=AFPM Tom Lane wrote= : > My attention was drawn to commit 525392d57 after observing that > Valgrind complained about a memory leak in some code that commit added > to BuildCachedPlan(). I tried to make sense of said code so I could > remove the leak, and eventually arrived at the attached patch, which > is part of a series of leak-fixing things hence the high sequence > number. > > Unfortunately, the bad things I speculated about in the added comments > seem to be reality. The second attached file is a test case that > triggers > > TRAP: failed Assert("list_length(plan_list) =3D=3D list_length(plan->stmt= _list)"), File: "plancache.c", Line: 1259, PID: 602087 > > because it adds a DO ALSO rule that causes the rewriter to generate > more PlannedStmts than it did before. > > This is quite awful, because it does more than simply break the klugy > (and undocumented) business about keeping the top-level List in a > different context. What it means is that any outside code that is > busy iterating that List is very fundamentally broken: it's not clear > what List index it ought to resume at, except that "the one it was at" > is demonstrably incorrect. > > I also don't really believe the (also undocumented) assumption that > such outside code is in between executions of PlannedStmts of the > List and hence can tolerate those being ripped out and replaced. > I have not attempted to build an example, because the one I have > seems sufficiently damning. But I bet that a recursive function > could be constructed in such a way that an outer execution is > still in progress when an inner call triggers UpdateCachedPlan. > > Another small problem (much more easily fixable than the above, > probably) is that summarily setting "plan->is_valid =3D true" > at the end is not okay. We could already have received an > invalidation that should result in marking the plan stale. > (Holding locks on the tables involved is not sufficient to > prevent that, as there are other sources of inval events.) Thanks for pointing out the hole in the current handling of CachedPlan->stmt_list. You're right that the approach of preserving the list structure while replacing its contents in-place doesn=E2=80=99t ho= ld up when the rewriter adds or removes statements dynamically. There might be other cases that neither of us have tried. I don=E2=80=99t think that mechanism is salvageable. To address the issue without needing a full revert, I=E2=80=99m considering dropping UpdateCachedPlan() and removing the associated MemoryContext dance to preserve CachedPlan->stmt_list structure. Instead, the executor would replan the necessary query into a transient list of PlannedStmts, leaving the original CachedPlan untouched. That avoids mutating shared plan state during execution and still enables deferred locking in the vast majority of cases. There are two variants of this approach. In the simpler form, the transient PlannedStmt list exists only in executor-local memory and isn=E2=80=99t registered with the invalidation machinery. That might be acceptable in practice, since all referenced relations are locked at that point -- but it would mean any invalidation events delivered during execution are ignored. The more robust variant is to build a one-query standalone CachedPlan using something like GetTransientCachedPlanForQuery(), which I had proposed back in [1]. This gets added to a standalone_plan_list so that invalidation callbacks can still reach it. I dropped that design earlier [2] due to the cleanup overhead, but I=E2=80=99d be happy to bring it back in a simplified form if that seems preferable. One open question in either case is what to do if the number of PlannedStmts in the rewritten plan changes as with your example. Would it be reasonable to just go ahead and execute the additional statements from the transient plan, even though the original CachedPlan wouldn=E2=80=99t have known about them until the next use? That would avoid introducing any new failure behavior while still handling the invalidation correctly for the current execution. > It's possible that this code can be fixed, but I fear it's > going to involve some really fundamental redesign, which > probably shouldn't be happening after beta1. I think there > is no alternative but to revert for v18. ...Beyond that, I think I=E2=80=99ve run out of clean options for making deferred locking executor-local while keeping invalidation safe. I know you'd previously objected (with good reason) to making GetCachedPlan() itself run pruning logic to determine which partitions to lock -- and to the idea of carrying or sharing the result of that pruning back to the executor via interface changes in the path from plancache.c through its callers down to ExecutorStart(). So I=E2=80=99ve steered away from revisiting that direction. But if we=E2=80=99re not comfortable with either of the transient replanning options, then we may end up shelving the deferred locking idea entirely -- which would be unfortunate, given how much it helps workloads that rely on generic plans over large partitioned tables. Let me know what you think -- I=E2=80=99ll hold off on posting a revert or = a replacement until we=E2=80=99ve agreed on the path forward. --=20 Thanks, Amit Langote [1] https://www.postgresql.org/message-id/CA%2BHiwqGSOge3eT3kcm_nxCSA3Ut%2B= d0jtchi8g8J9uXi-kyC7Jw%40mail.gmail.com [2] https://www.postgresql.org/message-id/CA%2BHiwqHRRFQN6yZ54fBydOTM6ncqZB= CmewZ6n519RjRdDsO44g%40mail.gmail.com