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 1wWugr-002wHH-1T for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Jun 2026 11:32:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wWugq-0073HI-16 for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Jun 2026 11:32:16 +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 1wWugq-0073HA-02 for pgsql-hackers@lists.postgresql.org; Tue, 09 Jun 2026 11:32:16 +0000 Received: from mail-oi1-x233.google.com ([2607:f8b0:4864:20::233]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wWugn-000000028w5-3ZdS for pgsql-hackers@lists.postgresql.org; Tue, 09 Jun 2026 11:32:15 +0000 Received: by mail-oi1-x233.google.com with SMTP id 5614622812f47-486b93fc7c8so1144361b6e.3 for ; Tue, 09 Jun 2026 04:32:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1781004732; cv=none; d=google.com; s=arc-20240605; b=i9cxrg3p6RDEnyIHW2U2HMrkO1Elwm8yHgjpyRXSMB4MJPrOfPuPRO4rvgp5u8//kN 3vUjmuR2zI0rpXAMQ05xuDEdCHpOt1Z84pWYCrYJM2yIGwc/RxCcrn+QJpefIF0Zrxcu WPuw6wXD8COJVKe+wfN7T2H2Qmw4sMGmelm+bUNXGQQIdSP46VcJZRbve83UeNWJXSZs Bw5Sx8A9xfhiPh1l6cKVFCep0kBJkvk6V/48IsAQlExj5+VYA38rptfl3k1nULSiJpcl k8rGWoKdwX5U3diUCgsaWst+j7M8Y2SUmMwIRagCZVnucMmo67tbFMxXA3EFL05IOCc5 VSEA== 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=WVDQq2gDZuhtxt08q00FUHkHGTWcIk4kTuMHImSfPz8=; fh=us3OHwggLkG0CtBUZMlNaaOu9UR+qD+dYnPsjY4UpyE=; b=BhD1KVBj56pBb2iZs0DUZz67kB/Y1OI6oK2qXFjK4mnZBW/1UCvKN8duZo2uWeiZJK W6z1NQj+rAsIvBGl3lb2Gncn9EdLGn97zYSH9kmlh2nJUzqFN+79JnQrzAJLXw44Jral e/2OiPznL5Npn38p6oIxgtvZEwdlba4e5BOI85V41uk8bPtE/zotl+KYJYUmk6+0Ali1 i+W0h3g6rGItilLJdFTmmlh/yqkHKpaylOZZa/vNZKZ/iNRA2OnYxR54MSN5Z2805ztr gHoVRMRpvSei4YUjtzo2LucCaiL47WKdh0zBX1yhy1/Mu7lwaxc5nKtEe9PjqdeBDbjk D2BA==; 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=1781004732; x=1781609532; 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=WVDQq2gDZuhtxt08q00FUHkHGTWcIk4kTuMHImSfPz8=; b=eQ1C3eLEqxFoXTKjflk2G8NIQHx2m454eeK0Kv93SkryGgilZwmZ+NAYDCPBYve7xk 3qHmq/qVK7klTSvUVTBIt30VhkycSzwLiKmmi3GuO232AtxsdwHabwUzSSawpSIbGW5I onxrIzcCuw1R+HcmUigPXPmom87MVyV5dbNjv0VuIjXoTZjJ3mszMwCB5saFXiLfBVnv G+BQ2c8n6aNMrQ5loUkLWN1VnrvO9VPURvT7ijjpYFZwSSH8rTQVblOoPcRhhY8icXJ1 zhpw5sAcU6Fk8NqHuROyQPiNUuA0Y76gGY51LXFSb5b3OP2UbSZm0kM2OD5OZhx9NrhX DYmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781004732; x=1781609532; 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=WVDQq2gDZuhtxt08q00FUHkHGTWcIk4kTuMHImSfPz8=; b=FNj86X7/a8eTtaFRA6RaPvIhx9BhWREbWh2l/eF33oWZ3lD6GeIVwsRf8Hls9Ibf4t +RWytj+Y86nptRkmsi4b8UlePBhNiq2/GX9/v6eXW9A0gkE/n2sDyjzkqAvuPBXhD3dG KwLSVihuO53SAa0aOOuJOCHfrhN48rZtcBUobw15It2SqVof0uNF6ZU5Wyn1TwRfLqIv Tf0JUmArdCl5y4VKqv1qBOzqd1g1A5m1lBXyqsUnRmDM9JkosXQtS/pAWnTCacem1XwQ qMM251nic+c68hv9ilIZaRlJVIi4BV/zXRCl0Ut+GFJGACCaX8dfl1EBwGriZoQuXmnr 3AQg== X-Forwarded-Encrypted: i=1; AFNElJ+LJBCwgOt10L+hzNBO1HzTYqrJHfYmoccuP6ZIs6lpK6rckvbrXjTlneADuSDsp+D5yItQvHc0xUD2Hffx@lists.postgresql.org X-Gm-Message-State: AOJu0YwKN12L4Nj0/hOb1M51swJZpdy8vnJLTvZVJypFLhnhZj+E8VLo sXcO0UkudL+adwsH7HaYEO4YY/jvWu81MeXBCvAoFFJ7aB+Yzh3RdaZjXGPWsx+AXfscasR0rRw 23IvgYN1cOU8KMIL9Sl4p/OSeGRxw7sc= X-Gm-Gg: Acq92OFaUoS1sp+ixL+zuZIqto/+kMDW19+TnlI7biU8czLzsdwfJroyk8/f2JeDl5R fG/wLogikNoZjHBVvQJq2ck4Z80NOzVI0rtXgFRfD1avBxs+9S/OkHfKk0vVO6CAIQm5OM8n3H2 yFxL+PiN23IQrdI8xt3cab8zk0ym8qbZ7a4B9x4orlxVtADGTc4hrc7FUbmvT9FeyOg6dIOVfT7 GHWl+TdujHxdRXSnEioCudYCvcBvdmzN1RlZ4vFGYrIiiASXoeOYa6E8NKhNwB38ht6fi6o3fJN 7rJlDokJlBwtVZSvsA== X-Received: by 2002:a05:6808:1b25:b0:46e:df55:23fa with SMTP id 5614622812f47-4868dc82534mr10870864b6e.17.1781004731901; Tue, 09 Jun 2026 04:32:11 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Shlok Kyal Date: Tue, 9 Jun 2026 17:02:00 +0530 X-Gm-Features: AVVi8Cf2VL7f5CRb5YkaZpf9nOjVVe1eti1BfZtlGA79UWPXniim8HK9RXtaZFQ 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 Mon, 8 Jun 2026 at 22:36, Shlok Kyal wrote: > > 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 p= atch: > >> > > >> > 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, upgradin= g > >> > the cluster can error out. > >> > > >> > Example: > >> > We set up a logical replication between publisher node and subscribe= r 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_n= ew > >> > node, we get an error: > >> > ``` > >> > SELECT pg_catalog.binary_upgrade_create_replication_origin('1'::pg_c= atalog.oid, > >> > 'pg_16393'::pg_catalog.name, '0/01743078'::pg_catalog.pg_lsn); > >> > psql:subscriber_new/pg_upgrade_output.d/20260522T140312.807/dump/pg_= upgrade_dump_globals.sql:37: > >> > ERROR: replication origin with ID 1 already exists > >> > ``` > >> > > >> > This error occurs in "Performing Upgrade" stage. Should we add a che= ck > >> > in the "Performing Consistency Checks" stage so that we don't need t= o > >> > 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 i= f > >> > 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 cl= uster 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 du= ring upgrades; prior to that, these were not migrated. Given that change, i= t also makes sense to migrate replication origins from them. Otherwise, whe= n upgrading from PG17 to a later version, you could end up with a subscript= ion where pg_subscription_rel and the remote LSN are migrated, but the corr= esponding 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_n= ame_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_th= e_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_th= e_li > >> > >> thanks > >> Shveta > > > > > > Fixed this. Now binary_upgrade_create_replication_origin handles it si= milarly to the way pg_replication_origin_create handles the name of the ori= gin. > > > > 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" expec= ted? > > 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? > One more comment: 3. In logical-replication.sgml, we have documentation as: "Commit timestamps and origin data are not preserved during the upgrade." Now since the origin related data is preserved after the upgrade, should we update the documentation here? Thanks, Shlok Kyal