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 1wWdQm-002km1-1x for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Jun 2026 17:06:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wWdQj-003HZw-16 for pgsql-hackers@arkaria.postgresql.org; Mon, 08 Jun 2026 17:06:29 +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 1wWdQi-003HZm-25 for pgsql-hackers@lists.postgresql.org; Mon, 08 Jun 2026 17:06:28 +0000 Received: from mail-oo1-xc29.google.com ([2607:f8b0:4864:20::c29]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wWdQg-00000001iUO-2KMT for pgsql-hackers@lists.postgresql.org; Mon, 08 Jun 2026 17:06:27 +0000 Received: by mail-oo1-xc29.google.com with SMTP id 006d021491bc7-69de9bc590aso3346339eaf.1 for ; Mon, 08 Jun 2026 10:06:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1780938386; cv=none; d=google.com; s=arc-20240605; b=HcU98/fMrLacodLqpKu03jJQHdar4pFGcXvRpl7MqFYLmpi5WpCO5EezKn37erJtQK uJxTGiPfodpz+8CLq0/f/QS+1yDOUcRZOqgGSahzm9f1vpEtxlbvE2zL5U9mpKlUjPq/ 6daH//M823dyRPmG6wEwAgzC4f77aT9GNJMeVMOsG83vkkqN7exYVxMaxKtiwe5nfTgg ZhJdI66Gzqy95b6Ow0xLWKBW8c+ZIEUxPkzsl9lltUU8ruU47TsD8Du3M4amJg3e0tGN LRBkeu6nIs8b6SJtiV7DzQC9X4EK/WkzaUF8HUnrdsB5ZvNVwsoOVdYGwMWbSQJvDclF lepQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=R9syrf0q40IGtCNMaCE/a/qttTccO7rZEcCv3U8SpDM=; fh=k/msbR7WkFTDT7HNOUQzEUR/eVDtdZVEnpnYKvp2nsU=; b=eYof1FwWUVqr0yWQ7Vjh7ChdRZOlkBGDJ10lWlXD37A+dlkoFcxwbAopvpT63cjKxL ZvcCsZKxUM3fSGnwP4KYdkarnyneSluXHBGs30fW3LF3GmjpS8QsKE2WdjYaRKASnbxR ZEbY0TOmLV7L/H3AlRx9mP6effAEpz9MOc8yhDF0fr2VGSjZArCy/Z8ZjFqAOSh8W5Xw xnk9E6IC1MWlJzY7DJHbnAAsEr07Hih2Ig6/4+PAKjqDn3waIosc9BaZrkPST5BkrRSs NZ9EeAAjXwPsArGph3e/YF6t/wCpmGYJmSNcen6TtofM1lmgYeoFt7DmmkvUkryE+7R1 Nj/A==; darn=lists.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=1780938386; x=1781543186; 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=R9syrf0q40IGtCNMaCE/a/qttTccO7rZEcCv3U8SpDM=; b=n5jFWYqsRL9KTzXRUnr12sK4DdnJQpbV2a7ubDFn2o9BvytLorgVVgCvXGBifLlyV6 vVZtmRkjy6zoe43JnrwmfuuFEmQjIL2Xqb3IARY0N89+/xkSInoTbrrI2tQhLXDerb1b lDcuL5QW+yNIhcML1wbwxd8k2ZaV2I3XROnlrGyxt6ADeMmdgm8PJBb+WgWgl0q+8PPm IItk1NbirlyIt6vzJI5rS5QdUZpcSYB6g0uJTWOvp+1Oy5CNprYdbZD8HRAtrYtirHHc YOBqgvw/lXVlJEVguQc45vyP42xf90OxKMY0ZW55CuU7RjhcA6OKsjBHCOce4boBb1Ui adXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780938386; x=1781543186; h=content-transfer-encoding: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=R9syrf0q40IGtCNMaCE/a/qttTccO7rZEcCv3U8SpDM=; b=O2w+p4R/McSSpnreNztZO8Ezx4582oJqZazdVFlW8dCgFl5CeiUi1cqkDrdSzWtkOY ri+JW/w2AyEj5nXAxm4/P6O98Y9Ao6MxKZ5TQX9Oj8a5mz8JD8FnLbuvEVCnqxRi+6bm k3001GYEMdG4s/MHTz9KVCupHt15IQvlKIidZ0R4OpmUxQzqBz3IfChUdJScKPcPwMez CjKi6yIRg3cacd3LY1QbWw9QAJsxwlkUklwPWl0QJNH7LJ1T3hr4KgALSFuusz+OzDub NJIzrx2RYWgGAZJdoxZDGPNQIzbYJSvh08rrSu6YgZrbbO3iB2UjlgWHbM5BA5fR70sf whkw== X-Forwarded-Encrypted: i=1; AFNElJ8xRJXbNjen6aqxPWGvAf23s7/yBX37N5cQ0ZVOcfvDffg1bhldOMxneffc5ypKksuVwAAZcZp/91dCKbGk@lists.postgresql.org X-Gm-Message-State: AOJu0Yw/J3UohC4NsgEjBE/Rht0NAEEEkyp5SEDs6INg44vxtuTcuOZN 5oOT57Wu0M/twm8WvopWvsu0BvyRRRnpHGYzlgQmZCST9PXxx0Fudht/Ojnl+anCWBgjwKjSupp 6mY1kX+JNSyyhuH8R6vT4X+sJr7SRz8wX2Bc9 X-Gm-Gg: Acq92OEsEPoGMVCe4a2ahgkjluc3gsDcR9yXqjY2gdPvRIKC6bVLrzQitZyOtGahx+M Z2FPtEnVhhvMhX8sg3dToy2ZBF8m9jxR/RiVO7YB+spKQrVO2HYG2LBSPletWNk2WOp2yoZD1mM I8lHEG073RWzUquYxL2KzDnjUTJhQa1e/cwlULD7PfqZ7H7/BGUAsm+2GT3s/oTllw/ZopRB7Bw KiZJgCA9Hq0ENHHTjYM2sU3UPVuhQ6eCXbN6vwu2tnXI3ORemMOaQbvtyw2rVU0f9l78jeH8DU0 tQk/ReWsxMfYj7SYXc92 X-Received: by 2002:a05:6820:1805:b0:69d:c5ad:40aa with SMTP id 006d021491bc7-69e68c4fb05mr7981309eaf.40.1780938385625; Mon, 08 Jun 2026 10:06:25 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Shlok Kyal Date: Mon, 8 Jun 2026 22:36:13 +0530 X-Gm-Features: AVVi8CeINpydmU4hLb-2gOpuMgSkVJokAGcJA49G0FNlE6iUiD7HoEreAzhUNbg Message-ID: Subject: Re: [PATCH] Preserve replication origin OIDs in pg_upgrade To: Ajin Cherian Cc: shveta malik , Zsolt Parragi , vignesh C , "Hayato Kuroda (Fujitsu)" , PostgreSQL Hackers , shveta malik 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 Thu, 28 May 2026 at 08:18, Ajin Cherian wrote: > > > > On Fri, May 22, 2026 at 8:27=E2=80=AFPM shveta malik wrote: >> >> On Fri, May 22, 2026 at 3:16=E2=80=AFPM Shlok Kyal wrote: >> > >> > On Mon, 18 May 2026 at 16:13, Ajin Cherian wrote: >> > > >> > > Rebased the patch as it was no longer applying. >> > > >> > Hi Ajin, >> > >> > I have started reviewing the patch. Here is my comment for v6-0002 pat= ch: >> > >> > Suppose we have a replication setup: publisher -> subscriber >> > and we are upgrading subscriber to subscriber_new. >> > And if initially 'subscriber_new' has a replication origin, upgrading >> > the cluster can error out. >> > >> > Example: >> > We set up a logical replication between publisher node and subscriber = node. >> > >> > On subscriber node: >> > postgres=3D# SELECT * FROM pg_replication_origin; >> > roident | roname >> > ---------+---------- >> > 1 | pg_16393 >> > (1 row) >> > >> > And initially subscriber_new has a replication origin: >> > postgres=3D# select pg_replication_origin_create('myname'); >> > pg_replication_origin_create >> > ------------------------------ >> > 1 >> > (1 row) >> > >> > postgres=3D# SELECT * FROM pg_replication_origin; >> > roident | roname >> > ---------+-------- >> > 1 | myname >> > (1 row) >> > >> > Now, if we run pg_upgrade to upgrade subscriber node to subscriber_new >> > node, we get an error: >> > ``` >> > SELECT pg_catalog.binary_upgrade_create_replication_origin('1'::pg_cat= alog.oid, >> > 'pg_16393'::pg_catalog.name, '0/01743078'::pg_catalog.pg_lsn); >> > psql:subscriber_new/pg_upgrade_output.d/20260522T140312.807/dump/pg_up= grade_dump_globals.sql:37: >> > ERROR: replication origin with ID 1 already exists >> > ``` >> > >> > This error occurs in "Performing Upgrade" stage. Should we add a check >> > in the "Performing Consistency Checks" stage so that we don't need to >> > re-initdb the new cluster to perform the upgrade? >> > Maybe we can add a check similar to >> > check_new_cluster_replication_slots(), where pg_upgrade errors out if >> > the new cluster already contains replication origins. Thoughts? >> >> +1. I had the same thought while reviewing the patch today. We should >> have it unless there is a reason we have avoided it?? > > > Fixed this. Added a new check for replication origins and if the new clus= ter has any existing replication origins, then the check will fail. >> >> >> Few trivial comments: >> >> 1) >> >> +#include "access/skey.h" >> +#include "catalog/indexing.h" >> >> pg_upgrade_support.c compiles without above. >> > > Removed. > >> >> 2) >> + Assert(!OidIsValid(rel->rd_rel->reltoastrelid)); >> >> Is there a reason for this sanity check? I generally do not see a >> Null-Toast table sanity check after every table_open. >> > > Removed. > >> >> 3) >> >> + >> + /* Dump replication origins */ >> + if (server_version >=3D 170000 && binary_upgrade && archDumpFormat =3D= =3D archNull) >> + dumpReplicationOrigins(conn); >> >> why the check is for PG17 specifically? >> > > In PG17, we started migrating pg_subscription_rel and the remote LSN duri= ng upgrades; prior to that, these were not migrated. Given that change, it = also makes sense to migrate replication origins from them. Otherwise, when = upgrading from PG17 to a later version, you could end up with a subscriptio= n where pg_subscription_rel and the remote LSN are migrated, but the corres= ponding replication origin is not created. > > > > On Mon, May 25, 2026 at 5:13=E2=80=AFPM shveta malik wrote: >> >> >> One issue in 002: >> >> binary_upgrade_create_replication_origin() has this: >> >> + originname =3D PG_GETARG_NAME(1); >> + >> + roname_d =3D CStringGetTextDatum(NameStr(*originname)); >> + >> >> We are getting origin-name (text) into Name-type which can not be more >> than 64 bytes. So if an origin has name more than 64, it will end up >> trimming the name post-upgrade. >> >> I tried this: >> >> Old-setup: >> postgres=3D# SELECT >> pg_replication_origin_create('this_is_a_very_long_replication_origin_nam= e_that_exceeds_the_limit_of_64'); >> pg_replication_origin_create >> ------------------------------ >> 1 >> postgres=3D# select * from pg_replication_origin; >> roident | roname >> ---------+--------------------------------------------------------------= -------- >> 1 | this_is_a_very_long_replication_origin_name_that_exceeds_the_= limit_of_64 >> >> >> Post-upgrade: name got trimmed to 64 length. >> ------------------------- >> postgres=3D# select * from pg_replication_origin; >> roident | roname >> ---------+--------------------------------------------------------------= --- >> 1 | this_is_a_very_long_replication_origin_name_that_exceeds_the_= li >> >> thanks >> Shveta > > > Fixed this. Now binary_upgrade_create_replication_origin handles it simi= larly to the way pg_replication_origin_create handles the name of the origi= n. > > Here's an updated version v7 containing these fixes. Hi Ajin, I have reviewed the patch and here are some comments: 1. I want to clarify, what is the expected behaviour when we upgrade the postgres instance from version <=3D 16 to "HEAD + patch"? - ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname)); - replorigin_create(originname); + if (!IsBinaryUpgrade) + { + ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname)); + replorigin_create(originname); + } and + /* Dump replication origins */ + if (server_version >=3D 170000 && binary_upgrade && archDumpFormat =3D=3D archNull) + dumpReplicationOrigins(conn); When the postgres instance with subscription is updated from PG 16 (or less) to HEAD, the replication origin is created as we do not have "if (!IsBinaryUpgrade)" check in HEAD, whereas when the similar instance is upgraded to "HEAD + patch", no replication origin is present after the upgrade. Is this difference in the behaviour between HEAD and "HEAD + patch" expecte= d? 2.a) Can we replace: + /* Check for OID collision */ + ScanKeyInit(&key, + Anum_pg_replication_origin_roident, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(node)); + scan =3D systable_beginscan(rel, ReplicationOriginIdentIndex, + true /* indexOK */, + SnapshotSelf, + 1, &key); + collides =3D HeapTupleIsValid(systable_getnext(scan)); + systable_endscan(scan); + + if (collides) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("replication origin with ID %u already exists", node_oid))); with: if (SearchSysCacheExists1(REPLORIGIDENT, ObjectIdGetDatum(node))) ereport(ERROR, errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("replication origin with ID %u already exists", node_oid)); 2.b) Similarly, Can we replace: + /* Check for name collision */ + ScanKeyInit(&key, + Anum_pg_replication_origin_roname, + BTEqualStrategyNumber, F_TEXTEQ, + roname_d); + scan =3D systable_beginscan(rel, ReplicationOriginNameIndex, + true /* indexOK */, + SnapshotSelf, + 1, &key); + collides =3D HeapTupleIsValid(systable_getnext(scan)); + systable_endscan(scan); + + if (collides) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("replication origin \"%s\" already exists", + originname))); with: if (SearchSysCacheExists1(REPLORIGNAME, roname_d)) ereport(ERROR, errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("replication origin \"%s\" already exists", originname)); This will make the code smaller and easy to read. Thoughts? Thanks, Shlok Kyal