Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k6dWy-0005Ko-MB for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Aug 2020 17:30:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1k6dWx-0002fM-J8 for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Aug 2020 17:30:15 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k6dWx-0002fE-29 for pgsql-hackers@lists.postgresql.org; Fri, 14 Aug 2020 17:30:15 +0000 Received: from mail-qk1-x742.google.com ([2607:f8b0:4864:20::742]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1k6dWu-0004P1-6A for pgsql-hackers@lists.postgresql.org; Fri, 14 Aug 2020 17:30:14 +0000 Received: by mail-qk1-x742.google.com with SMTP id 77so9042342qkm.5 for ; Fri, 14 Aug 2020 10:30:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=CZDD0btnuRMOGgsXD20hi9f4Ad7DWVKJ6z5cGtm1axo=; b=dQwtrkD5Bl3iJ7CX4QPShPBp3tgyZxCxeOGbs0QFrzCG9LAO5vCA5qbOQxHZabF1hT VSArouT237w8rHNhwYywyw8QAqKdOYEmgHxb2hDJVa+4rM8k0VS384da7JuTeIezQ2bv SO4OJ//74AHw4nnJJRIKitmAwQZNi1LqiITa+CMZyXhNsx8Ysg/z/ESHm1ZqlRNS1LLZ LCix2K2X11oggua4XeM1heVqaKFInhqj5ZrmQjfPvLhvh1y/SVRfgR+mIinAHq2o8Sok 0gp3g//U856SsRgsplPkf0ztMwcLn1fQhe4ElVY0yFkcZU8VgDpJ0nWD15Bg9nADS0oC ypBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=CZDD0btnuRMOGgsXD20hi9f4Ad7DWVKJ6z5cGtm1axo=; b=LdkvX8Fhy8joG1jabN1Xhw8DruM70o50XiGJc/0C9JOXnhY08mviy2worQbrIrSnvv nyDypt+fJtgX+bHRotwoZgVgPm6UP6AZQeaTtrvjyELd480r8DvRdVvChGYTFB+CZjx+ IPJA+sOu6nk41GHu61Y/sweMy6zarjzT3iyDZysoQzM/5J8jr25+NseeCQ7jWd6JnqLa d2Pn24M6t+U7Yj2m/UVmyc24PovfqzmrXiB5qHyh0v6ZNnceWeZlkcTU/4X9dmKj2hzc 8ZKtozlqpyunYubnOwS7/kmRpfUbnGg26s1Z9Y9wqrhgxof8xtj+2toTbf35ITZJZyWx BHgw== X-Gm-Message-State: AOAM530w+/ppBMPg/O1/6HhLcZALELC57x6DXTHqQBqQtI18YurRpntN RSDIMogplyKMTaJWxosHoCwnjdjtRBpsx3RpNBZ9hNbFtNhPYPYKUO3nR0h5ObEmnwB422WyOjZ Cq1qYD6hbpBH1xN5JjvNXSagzfPO14nAs/Ppbf9cO/VER5s47ZtMUejYDfUFjMRxjyigbxgrDSI QqgdpdwA5pAHIROHgI X-Google-Smtp-Source: ABdhPJwlE1DwCwzCSdyPY6VVmVwFSRGvZCXeTjxSRH/DM8O/5uhQ0U2qHcP7ILZnm5MnHtsxt1wWRA== X-Received: by 2002:a37:385:: with SMTP id 127mr2795088qkd.3.1597426210586; Fri, 14 Aug 2020 10:30:10 -0700 (PDT) Received: from perhan.alvh.no-ip.org ([190.95.19.47]) by smtp.gmail.com with ESMTPSA id f189sm9126413qke.15.2020.08.14.10.30.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Aug 2020 10:30:09 -0700 (PDT) Received: by perhan.alvh.no-ip.org (Postfix, from userid 1000) id 12E352A151C; Fri, 14 Aug 2020 13:30:08 -0400 (-04) Date: Fri, 14 Aug 2020 13:30:08 -0400 From: Alvaro Herrera To: Tom Lane Cc: pgsql-hackers@lists.postgresql.org Subject: Re: Dependencies for partitioned indexes are still a mess Message-ID: <20200814173008.GA21298@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="azLHFNyN32YCQGCU" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20200812224828.GA3888@alvherre.pgsql> User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --azLHFNyN32YCQGCU Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2020-Aug-12, Alvaro Herrera wrote: > Hmm, we do make the FK constraint depend on the ATTACH for the direct > children; what I think we're lacking is dependencies on descendants > twice-removed (?) or higher. This mock patch seems to fix this problem > by adding dependencies recursively on all children of the index; I no > longer see this problem with it. After going over this some more, this analysis seems correct. Here's a better version of the patch which seems final to me. I'm not yet clear on whether the noisy DROP INDEX is an actual bug that needs to be fixed, or instead it needs to be left alone. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --azLHFNyN32YCQGCU Content-Type: text/x-diff; charset=iso-8859-1 Content-Disposition: attachment; filename="v2-0001-pg_dump-fix-dependencies-on-FKs-to-multi-level-pa.patch" Content-Transfer-Encoding: 8bit From 07d8af1885edafbd670efc52faa15824787a1dc2 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 14 Aug 2020 13:26:20 -0400 Subject: [PATCH v2] pg_dump: fix dependencies on FKs to multi-level partitioned tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parallel-restoring a foreign key that references a partitioned table with several levels of partitions can fail: pg_restore: while PROCESSING TOC: pg_restore: from TOC entry 6684; 2606 29166 FK CONSTRAINT fk fk_a_fkey postgres pg_restore: error: could not execute query: ERROR: there is no unique constraint matching given keys for referenced table "pk" Command was: ALTER TABLE fkpart3.fk ADD CONSTRAINT fk_a_fkey FOREIGN KEY (a) REFERENCES fkpart3.pk(a); This happens in parallel restore mode because some index partitions aren't yet attached to the topmost partitioned index that the FK uses, and so the index is still invalid. The current code marks the FK as dependent on the first level of index-attach dump objects; the bug is fixed by recursively marking the FK on their children. Reported-by: Tom Lane Author: Álvaro Herrera Discussion: https://postgr.es/m/3170626.1594842723@sss.pgh.pa.us --- src/bin/pg_dump/pg_dump.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 9c8436dde6..2cb3f9b083 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -235,6 +235,7 @@ static DumpableObject *createBoundaryObjects(void); static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs, DumpableObject *boundaryObjs); +static void addConstrChildIdxDeps(DumpableObject *dobj, IndxInfo *refidx); static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo); static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind); static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo); @@ -7517,25 +7518,20 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) reftable = findTableByOid(constrinfo[j].confrelid); if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE) { - IndxInfo *refidx; Oid indexOid = atooid(PQgetvalue(res, j, i_conindid)); if (indexOid != InvalidOid) { for (int k = 0; k < reftable->numIndexes; k++) { - SimplePtrListCell *cell; + IndxInfo *refidx; /* not our index? */ if (reftable->indexes[k].dobj.catId.oid != indexOid) continue; refidx = &reftable->indexes[k]; - for (cell = refidx->partattaches.head; cell; - cell = cell->next) - addObjectDependency(&constrinfo[j].dobj, - ((DumpableObject *) - cell->ptr)->dumpId); + addConstrChildIdxDeps(&constrinfo[j].dobj, refidx); break; } } @@ -7548,6 +7544,35 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) destroyPQExpBuffer(query); } +/* + * addConstrChildIdxDeps + * + * Recursive subroutine for getConstraints + * + * Given an object representing a foreign key constraint and an index on the + * partitioned table it references, mark the constraint object as dependent + * on the DO_INDEX_ATTACH object of each index partition, recursively + * drilling down to their partitions if any. This ensures that the FK is not + * restored until the index is fully marked valid. + */ +static void +addConstrChildIdxDeps(DumpableObject *dobj, IndxInfo *refidx) +{ + SimplePtrListCell *cell; + + Assert(dobj->objType == DO_FK_CONSTRAINT); + + for (cell = refidx->partattaches.head; cell; cell = cell->next) + { + IndexAttachInfo *attach = (IndexAttachInfo *) cell->ptr; + + addObjectDependency(dobj, attach->dobj.dumpId); + + if (attach->partitionIdx->partattaches.head != NULL) + addConstrChildIdxDeps(dobj, attach->partitionIdx); + } +} + /* * getDomainConstraints * -- 2.20.1 --azLHFNyN32YCQGCU--