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 1t2YiL-004xQZ-Sy for pgsql-general@arkaria.postgresql.org; Sun, 20 Oct 2024 16:23:34 +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 1t2YiK-00GtgC-4f for pgsql-general@arkaria.postgresql.org; Sun, 20 Oct 2024 16:23:32 +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.94.2) (envelope-from ) id 1t2YiI-00Gtft-EA for pgsql-general@lists.postgresql.org; Sun, 20 Oct 2024 16:23:32 +0000 Received: from fhigh-a3-smtp.messagingengine.com ([103.168.172.154]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t2YiB-001ri7-CN for pgsql-general@lists.postgresql.org; Sun, 20 Oct 2024 16:23:29 +0000 Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfhigh.phl.internal (Postfix) with ESMTP id ACA61114017C; Sun, 20 Oct 2024 12:23:21 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-01.internal (MEProxy); Sun, 20 Oct 2024 12:23:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= cc:content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm2; t=1729441401; x=1729527801; bh=LhmuQEt52oHxM8FBYwTM9jiUTU3RzYPEOOVUJ0+xjHw=; b= JA67cMsuh+Wrf55rVz6Km3zyA6Gyi6s0P18ESLgI3izb03nStZKduM5qTouJPqgt rtuOR3pSu9d9s6ma3H6qSsygsG5PAew2qyb6ZrY50ZI3dt1DzmINl0J3v84VOR8m UBQiQAfBtJE2FGumVUH/oS5f7BJmpm9K570CKajvVJ2FlapJ0v1RPPqIeWsL6bMJ bmLCFreIynOD3/BzslcJsW2Lq2vW8BgOusk5BfTa3WEHbEk9h5gF+3S20M6s0ho8 BslurKQ80WQGD0QlS1Hx18kFnsMcnjdriLd110l87zQR+2cL1RUSY72QdtpMP6cD puBblElZ9364M7DW2vvvTA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1729441401; x= 1729527801; bh=LhmuQEt52oHxM8FBYwTM9jiUTU3RzYPEOOVUJ0+xjHw=; b=G 6f1uPDxHg3b6J3he32zPEe6voI3cXwMnWYPw401OYifaQ+awnAM8x56tUrSx865S XoX/NX7WlP06Z1oK2xjRp59nfZWpZjT8QUY8RNoD2Qsnk9rAzSFxzuDk4jhiv2a9 0wT9jHQBLoVTJ7jJKk55DN72kNnvojo9JLNQx3ne5ThiiutygBpjqe/CIwUbkrL7 eYtfPW/w3LA6HqRTQz5L11h+zj//yfzz1zOc7WDU8UFjwIgH/9rL5WConexcu4Jy DGG1O0HH6+NXDDshFr1/Ctct1FtP7UPROTeood1G8WDWkFy1+groYNUI8Kcn5z3P BV/vXM9Zf5GxJmxNGI6zQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrvdehjedgleelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpefkffggfg fuvfhfhfgjtgfgsehtkeertddtvdejnecuhfhrohhmpeetughrihgrnhcumfhlrghvvghr uceorggurhhirghnrdhklhgrvhgvrhesrghklhgrvhgvrhdrtghomheqnecuggftrfgrth htvghrnhepleegveekkeekueeigfdtveeileeuhfefudefteekjeffkeejueejheegheeg kedtnecuffhomhgrihhnpehpohhsthhgrhgvshhqlhdrohhrghenucevlhhushhtvghruf hiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrughrihgrnhdrkhhlrghvvghr segrkhhlrghvvghrrdgtohhmpdhnsggprhgtphhtthhopedvpdhmohguvgepshhmthhpoh huthdprhgtphhtthhopehushgvrhesphhiughurdguvghvpdhrtghpthhtohepphhgshhq lhdqghgvnhgvrhgrlheslhhishhtshdrphhoshhtghhrvghsqhhlrdhorhhg X-ME-Proxy: Feedback-ID: i76984098:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 20 Oct 2024 12:23:20 -0400 (EDT) Message-ID: <254c31c2-ff15-4720-a4fc-f0969d677d72@aklaver.com> Date: Sun, 20 Oct 2024 09:23:19 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Postgres attach partition: AccessExclusive lock set on different tables depending on how attaching is performed To: user@pidu.dev, pgsql-general@lists.postgresql.org References: Content-Language: en-US From: Adrian Klaver In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 10/20/24 04:31, user wrote: > Hello, > I was reading all the tips that could make the attach partition > operation seamless. > https://www.postgresql.org/docs/current/ddl-partitioning.html > There is > a mention about check constraint that could be places before the attach > process. But to minimise the time when AccessExclusive lock is held on > my table, I wanted to push it further and also add indexes and foreign > keys BEFORE the attach command is invoked. > And here is a problem. When I run the attach command without foreign > keys being present beforehand on a table, there is only AccessExclusive > lock on a table I attach partition to. > BUT if my table to-be-attached has a foreign key constraint already, > then the referenced table will get the ExclusiveLock! I do not > understand why is it needed, the constraint already exists... > > The reproduction: ( Postgres Version 14 ) > > CREATE TABLE refs ( >                     id integer primary key, >                     did integer >                 ); > CREATE TABLE films ( >                     id integer, >                     code char(5) , >                     title varchar(40) NOT NULL, >                     did integer NOT NULL references refs(id) >                     ) >                     partition by list (code); > > insert into refs values (5, 5) > create table films_partition (LIKE films INCLUDING ALL) > case 1: films_partition does not have a foreign key added before the attach > BEGIN; > insert into films_partition values (1, 'dr', 'musician',5) > alter table films_partition add constraint check_code check (code = 'dr'); > ALTER TABLE films ATTACH PARTITION films_partition for values in ('dr') > keep the transaction running... > > check the locks: > > select relname, mode >                 from pg_locks l >                     join pg_class c on (relation = c.oid) >                     join pg_namespace nsp on (c.relnamespace = nsp.oid); > films relname, ShareUpdateExclusiveLock mode > films_partition relname, AccessShareLock mode > films_partition relname, RowExclusiveLock mode > films_partition relname, ShareRowExclusiveLock mode > films_partition relname, AccessExclusiveLock mode > refs relname, AccessShareLock mode > refs relname, RowShareLock mode > refs relname, ShareRowExclusiveLock mode > > No AccessExclusive lock on "refs" table! > > case 2: films_partition does have the foreign key contrain >  BEGIN; > insert into films_partition values (1, 'dr', 'musician',5) > alter table films_partition add constraint check_code check (code = 'dr'); > alter table films_partition ADD CONSTRAINT fk_did FOREIGN KEY (did) > REFERENCES refs (id); > ALTER TABLE films ATTACH PARTITION films_partition for values in ('dr') > keep the transaction running... > > check the locks: > > films relname, ShareUpdateExclusiveLock mode > films_partition relname, AccessShareLock mode > films_partition relname, RowExclusiveLock mode > films_partition relname, ShareRowExclusiveLock mode > films_partition relname, AccessExclusiveLock mode > refs relname, AccessShareLock mode > refs relname, RowShareLock mode > refs relname, ShareRowExclusiveLock mode > refs relname, AccessExclusiveLock mode > > There is AccessExclusiveLock on "refs" table! > > Conclusion > I really don't want the "attach partition" to take too much time, so I > want to have all the constraints added before it is run. And indeed, the > time is reduced. But this additional lock now increases the chance of > deadlocks, as AccessExclusive locks are grabbed on many tables > referenced by foreing keys. Is there anything I can do better? Whi is it > that attach_partition adds a foreign key without additional > AccessExclusive lock, https://www.postgresql.org/docs/current/sql-altertable.html ATTACH PARTITION [...] "Currently FOREIGN KEY constraints are not considered. " but this lock is required when the constrint > already exists? Because I am pretty sure it is due to this statement: alter table films_partition ADD CONSTRAINT fk_did FOREIGN KEY (did) REFERENCES refs (id); Try: BEGIN; insert into films_partition values (1, 'dr', 'musician',5) alter table films_partition add constraint check_code check (code = 'dr'); alter table films_partition ADD CONSTRAINT fk_did FOREIGN KEY (did) REFERENCES refs (id); COMMIT; Then: ALTER TABLE films ATTACH PARTITION films_partition for values in ('dr') Also from https://www.postgresql.org/docs/current/sql-altertable.html Take a look at: ADD table_constraint [ NOT VALID ] ... "Normally, this form will cause a scan of the table to verify that all existing rows in the table satisfy the new constraint. But if the NOT VALID option is used, this potentially-lengthy scan is skipped. The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a matching row in the referenced table, in the case of foreign keys, or they'll fail unless the new row matches the specified check condition). But the database will not assume that the constraint holds for all rows in the table, until it is validated by using the VALIDATE CONSTRAINT option. See Notes below for more information about using the NOT VALID option." > > Regards! > > -- Adrian Klaver adrian.klaver@aklaver.com