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 1slazz-0005eX-KY for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Sep 2024 21:23:40 +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 1slazy-000Lqn-7Q for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Sep 2024 21:23:38 +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 1slazx-000Lqe-JI for pgsql-hackers@lists.postgresql.org; Tue, 03 Sep 2024 21:23:38 +0000 Received: from mail-oo1-xc2f.google.com ([2607:f8b0:4864:20::c2f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1slazv-0000yA-4W for pgsql-hackers@postgresql.org; Tue, 03 Sep 2024 21:23:37 +0000 Received: by mail-oo1-xc2f.google.com with SMTP id 006d021491bc7-5dfb53d4b13so2609625eaf.2 for ; Tue, 03 Sep 2024 14:23:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1725398612; x=1726003412; darn=postgresql.org; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=F9qh6IAjJF69HqkzLpOtbarEfpyj0kfldVT7ETSR3F0=; b=aJ5LjVwDQrtPEr+SFzdx0fagJdABFf0rywIPgnZMrhtHGqxuKibtNXvFlzjdi4wx0M okVP7lLyUknyWLpB3YOHUlo8SO19vAN8ywJnuYDWh8YoeBtxKnVR7STlGGGJNGBTRBA5 1JH/z6NysjRlNQJOhwQqr53IY4XwvklwvZetI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725398612; x=1726003412; h=user-agent:in-reply-to:content-transfer-encoding :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=F9qh6IAjJF69HqkzLpOtbarEfpyj0kfldVT7ETSR3F0=; b=FpHsqNtaB7H6jWYXEMF3Vt06DoBb73gz1V6JblXl8+4Pnwa0KPAxFoxR1dCz3q0O+E ECAdzCKCA8q9ZXMJ8xHGAhY6kYiutD9Bs+5c+K8MojG00gonbapf6EJE/Ysg8uxcfzWT 7YaJA4Sw/r4zhGE/kcaEgPitqfkdZZzOW35AS7LmS3JGziBo4pT2YLUjVj5rNfDX+o1B 8hj3w9kx5izhuMmp1+LvMsPui+FXPoeJBjqh9mFCrx00o3i0k5d8kcRbLzbZI4zCNtR5 t1O6K3UjvkQNCHQDYFbNqJzi2JTU73hqvkk3IzkLtt1bXIpzfSpM+STYSn45P44dcL5+ YoMw== X-Forwarded-Encrypted: i=1; AJvYcCX8qvUxgPpDFwhEba2UC7FB70jVjWYGRvtg297/bDZ6WTn0xmiaBNQ/URItXob48DEBAXDPDg5+483BooN2@postgresql.org X-Gm-Message-State: AOJu0YzsWZHXq5cDApp5h6z/JvzDgQLCXS/sZdtqrtdOIaTqLuZFbiRM xqZpT/01RTT/cqiMK55EPS+LcMQnLri+xM0RSgi2X5R9OwKHIH/MxkFYoA+i2Q== X-Google-Smtp-Source: AGHT+IEi9Y55hpfLmdtUjITUVvegD5gnu5RCpF7JGpI9Y4pngzPbF2k0clWSjjgQeG+gMmTbCuEcWg== X-Received: by 2002:a05:6870:b14d:b0:273:da6b:9a3d with SMTP id 586e51a60fabf-277ccc0ffddmr13635630fac.22.1725398612420; Tue, 03 Sep 2024 14:23:32 -0700 (PDT) Received: from google.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-70f7781ca5dsm1760977a34.18.2024.09.03.14.23.31 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Sep 2024 14:23:32 -0700 (PDT) Date: Tue, 3 Sep 2024 14:23:29 -0700 From: Noah Misch To: Nitin Motiani Cc: Heikki Linnakangas , Robert Haas , pgsql-hackers@postgresql.org, Tom Lane , Smolkin Grigory , Michael Paquier , Alexander Lakhin Subject: Re: race condition in pg_class Message-ID: <20240903212329.61.nmisch@google.com> References: <20240704220816.51.nmisch@google.com> <20240714174800.de.nmisch@google.com> <20240817040748.f8.nmisch@google.com> <63c27c17-0d8f-4ede-a624-3ee41d28b539@iki.fi> <20240822073200.4f.nmisch@google.com> <20240831011043.2b.nmisch@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Sep 03, 2024 at 09:24:52PM +0530, Nitin Motiani wrote: > On Sat, Aug 31, 2024 at 6:40 AM Noah Misch wrote: > > On Thu, Aug 29, 2024 at 09:08:43PM +0530, Nitin Motiani wrote: > > > On Thu, Aug 29, 2024 at 8:11 PM Noah Misch wrote: > > > > - In the cancel case, call both systable_inplace_update_cancel and > > > > systable_inplace_update_end. _finish or _cancel would own unlock, while > > > > _end would own systable_endscan(). > > > > > > > What happens to CacheInvalidateHeapTuple() in this approach? I think > > > it will still need to be brought to the genam.c layer if we are > > > releasing the lock in systable_inplace_update_finish. > understanding is that the code in this approach would look like below > : > if (dirty) > systable_inplace_update_finish(inplace_state, tup); > else > systable_inplace_update_cancel(inplace_state); > systable_inplace_update_end(inplace_state); > > And that in this structure, both _finish and _cancel will call > heap_inplace_unlock and then _end will call systable_endscan. So even > with this structure, the invalidation has to happen inside _finish > after the unlock. Right. > So this also pulls the invalidation to the genam.c > layer. Am I understanding this correctly? Compared to the v9 patch, the "call both" alternative would just move the systable_endscan() call to a new systable_inplace_update_end(). It wouldn't move anything across the genam:heapam boundary. systable_inplace_update_finish() would remain a thin wrapper around a heapam function. > > > > - Hoist the CacheInvalidateHeapTuple() up to the genam.c layer. While > > > > tolerable now, this gets less attractive after the inplace160 patch from > > > > https://postgr.es/m/flat/20240523000548.58.nmisch@google.com > > > > > > > I skimmed through the inplace160 patch. It wasn't clear to me why this > > > becomes less attractive with the patch. I see there is a new > > > CacheInvalidateHeapTupleInPlace but that looks like it would be called > > > while holding the lock. And then there is an > > > AcceptInvalidationMessages which can perhaps be moved to the genam.c > > > layer too. Is the concern that one invalidation call will be in the > > > heapam layer and the other will be in the genam layer? > > > > That, or a critical section would start in heapam.c, then end in genam.c. > > Current call tree at inplace160 v4: > How about this alternative? > > genam.c:systable_inplace_update_finish > PreInplace_Inval > START_CRIT_SECTION > heapam.c:heap_inplace_update > BUFFER_LOCK_UNLOCK > AtInplace_Inval > END_CRIT_SECTION > UnlockTuple > AcceptInvalidationMessages > Looking at inplace160, it seems that the start of the critical section > is right after PreInplace_Inval. So why not pull START_CRIT_SECTION > and END_CRIT_SECTION out to the genam.c layer? heap_inplace_update() has an elog(ERROR) that needs to happen outside any critical section. Since the condition for that elog deals with tuple header internals, it belongs at the heapam layer more than the systable layer. > Alternatively since > heap_inplace_update is commented as a subroutine of > systable_inplace_update_finish, should everything just be moved to the > genam.c layer? Although it looks like you already considered and > rejected this approach. Calling XLogInsert(RM_HEAP_ID) in genam.c would be a worse modularity violation than the one that led to the changes between v8 and v9. I think even calling CacheInvalidateHeapTuple() in genam.c would be a worse modularity violation than the one attributed to v8. Modularity would have the heap_inplace function resemble heap_update() handling of invals. > If the above alternatives are not possible, it's probably fine to go > ahead with the current patch with the function renamed to > heap_inplace_update_and_unlock (or something similar) as mentioned > earlier? I like that name. The next version will use it. > > > I see that all the places we check resultRelInfo->ri_needLockTagTuple, > > > we can just call > > > IsInplaceUpdateRelation(resultRelInfo->ri_RelationDesc). Is there a > > > big advantage of storing a separate bool field? Also there is another > > > > No, not a big advantage. I felt it was more in line with the typical style of > > src/backend/executor. > just find it a smell that there are two fields which are not > independent and they go out of sync. And that's why my preference is > to not have a dependent field unless there is a specific advantage. Got it. This check happens for every tuple of every UPDATE, so performance may be a factor. Some designs and their merits: ==== a. ri_needLockTagTuple Performance: best: check one value for nonzero Drawback: one more value lifecycle to understand Drawback: users of ResultRelInfo w/o InitResultRelInfo() could miss this ==== b. call IsInplaceUpdateRelation Performance: worst: two extern function calls, then compare against two values ==== c. make IsInplaceUpdateRelation() and IsInplaceUpdateOid() inline, and call Performance: high: compare against two values Drawback: unlike catalog.c peers Drawback: extensions that call these must recompile if these change ==== d. add IsInplaceUpdateRelationInline() and IsInplaceUpdateOidInline(), and call Performance: high: compare against two values Drawback: more symbols to understand Drawback: extensions might call these, reaching the drawback of (c) I think my preference order is (a), (c), (d), (b). How do you see it? > But even for the > ri_TrigDesc, CatalogOpenIndexes() still sets it to NULL. So shouldn't > ri_needLockTagTuple also be set to a default value of false? CatalogOpenIndexes() explicitly zero-initializes two fields and relies on makeNode() zeroing for dozens of others. Hence, omitting the initialization fits the function's local convention better than including it. (PostgreSQL has no policy or dominant practice about redundant zero-initialization.)