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 1whwgR-000VGJ-0O for pgsql-hackers@arkaria.postgresql.org; Thu, 09 Jul 2026 21:53:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1whwgP-00EpNB-1R for pgsql-hackers@arkaria.postgresql.org; Thu, 09 Jul 2026 21:53:26 +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 1whwgP-00EpMu-05 for pgsql-hackers@lists.postgresql.org; Thu, 09 Jul 2026 21:53:25 +0000 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1whwgN-00000000NcD-2R1l for pgsql-hackers@postgresql.org; Thu, 09 Jul 2026 21:53:24 +0000 Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-3810c5d691bso329345a91.1 for ; Thu, 09 Jul 2026 14:53:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1783634002; cv=none; d=google.com; s=arc-20260327; b=M0dq5QmFaZ22EyeX8+gpYTrIaB9yaNU09iOlVF0mA+mGAoAzoTIC6BzrlGHCpLrGJX Xmu7Effw+ua96mnOAbkolXHXsSsDh8CzszMidLbKC1R0lEJZmJwlc02GV5ZYm2hfHSJX 0oFCMOTzlDmcnK3DaMc9oOJrcEoHXInoZY+SYks/8HPdATfY/76xyhZVco0hteoe/wf2 tfBGWVATl9HFuSELm0jhtW97qt2R4qMHEW+Qfl11RcVyD3yd0j8Bi7CO+8aXjsJWU7uH CukSitqs0onxj65Sp86ckqwz+lzezT2DTOSZ5D0fXqmn9NQAP6e/DsAmgA0O6dGM/Z62 W9+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=ySMuaLOpxJr7OCThGIvSfanbRaB8x6ydzGySk7wuOGw=; fh=hdU382xYya1luXn65v/QwSyJCGVVuKUdGQXE2cEHUy0=; b=strnlbJAugeKP+EfGDSrjHC7dqCtHMlz7eTlqWLetbw6NX41jQW1y5HpAdM5d+JVun TBLjgDKyv8KLnPlYBfFcGY/Q1CXRySQ3A6bv2OPOEBv3vZbkutuFE1d4hqZroazHvAfo vKcU4pMGjuUjS55CPEyEY3OETu6wIeKtfv7dLUbP6TxkoLXNlKSgDah0YGzBq4aGW+vf VgiVnVaqJnmQYYngvXs1wV2aOqDjFFZQyV3E5V1rhldg2z9ypJvstmDrGKPJztYMtRlh zOF90p6EXeN2/0tcT5b7dIOzF1ye6UTmwtXhFJGpqV4OVW9kXJIG9YGgeYniTcjvyDFx Y/Ig==; 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=1783634002; x=1784238802; darn=postgresql.org; h=content-transfer-encoding:content-type:cc:to:subject:message-id :date:from:in-reply-to:references:mime-version:from:to:cc:subject :date:message-id:reply-to:content-type; bh=ySMuaLOpxJr7OCThGIvSfanbRaB8x6ydzGySk7wuOGw=; b=Dvyg4zgH6i2AKXX3/hugRvKxznFHh0K2GRdo7fRlSznfTyCFe+VyYyyop0yorP37Lk VwL7nxGlWcxA+7/hUqcjhMaaYl3DtxDjpSlWTWSw949qkB7ZCuBzxxLr2HJGXsnAXfll EDP11pZsPoZCI5uv4bp/qu96zaksHkO9o/eItu3299UbN51XZRjvfPww1FZ0hmdthPZG eThQ29kcl+MUQoPbSDBDwqgOzbavrcPXx7Q5WOY7Rzfz+C5mX2gxGBBGNBuBqCnrP5G6 hCURA+dPOXT+bOiiYtlY9Sgq75TKXQlgXo01iviD1C6TqzbBTua/7ZuM7bJg2x/1W5Q9 btEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783634002; x=1784238802; h=content-transfer-encoding:content-type: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 :content-type; bh=ySMuaLOpxJr7OCThGIvSfanbRaB8x6ydzGySk7wuOGw=; b=W3b2fIs7QJWOE6xgla3yU0DBZPjKmN+GyvvxvTTUuCduXwbrQhO/Qh5fG9KPkI7485 jh42Fw8BL832EzDx3oY4PmFED9dnXxVRwCBo/Lwp8bfH2NYs+cYrrzwvU33GVagdKsgX qHORzDMR1pKKZoHnQl5xakEc1UHw7/QdFNDthWcVpVEbK2lL6qwY0ssOhT83z76wXyJn QVOK9sta+y3GwbdP6avL2lF9XcU4lzqNluv7NENzLnsl/58WDwL9AYAuQUWDmuEVmiyP wXjpoiAzBOn6X7oRNtKQM4SRSsb2rAVIFYc31mAgLL/MfidaFgsmxRY2apD1+R5kZtOg tmoQ== X-Forwarded-Encrypted: i=1; AHgh+RpdxNXLcsr+a+kc3mdtR0/xqY1JKvIDE6E64w49FDWhezPUXbnG0x/ITRUfcajTuQmxCnuc0I+gnZbxIopL@postgresql.org X-Gm-Message-State: AOJu0YzmzkdpoFMv6LMvYFqxRxo4vmNRiMtqdx8pF85z4e4WpgkVCxao A6pSGnq6GIP6O92Falw3o9cFReQ2IFN3yEkvow5GkLbE9RvKNt95HU6uR7UIX5LIdUS8szsfT0a RCzBe8icWkuHnGuDAeh4PSpJDVs+XE34= X-Gm-Gg: AfdE7cnK9zppect+4bn2gRJ97nXnOoDof9ARur29SLgDXl1+GgTwXr7HnvlgidzulqV JOh0lQewtq4+3yIJXzxbm5cLQccnICRNSW++h7JRYg1kNxaIc0+cxZLON8xfFtENR0tMR2tOOji WJ1cw1AvzofBK6gIS62oSI/lGbTBP4+4+WUwDgzJDhrgo645QuSoso3gkkp3kDGrMalrg0lnfjn avhmqHQA6Z6IwZHHTgbMoJBcGVRgu3+MFIRHIxC7cac70R8RXyUnRKEeBEfOQK4uErCG8zkSA== X-Received: by 2002:a17:90b:570d:b0:37f:9ce1:736b with SMTP id 98e67ed59e1d1-389417e1de6mr7666463a91.33.1783634001864; Thu, 09 Jul 2026 14:53:21 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Masahiko Sawada Date: Thu, 9 Jul 2026 14:52:44 -0700 X-Gm-Features: AVVi8CeEvBxSvDfPDBiwwkBq_VmzDf-hVAqNMy3zoqaLovAiASWdrmSbxS8PXCs Message-ID: Subject: Re: Introduce XID age based replication slot invalidation To: Bharath Rupireddy Cc: Srinath Reddy Sadipiralla , SATYANARAYANA NARLAPURAM , "Hayato Kuroda (Fujitsu)" , John H , PostgreSQL-development 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 Mon, Jul 6, 2026 at 11:34=E2=80=AFPM Bharath Rupireddy wrote: > > Hi, > > On Thu, Jul 2, 2026 at 4:18=E2=80=AFPM Masahiko Sawada wrote: > > > > > Thank you Sawada-san. I've been thinking more about it and I agree we > > > need to address this. While I still think the scenario is unlikely in > > > practice (SIGTERM would have to take a long time, the slot's xmin > > > would have to be very old while the walsender is still running, etc.)= , > > > I think it's worth handling. > > > > > > I can think of a couple of approaches: > > > > > > 1. Use ConditionVariableTimedSleep instead of ConditionVariableSleep > > > when called from an autovacuum worker. Workers don't block forever, > > > but they still wait for the timeout duration, still send redundant > > > SIGTERMs, and a correct timeout value needs to be chosen. When it > > > expires, the worker either retries (still stuck) or gives up (same as > > > approach 2). > > > > > > 2. Make the vacuum path non-blocking when another process is already > > > invalidating the same slot. The first process to attempt invalidation > > > proceeds normally: it sends SIGTERM and waits on > > > ConditionVariableSleep for the process holding the slot to exit. But > > > if a subsequent autovacuum worker finds that another process has > > > already initiated invalidation of this slot, it skips the slot and > > > proceeds with vacuum instead of waiting on the same > > > ConditionVariableSleep. > > > > > > I think approach 2 is simple. If another process is already > > > invalidating the slot, there's no reason for the autovacuum worker to > > > also block. The tradeoff is that this vacuum cycle's OldestXmin won't > > > move forward and it will need another cycle for this relation. But > > > that's fine given that the scenario as explained above is unlikely to > > > happen in practice. > > > > > > Please let me know if my thinking sounds reasonable. I'm open to othe= r > > > ideas too. > > > > The third idea I came up with is that (auto)vacuum behaves differently > > in terms of XID-aged slot invalidation depending on the slot being > > used or not; (auto)vacuum invalidate the XID-aged slot if no one is > > holding the slot, and it just wakes up the checkpointer to invalidate > > the slot if a process is still holding the slot. If the XID-aged slot > > is not held by any process, (auto)vacuum simply invalidates the slot. > > I believe that while the former case happens in most cases in > > practice, delegating the checkpointer to invalidate XID-aged slots > > might help avoid vacuum from being blocked. > > > > What do you think about the above idea? > > I see two cases here. > > 1/ No one is holding the slot. The connection is gone for whatever > reason. Here vacuum just acquires and invalidates the slot right away, > no signal, no waiting, and this already works. > > 2/ The slot is held but has aged out, due to a slow connection, > replica lag, or slow decoding/apply. This is the case that involves > terminating the holder and waiting, which is where blocking can > happen. > > I partially agree with your suggestion for case 2. My preference is to > not add any blockers for vacuum. It does opportunistic XID-age > invalidation, invalidates the slots it can take without waiting, and > leaves the held ones to the checkpointer, which is the guaranteed > path. It is also easier to reason about and to explain to users. > > The tradeoff is that vacuum won't invalidate a held slot in the same > pass, so the relation being vacuumed right then doesn't get the > advanced horizon. Once the checkpointer has invalidated the slot, > later relations pick it up, which may well be in the same vacuum cycle > or next. I am fine with that. > > Given this, I do not think 0003 is needed anymore. Its whole purpose > was to stop multiple vacuum processes piling onto the same slot's > condition variable. If the vacuum never waits there, that contention > cannot happen. There is only one checkpointer. The unheld case is > already safe. The check runs under the slot's spinlock, so the first > process marks the slot invalidated and any others see it is done and > move on. No signal, no waiting. I will drop 0003. Agree to drop 0003 patch. > I would skip having the vacuum explicitly wake the checkpointer when > it sees a held slot. Imagine one walsender holding the slot's xmin and > 8 autovacuum workers running. Each worker hits that same held slot and > would signal the checkpointer, so we would get a signal per worker for > a single slot, repeated every cycle until the checkpointer acts. If > the checkpointer is already running, another request gets queued, and > this can happen repeatedly, creating a flood of checkpoint requests. I agree that we should avoid requesting checkpoints just to invalidate XID-aged slots. > Since 0001 already invalidates aged slots during every checkpoint, the > slot gets cleaned up on the checkpointer's regular pass anyway. I > would rather rely on that than send extra signals to perform > checkpoints. If we rely on the checkpointer for held slot cases, XID-aged slots held by someone could be left for up to one day, the maximum value of checkpoint_timeout, in the worst case. I considered an alternative idea: (auto)vacuum sets a flag on shmem for XID-based slot invalidation and has the checkpointer perform the invalidation upon request, without creating a checkpoint. But that seems beyond the checkpointer's role. Given that it's not common for XID-aged slots to be still held by someone, it would be okay to skip the held slots. The same applies on replicas, where the restartpoint pass is the only mechanism anway. So I agree to simply skip held slots. Regards, -- Masahiko Sawada Amazon Web Services: https://aws.amazon.com