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.96) (envelope-from ) id 1wCgJI-002DbU-1b for pgsql-hackers@arkaria.postgresql.org; Tue, 14 Apr 2026 16:08:20 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wCgJG-00CiBd-2Q for pgsql-hackers@arkaria.postgresql.org; Tue, 14 Apr 2026 16:08:19 +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.96) (envelope-from ) id 1wCgJG-00CiBT-15 for pgsql-hackers@lists.postgresql.org; Tue, 14 Apr 2026 16:08:19 +0000 Received: from mail-yx1-xb132.google.com ([2607:f8b0:4864:20::b132]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wCgJF-00000000zqb-0K5Z for pgsql-hackers@postgresql.org; Tue, 14 Apr 2026 16:08:18 +0000 Received: by mail-yx1-xb132.google.com with SMTP id 956f58d0204a3-651ce2484d5so2559673d50.1 for ; Tue, 14 Apr 2026 09:08:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776182897; cv=none; d=google.com; s=arc-20240605; b=O9itCGyYvTHOHmxgRf6Mbx6MzKO6C8asPNHwPet9WBHCU4lnrj5f6l3rNFZSpRrAdH I8QaNrC0uFuXUSNh3KaxFLoZcOWeNbNucJK3ZV6xj9eemV6/PNAmSyGlr68eWeWLFxnA 5pNnQ5Esmg5C00zNm2IJOFsy7L4yOH198VGyTBWbripEjNCwJPi5k2ZPUcXiYCXJ71Ix UBGwjT7lI9MUINeUMmkZWWsP4LKFHNHTJrH+nvrO7QrV4yofPjRuOVYsPec0CpPc8HMC gD1Ln7GwI6KZzfSF4u7nhhUDwIm2xB0noo/miGBlphID+Ty9eonnaH4OttDP1sLDckhk xNcw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=poEnNa1JGyqEn2QZt1TqtjsqByWDaLn/MCsOzlf7snY=; fh=PVOs68opFao8thHV9WTLeba7J8XrUe25jCGsdBzVKNo=; b=etI4/cjAolS0RUnq1XEXs90cd4h1JTaFkGWHa61EW255Zn9lMMQ6x8wb3HYvJNCm7N gOfqaQh56tAkpHISJJGYcfoCS4cLQ6PA4BCTLrCnfYMimPDeBnzCcJikgXhA8IBsJ6tN 7nzuUU1sgbU6viC3zTp7ZNotCBQ760IRg3uogxLZ+Pp2kw9Cq44dT0juzgNrv11unzHb 8e6rBChmSX78g08k6MxVzIazL7ZkuZVPK534ao0eiiBjwWkW92NSwlsMEWWcgxVkFCYA VGEQV5dvBzJ2Xa4dCjZ9vSHPuOyrDcdVqxei+oCUYE0YCWV2xOotCV3ghn6L2WiN5OsU nhbw==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776182897; x=1776787697; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=poEnNa1JGyqEn2QZt1TqtjsqByWDaLn/MCsOzlf7snY=; b=nP+k+uOXzJxZp2BdkOE/fTHnnH/sq4S3EoPIuhBWFY4ReEn2nCeJPVu1rVb9OdbjIK qu+oVjz0IjRvK0cC6j5x8m7+DuGKsxyKYGdedffoAibMv4P2f1Iv1a/s4kkWGS8xTVhS aFOoP0bPpxtJd/0AQftQYpIIPXFmsO1GZ8OSKDno+qKbIS7WRFj6Zvc0bDFVoC/dXDzR JhlXDD/mLKKq6t1BhtN4T7flc18YoQRNlPcntjXVBSRH8xrtZ8kX6w8GWyOUjt66idKJ f/bm0D1f5afKOgdVnbmlnn75a0CZaMqr2m7cAEo4QqL+hSy+r6TRTFFeXjzTtPUIKt/b Q/xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776182897; x=1776787697; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=poEnNa1JGyqEn2QZt1TqtjsqByWDaLn/MCsOzlf7snY=; b=HQejhadFYitPx9/fA2uaDd61BC0a+8l7MpJFm0tN1/8wUh8G5AalCj72/vgVQ9VxGs vtI93a8gKCZbO0SxPNJseeLmnQIbavvWcywmo0SUCr8x+cwYzAUXPFMO5qqwVGjNqJXV nTg8PsW37Ctux0BAu2fPWCW7js1wbiMfyxICxeF/lG6+vV/Le0MUP3PUYNILPA7o7SHP NYBFx6iV+Zy3XiK93ujL6S9kI6v0QvXxFsZ4YhHjWVdKnWzifHcEmOrzZAk2U98Eu706 KSAAw8CpJ/zst8sqLsrKq6FoTV7gpVJJOtld0XK9Fo6/Zo1Bnb8bI/xkG9Sr53eDPNvf cgtw== X-Gm-Message-State: AOJu0YyqeW2+B/9dZiBKh9oJ1l9jGViyFc+1XBEIop7/Ibm5ToXkzYb9 r6e+yi4JgoohSM/QmSldfrrLuja+EViUNaZ7t2vMNhpjOH+/0yqAOJeu3etTx/5w6clbU/Y7wxH 8ODWOA0ErbpUsvJTE/8+XHSx8gmXURlg= X-Gm-Gg: AeBDiev8RNG60Q1suTLk5wtA+SOYYqkzAmWNSgr3f4J0ruUwmtrB9/m80beUpVP5Hsm CAuCM76QPbqew8GoWEdv+B8NLonCFZDThO5vmO4kFnkCaf5GiDSgBh7VGPGplhqE0mpLOps2vUK VgUdbENyMqtv/e5DeVzsb0iweEwPKD1JNEqyuyoEmHa+MPIIKStzlCKWmqZ3G0ykSQhSMylUMD8 LtGP55lgLIZr6O0UT4PnVl7yFMsJueqkhFYDx0vHN6SS8MDvS3d12R1+44Gw8+u8UELAUrbJVXJ ZvVxF4TVjXTWBtCBB3Vht8Hm23aygh2fBbF6suQf2c7ikDYhKNzRLrJrRjOQuY4EP1DWgsvW82z wsdYPY8vwF6zcOTLV X-Received: by 2002:a05:690c:8e16:b0:7a2:a8dd:165d with SMTP id 00721157ae682-7af72438777mr146917867b3.53.1776182896401; Tue, 14 Apr 2026 09:08:16 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Kirill Reshke Date: Tue, 14 Apr 2026 21:08:04 +0500 X-Gm-Features: AQROBzBKbffzgKRF3I25T081XyGS_T5Qh-66Og5RialnKL0Qr6lslcLiqIW3NNA Message-ID: Subject: Re: GetCachedPlan() refactor: move execution lock acquisition out To: Amit Langote Cc: PostgreSQL-development Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, 14 Apr 2026 at 13:20, Amit Langote wrote: > > Over in the "generic plans and initial pruning" thread [1], I came to > think that the cleanest way to address the architectural issue behind > that thread is to make GetCachedPlan() do less execution-related work. > Specifically, it should stop acquiring execution locks itself, and > leave that decision to callers. > > GetCachedPlan() has long combined plan acquisition with execution > setup, and that coupling makes it harder to improve either side > cleanly. Tom pointed in this direction back in 2023 [2]: > > "...the whole problem arises because the system is wrongly factored. > We should get rid of AcquireExecutorLocks altogether, allowing the > plancache to hand back a generic plan that it's not certain of the > validity of, and instead integrate the responsibility for acquiring > locks into executor startup." > > This patch takes the first half of that suggestion by moving execution > locking out of the plancache and into its callers. > > The attached patch does that, with no intended behavioral change: > > * Remove AcquireExecutorLocks() from CheckCachedPlan(), so > GetCachedPlan() returns a plan without holding execution locks. > > * Add a new internal helper in plancache.c, LockCachedPlan(), which > acquires execution locks, rechecks validity, and returns false if the > plan was invalidated, so the caller can retry. > > * Add GetCachedPlanLocked() as a convenience wrapper that fetches a > plan, calls LockCachedPlan(), and retries on invalidation. This > becomes the normal entry point for callers that want a plan ready for > execution. > > * Convert existing GetCachedPlan() callers to use GetCachedPlanLocked(). > > The second half of Tom's suggestion, moving that responsibility into > executor startup, is trickier. ExecutorStart() is a stable API with > extension hooks, so changing its contract has a fairly high bar. I > tried that route once already [3]. > > A working variant that adds an ExecutorPrep() entry point, with a > wrapper implementing pruning-aware locking on top, was discussed in > the original thread [1]. But rather than propose that whole stack at > once, I think it is better to do this in phases: first decouple plan > acquisition from execution locking, then revisit the ExecutorPrep() > piece separately if this goes in. > > The eventual goal is still pruning-aware locking. I'm posting this > piece separately because the original thread has become fairly long, > and this part seems easier to review on its own. > > [1] https://postgr.es/m/CA+HiwqFGkMSge6TgC9KQzde0ohpAycLQuV7ooitEEpbKB0O_mg@mail.gmail.com > [2] https://postgr.es/m/4191508.1674157166%40sss.pgh.pa.us > [3] https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=1722d5eb05d8e5d2e064cd1798abcae4f296ca9d > > -- > Thanks, Amit Langote Hi! I have slightly checked v1. Can't tell if refactoring does make cached plan maintenance more straightforward because of lack of experience in this area, but here's my 2c > + > + for (;;) > + { > + cplan = GetCachedPlan(plansource, boundParams, owner, queryEnv); > + if (LockCachedPlan(cplan)) > + break; > + > + ReleaseCachedPlan(cplan, owner); > + } Should we use CFI here? > +static bool > +LockCachedPlan(CachedPlan *cplan) > +{ > + AcquireExecutorLocks(cplan->stmt_list, true); > + if (!cplan->is_valid) > + { > + AcquireExecutorLocks(cplan->stmt_list, false); > + return false; > + } > + return true; > +} simply `return cplan->is_valid ` would be more Postgres-y here, isnt it? -- Best regards, Kirill Reshke