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.94.2) (envelope-from ) id 1stBAw-00E9xn-GS for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Sep 2024 19:26:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1stBAv-00Chx0-6V for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Sep 2024 19:26:17 +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.94.2) (envelope-from ) id 1stBAu-00Chw5-P6 for pgsql-hackers@lists.postgresql.org; Tue, 24 Sep 2024 19:26:16 +0000 Received: from mail-io1-xd32.google.com ([2607:f8b0:4864:20::d32]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1stBAq-000tFx-ES for pgsql-hackers@lists.postgresql.org; Tue, 24 Sep 2024 19:26:16 +0000 Received: by mail-io1-xd32.google.com with SMTP id ca18e2360f4ac-82cf3286261so220620939f.0 for ; Tue, 24 Sep 2024 12:26:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727205971; x=1727810771; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=sb21uaSVegwcZsKVzyeGOAsiuIZc+pJfkRSY7tfDrdA=; b=Cyp5p7bs5Q3zbEFxRYF99/wpK4JTociq7VeqgmefXrH3T11yuUiqvJAJHcnAuuVli5 mzHOvgKagPfco5V4Fbmw4gV19lWuiK0bqj2JfQW7Q+WM6sLqAc1aLOyHVeFpIHSVVOG6 kdkg14wlapJeIaKMrRJrd6kEpXA2f+WcPbDUBoKj0m8Vs+lNhHu/yFWBJrukBwC3Y/50 gV1wV4RjFv1E5SpMyG2ip3eOZyV3CtoXsTY7Iw2ffQrfis7qsj8o/17cwaqyzEuAJnq3 6saqcEjkgZjC5fgSNmBmbvGG1CRhFXQ9lShGrW7mL+mzEzb0lJZXaOv8HXSHzPOtYMFF VREA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727205971; x=1727810771; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=sb21uaSVegwcZsKVzyeGOAsiuIZc+pJfkRSY7tfDrdA=; b=jRSJk/j4B8mPjdNytKJAwzGbLoVOgi5ujvSLTOjETTcy8VYwZdwVz+WcMoYX94rkWl oOD3ojHK+Ytaa2S6BZfVn9b9fbLKFtJ44UTAKFcTuJT32iHBkVLURd+Wlz2XnYdcMIg8 K/Jk6dPzwtkq+3319g3PWaO7g2IDbwEI2azNOvfIivnBsU7aVNiZST86pzjW09LOKY5P +wVCzJXMD+NWttqLE8k6GlG0Y+jEGPX/yDrt8buN/o8R0E0Gl6l7p17OspEPJ9Kg0YKU gfMZ/vXXi4Km2n07KvMarKQaIHoSrkKsULcpXmyEUwE18AcB86FVl3DoV14Xx+ovtfsF U2pQ== X-Forwarded-Encrypted: i=1; AJvYcCV42Q4xfgdjVpwClNMI7g4IODcwpWasdn+/MGmwU4vCqmXLlnEwqBQhx5/0sm0HwW3306Yvnnt2fTXpeADC@lists.postgresql.org X-Gm-Message-State: AOJu0Yzi0Sjp4U0nOdwfMhU9FS0lObBxNQ1ll2kreFRf/ueVpX+53zQB FfG35zMWgqHRt5vsxAigy8gRylSW7LXfEykw7OP9NFMzngbvPzDP X-Google-Smtp-Source: AGHT+IGZBSu2L55I1yjbdCRKKaEL1/cDJz1doxyWB547zrEKEPhDeoi00elLCwLCWfcORuECbz8dhw== X-Received: by 2002:a05:6602:4989:b0:832:13ce:1fad with SMTP id ca18e2360f4ac-83247d2611amr69895339f.8.1727205971508; Tue, 24 Sep 2024 12:26:11 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4d40f12e783sm581090173.56.2024.09.24.12.26.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 12:26:10 -0700 (PDT) Date: Tue, 24 Sep 2024 14:26:08 -0500 From: Nathan Bossart To: Michael Paquier Cc: Alexander Lakhin , Tom Lane , "Jonathan S. Katz" , PostgreSQL Hackers Subject: Re: Large expressions in indexes can't be stored (non-TOASTable) Message-ID: References: <1812111.1726671296@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="yI10avGgeeovfWvh" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --yI10avGgeeovfWvh Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Sep 24, 2024 at 01:21:45PM +0900, Michael Paquier wrote: > On Mon, Sep 23, 2024 at 10:50:21AM -0500, Nathan Bossart wrote: >> I carefully inspected all the code paths this patch touches, and I think >> I've got all the details right, but I would be grateful if someone else >> could take a look. > > No objections from here with putting the snapshots pops and pushes > outside the inner routines of reindex/drop concurrently, meaning that > ReindexRelationConcurrently(), DefineIndex() and index_drop() are fine > to do these operations. Great. I plan to push 0001 shortly. > Actually, thinking more... Could it be better to have some more > sanity checks in the stack outside the toast code for catalogs with > toast tables? For example, I could imagine adding a check in > CatalogTupleUpdate() so as all catalog accessed that have a toast > relation require an active snapshot. That would make checks more > aggressive, because we would not need any toast data in a catalog to > make sure that there is a snapshot set. This strikes me as something > we could do better to improve the detection of failures like the one > reported by Alexander when updating catalog tuples as this can be > triggered each time we do a CatalogTupleUpdate() when dirtying a > catalog tuple. The idea is then to have something before the > HaveRegisteredOrActiveSnapshot() in the toast internals, for catalogs, > and we would not require toast data to detect problems. I gave this a try and, unsurprisingly, found a bunch of other problems. I hastily hacked together the attached patch that should fix all of them, but I'd still like to comb through the code a bit more. The three catalogs with problems are pg_replication_origin, pg_subscription, and pg_constraint. pg_contraint has had a TOAST table for a while, and I don't think it's unheard of for conbin to be large, so this one is probably worth fixing. pg_subscription hasn't had its TOAST table for quite as long, but presumably subpublications could be large enough to require out-of-line storage. pg_replication_origin, however, only has one varlena column: roname. Three out of the seven problem areas involve pg_replication_origin, but AFAICT that'd only ever be a problem if the name of your replication origin requires out-of-line storage. So... maybe we should just remove pg_replication_origin's TOAST table instead... -- nathan --yI10avGgeeovfWvh Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="toast_snapshot.patch" diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index d0d1abda58..b8be124555 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -22,6 +22,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "executor/executor.h" +#include "miscadmin.h" #include "utils/rel.h" @@ -234,6 +235,14 @@ CatalogTupleInsert(Relation heapRel, HeapTuple tup) { CatalogIndexState indstate; + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + CatalogTupleCheckConstraints(heapRel, tup); indstate = CatalogOpenIndexes(heapRel); @@ -256,6 +265,14 @@ void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate) { + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + CatalogTupleCheckConstraints(heapRel, tup); simple_heap_insert(heapRel, tup); @@ -273,6 +290,14 @@ void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate) { + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + /* Nothing to do */ if (ntuples <= 0) return; @@ -315,6 +340,14 @@ CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup) CatalogIndexState indstate; TU_UpdateIndexes updateIndexes = TU_All; + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + CatalogTupleCheckConstraints(heapRel, tup); indstate = CatalogOpenIndexes(heapRel); @@ -339,6 +372,14 @@ CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup, { TU_UpdateIndexes updateIndexes = TU_All; + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + CatalogTupleCheckConstraints(heapRel, tup); simple_heap_update(heapRel, otid, tup, &updateIndexes); @@ -364,5 +405,13 @@ CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup, void CatalogTupleDelete(Relation heapRel, ItemPointer tid) { + /* + * If we might need TOAST access, make sure the caller has set up a valid + * snapshot. + */ + Assert(HaveRegisteredOrActiveSnapshot() || + !OidIsValid(heapRel->rd_rel->reltoastrelid) || + !IsNormalProcessingMode()); + simple_heap_delete(heapRel, tid); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d27e6cf345..06ac1d39d2 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -19292,9 +19292,17 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, tab->rel = rel; } + if (concurrent) + PushActiveSnapshot(GetTransactionSnapshot()); + else + Assert(HaveRegisteredOrActiveSnapshot()); + /* Do the final part of detaching */ DetachPartitionFinalize(rel, partRel, concurrent, defaultPartOid); + if (concurrent) + PopActiveSnapshot(); + ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel)); /* keep our lock until commit */ diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index e03e761392..ed7d187bfe 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -377,6 +377,8 @@ process_syncing_tables_for_sync(XLogRecPtr current_lsn) replorigin_session_origin_lsn = InvalidXLogRecPtr; replorigin_session_origin_timestamp = 0; + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Drop the tablesync's origin tracking if exists. * @@ -387,6 +389,8 @@ process_syncing_tables_for_sync(XLogRecPtr current_lsn) */ replorigin_drop_by_name(originname, true, false); + PopActiveSnapshot(); + finish_sync_worker(); } else @@ -483,6 +487,8 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) started_tx = true; } + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Remove the tablesync origin tracking if exists. * @@ -500,6 +506,8 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) sizeof(originname)); replorigin_drop_by_name(originname, true, false); + PopActiveSnapshot(); + /* * Update the state to READY only after the origin cleanup. */ @@ -1456,7 +1464,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos) * logged for the purpose of recovery. Locks are to prevent the * replication origin from vanishing while advancing. */ + PushActiveSnapshot(GetTransactionSnapshot()); originid = replorigin_create(originname); + PopActiveSnapshot(); LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock); replorigin_advance(originid, *origin_startpos, InvalidXLogRecPtr, diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 925dff9cc4..502033f3d8 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -4604,8 +4604,10 @@ run_apply_worker() walrcv_startstreaming(LogRepWorkerWalRcvConn, &options); StartTransactionCommand(); + PushActiveSnapshot(GetTransactionSnapshot()); UpdateTwoPhaseState(MySubscription->oid, LOGICALREP_TWOPHASE_STATE_ENABLED); MySubscription->twophasestate = LOGICALREP_TWOPHASE_STATE_ENABLED; + PopActiveSnapshot(); CommitTransactionCommand(); } else @@ -4821,7 +4823,9 @@ DisableSubscriptionAndExit(void) /* Disable the subscription */ StartTransactionCommand(); + PushActiveSnapshot(GetTransactionSnapshot()); DisableSubscription(MySubscription->oid); + PopActiveSnapshot(); CommitTransactionCommand(); /* Ensure we remove no-longer-useful entry for worker's start time */ @@ -4925,6 +4929,8 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) started_tx = true; } + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Protect subskiplsn of pg_subscription from being concurrently updated * while clearing it. @@ -4983,6 +4989,8 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) heap_freetuple(tup); table_close(rel, NoLock); + PopActiveSnapshot(); + if (started_tx) CommitTransactionCommand(); } --yI10avGgeeovfWvh--