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 1w3pph-001acz-2z for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Mar 2026 06:29:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w3ppg-009BpG-1I for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Mar 2026 06:29:12 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w3ppg-009Bp7-0D for pgsql-hackers@lists.postgresql.org; Sat, 21 Mar 2026 06:29:12 +0000 Received: from mail-vk1-xa2a.google.com ([2607:f8b0:4864:20::a2a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w3ppd-00000000Igx-3Pm5 for pgsql-hackers@postgresql.org; Sat, 21 Mar 2026 06:29:12 +0000 Received: by mail-vk1-xa2a.google.com with SMTP id 71dfb90a1353d-56cd71a7630so747522e0c.2 for ; Fri, 20 Mar 2026 23:29:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774074548; cv=none; d=google.com; s=arc-20240605; b=YLiHHQ31a4CknfYrVRsDdQvgrYfkDlYwctsxi+XYBxcqPsU9tZpswSlmSQc5n0EwtX cAsQS32cm/wM1Kf0W2IqQbXNlnhqYxjUKq+R8U854UWDGRWpvcYzKR42qdSmI6wqYdLl fMCpZeMmKcIH6Bb8Qqje7s3I4iR4AMHQNWq+x6dg5QT7ZvL8Y87TckCR/KlYY2YUAXEW tdh+BDC8qa4L52lA4dsQYCGkqj1kA28X6yjk1VNF2L/y3bJ8RRsgnjhPRpxJL3B2SB5j AINQBnbI+Mox4U+aqSisTOTx4AWDKSoLhBUKyoJfgCvsxPQ/lQ70Z1yFVIieJ+fDQ6dw c3Yw== 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=ka8AQT54h6dzYb7YtK+S4ye5gpCAXYz1MXSn19amL3o=; fh=r+BncCDTlNGsQwidKyWH1DdQx4LGExXj8CDh66cgxns=; b=AjDU0LO72u7nHimp4Fuv/VmlA95FssYMqFuxgi8JJF4zWaf8enGzBzOqVFITsx0coE bcAcso1QGYUdTQEfkXPuKl5Fqc/UQwtctooA5p/BW4dLSPn0v2iS9xcK7zqHc/OQLVB5 tPhb/9ZR/ylaBQe5yZxIz3V2WlvhO36gDkw/OTkOYmW2CxcYkupVVzZ17fQ9V0uUetk0 sWHGhEvn6Hu2WS6MfsVjcBWfFNiAmqDA5ZoMp3+eCsvQAgKLMsFrpEO26HKp60JTbPcl Kb6216rTyHsLuZ0oZlBwcxyygTW58ddeHlZnkj9Mzn+CWhFBDNxKJdOiYOPwJsqGSv/W Itfg==; 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=20230601; t=1774074548; x=1774679348; 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=ka8AQT54h6dzYb7YtK+S4ye5gpCAXYz1MXSn19amL3o=; b=Tbx6enYRjJf/u7m3S7iYLX+28Y2rKSvO7MHG2QjdqLc573wq4K0j2/PxbeNXTK2v0n aBo2d9+aFfGqAb4YGaIQo//gZVVR0+6Fj9bmcz4k/iCFZuqTxxrIVN9WDaBSoUKN5Eal ln0vPwyhMpmn5X5WSQkERKYBTCfiZ3WM8jmiYnXHbJHupH9ToKN1hW1i8dgSy21tBW5A P1MuwsAmDL/ZHaeoz4ZnWwSJpJyKHLiQGG6xs4Kcr7/G8ZA1rkRT8suNEKogzVsFDCIe 9przclx5QRMv+U7u/uX8TzFz5RSaR6YsjQeXDkYR2jBkAVQfMdaYXN0WZ778FDpC8JPs RjSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774074548; x=1774679348; 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=ka8AQT54h6dzYb7YtK+S4ye5gpCAXYz1MXSn19amL3o=; b=oBSKzaKzfqlZal0ohwksYl29OfhnDvS6kKtyKKhSxHMdkraA+4Wsv6QKLdXMEpGi0c e+Yu1KjQPH/WwjXTbJcoRPox26xTAW7xg1JJB3XAlTPLRFL/HppCStPYOEN1chcZh5CU 4G4ZKwq5tzOERmE01baMJN0ns/CFYUSJem0PD8KdWQx29ZhsrBqut9tzJppJonRS+q43 T5B9xPKZXxES2Orl39W3PztGIA4V9VR2/K/MIk11hmSqEyVHOOuPFOvygBXas+mXWyDo ERTJQG3YQxGsUdWGoHwRhtH4Gud9xFj3hjQdOIJB9Gj0/pbRjNewxyma+EwnZl5tBMAY F3jg== X-Forwarded-Encrypted: i=1; AJvYcCWeutBMWfJw6s4EYn0ta5Vj5ITCKTSmsYAsIb63PV3MJlcHwq1yPjdAEur5L+8zUd3S5s+dseci6mFHEsig@postgresql.org X-Gm-Message-State: AOJu0YxVnKBkHHkn1WJT60ssQKIqzqup/J38yKn8DEJhddt0acfiSHPD KuGut7kfvtkoJXT2ss0dyPhYcwpYseT/uU0uEm4uHt+r/8NwxbGaMqFQL1KpymfPcvzUln8j15t 5XH/B7h4ca/QHyI5CKw3hp/A/rkHVh4o= X-Gm-Gg: ATEYQzzRgHHTeicX435K7Jto+EJfN9qj4LxYXBPo2ZdNv0neg8axi2Xh4CGbSv/Hoe6 nUAZe0Av1ZgGZPgXpfvzreLXlGXBPZJhIcigQY0D1SZt/c/GT+LkGOKfx/p/B2uszfNvImJRJ0H 6QAwqiAJ0Q/RTPi25IjOp6whqC4fR7nR8vFlZPJnIc0owSa0R5vcZmHdsY4FvUJpHOB9a9uwhlH EFBlcIw4dxpXKRtTOhE+FE9+09BN3D15KKlhmXl93PZ2OXGdV3T3o7NL4otq/b8wPUKfAWhitA6 OMA3+co= X-Received: by 2002:a05:6122:a19:b0:56a:7f37:d18f with SMTP id 71dfb90a1353d-56cde340980mr2681134e0c.3.1774074548109; Fri, 20 Mar 2026 23:29:08 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: SATYANARAYANA NARLAPURAM Date: Fri, 20 Mar 2026 23:28:57 -0700 X-Gm-Features: AaiRm51dRRW4Q3YOY-3ZIgXXmKctkoRw8IuSNy09Jg9wNA2pKCJFV2Sy2a8fLeE Message-ID: Subject: Re: Introduce XID age based replication slot invalidation To: Bharath Rupireddy Cc: "Hayato Kuroda (Fujitsu)" , John H , PostgreSQL-development Content-Type: multipart/alternative; boundary="0000000000003ec3b4064d82eb63" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000003ec3b4064d82eb63 Content-Type: text/plain; charset="UTF-8" Hi Bharath, Do you think we need different GUCs for catalog_xmin and xmin? If table bloat is a concern (not catalog bloat), then logical slots are not required to invalidate unless the cluster is close to wraparound. > I made the following design choice: try invalidating only once per > vacuum cycle, not per table. While this keeps the cost of checking > (incl. the XidGenLock contention) for invalidation to a minimum when > there are a large number of tables and replication slots, it can be > less effective when individual tables/indexes are large. Invalidating > during checkpoints can help to some extent with the large table/index > cases. But I'm open to thoughts on this. > It may not solve the intent when the vacuum cycle is longer, which one can expect on a large database particularly when there is heavy bloat. > Please find the attached patch for further review. I fixed the XID age > calculation in ReplicationSlotIsXIDAged and adjusted the code > comments. > I applied the patch and all the tests passed. A few comments: @@ -495,7 +525,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg MemoryContext vac_context, bool isTopLevel) { static bool in_vacuum = false; - + static bool first_time = true; first_time variable is not self explanatory, maybe something like try_replication_slot_invalidation and add comments that it will be set to false after the first check? + if (TransactionIdIsValid(xmin)) + appendStringInfo(&err_detail, _("The slot's xmin %u exceeds the maximum xid age %d specified by \"max_slot_xid_age\"."), + xmin, + max_slot_xid_age); Slot invalidates even when the age is max_slot_xid_age, isn't it? Thanks, Satya --0000000000003ec3b4064d82eb63 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Bharath,

Do you think we = need different GUCs for catalog_xmin and xmin? If table bloat is a concern = (not catalog bloat), then logical slots are not required to invalidate unle= ss the cluster is close to wraparound.=C2=A0

=C2=A0
I made the following design choice: try in= validating only once per
vacuum cycle, not per table. While this keeps the cost of checking
(incl. the XidGenLock contention) for invalidation to a minimum when
there are a large number of tables and replication slots, it can be
less effective when individual tables/indexes are large. Invalidating
during checkpoints can help to some extent with the large table/index
cases. But I'm open to thoughts on this.

It may not solve the intent when the vacuum cycle is longer, which on= e can expect on a large database particularly when there is heavy bloat.
=C2=A0
Please find the attached patch for further review. I fixed the XID age
calculation in ReplicationSlotIsXIDAged and adjusted the code
comments.

I applied the patch and all t= he tests passed. A few comments:=C2=A0

@@ -495,7 += 525,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStr= ategy bstrateg
=C2=A0 =C2=A0 MemoryContext vac_context, bool isTopLevel= )
=C2=A0{
=C2=A0 static bool in_vacuum =3D false;
-
+ static bo= ol first_time =3D true;

first_time variable is= not self explanatory, maybe something like try_replication_slot_invalidati= on and add comments that=C2=A0it will be set to false after the first check= ?


+ if (TransactionIdIsValid(xmi= n))
+ appendStringInfo(&err_detail, _("The slot's xmin = %u exceeds the maximum xid age %d specified by \"max_slot_xid_age\&quo= t;."),
+ xmin,
+ max_slot_xid_age);
=
Slot invalidates even when the age is max_slot_xid_age, isn&= #39;t it?



Thanks,
Satya=C2=A0
--0000000000003ec3b4064d82eb63--