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 1t6bMd-00E8dK-DX for pgsql-hackers@arkaria.postgresql.org; Thu, 31 Oct 2024 20:01:51 +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 1t6bMb-005aKg-NX for pgsql-hackers@arkaria.postgresql.org; Thu, 31 Oct 2024 20:01:50 +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 1t6bMb-005aKY-4b for pgsql-hackers@lists.postgresql.org; Thu, 31 Oct 2024 20:01:49 +0000 Received: from mail-oo1-xc34.google.com ([2607:f8b0:4864:20::c34]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1t6bMY-0043Xb-3u for pgsql-hackers@postgresql.org; Thu, 31 Oct 2024 20:01:48 +0000 Received: by mail-oo1-xc34.google.com with SMTP id 006d021491bc7-5ebc9bda8c8so674971eaf.0 for ; Thu, 31 Oct 2024 13:01:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1730404904; x=1731009704; 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=cUmHovZu3M5e/RHCQMBJQeLEwBoxJ7Brm+G0hvVMHJo=; b=eiStXz96HAA2e3oTy57WrVNZpy9MJmvMDOVoy/WKk/WllnReZ4l940+PiveZM66ZB4 ZRzg1iGThlL7TP1w7tccZZWIBLwx4z0h8jZgA3mlVYyabO8ieTvyTtIWpp7z5yGVvgNy niR8/u/XsOsET8BDIxluLbylldJGiiCwkG+Xg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730404904; x=1731009704; 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=cUmHovZu3M5e/RHCQMBJQeLEwBoxJ7Brm+G0hvVMHJo=; b=MjQDebzZZiHBNk2Ar0+vUC8OWh1CFEep3xWP5ansHrQoRCgzZ6QigcC1NQeCau9R1J ji0G598FD8aL7wa1/HYbY6LtnTHrES50UOt290GyaW1kumNjDn6T9y2uSTvbTbrGnse/ KUStMk9guORrHkrR25mH2TGeH+/QSncAzxqPWO2Kgp2rTVm8DX/JUU3wFJlg1dr/oE0g pB5bI28OwHYByKgMCZ8AgP0WxMkvF9yY9e5wD+j52iYD9jitVV2q9lHdW6kMmOKcfsZ7 Erv5XGnOjBoPzcK6SCjmjbi9keotk4oUa99Yq7kwrcZ0B3wqQx/8erh3zQOPBmKnNtBf 7LKA== X-Forwarded-Encrypted: i=1; AJvYcCVfq0GgFN6sGDptP1QxT1z/aufNb+TZIcq60WODeXbxxamU1ELIRENtCzCPX2PJeJSwGFoKc4PKlVUR1/7d@postgresql.org X-Gm-Message-State: AOJu0YyBzQs15dNY7eGok4z7bRU54tPDIuDezq4nnHke0ME9W9DbdZiy s/Wi4III8Knnxne9mXeEW0mUPAXmMT0gmV6kueVKptHi0j7DNoQIc93bl41B3Q== X-Google-Smtp-Source: AGHT+IHtvkhIm8p9vRSpqmO8PZjuK7gYy002zQLn7KF1uW5Iuy/YGeT9UFyQ+s2Pb3zjnFiSygoT8A== X-Received: by 2002:a05:6820:1c93:b0:5e7:caf5:ae03 with SMTP id 006d021491bc7-5ede631771amr765770eaf.2.1730404903793; Thu, 31 Oct 2024 13:01:43 -0700 (PDT) Received: from rfd.leadboat.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-5ec705086d3sm426615eaf.20.2024.10.31.13.01.41 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Oct 2024 13:01:42 -0700 (PDT) Date: Thu, 31 Oct 2024 13:01:39 -0700 From: Noah Misch To: Alexander Lakhin Cc: Nitin Motiani , Andres Freund , pgsql-hackers@postgresql.org Subject: Re: Inval reliability, especially for inplace updates Message-ID: <20241031200139.b4@rfd.leadboat.com> References: <20240831010711.67.nmisch@google.com> <20240930193350.04.nmisch@google.com> <20241013004511.9c.nmisch@google.com> <20241024025357.a8.nmisch@google.com> <20241031013924.cd.nmisch@google.com> <10ec0bc3-5933-1189-6bb8-5dec4114558e@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="dhrMrwYTLVcCbMQ+" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <10ec0bc3-5933-1189-6bb8-5dec4114558e@gmail.com> 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 --dhrMrwYTLVcCbMQ+ Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Thu, Oct 31, 2024 at 05:00:02PM +0300, Alexander Lakhin wrote: > I've accidentally discovered an incorrect behaviour caused by commit > 4eac5a1fa. Running this script: Thanks. This looks important. > parallel -j40 --linebuffer --tag .../reproi.sh ::: `seq 40` This didn't reproduce it for me, at -j20, -j40, or -j80. I tested at commit fb7e27a. At what commit(s) does it reproduce for you? At what commits, if any, did your test not reproduce this? > All three autovacuum workers (1143263, 1143320, 1143403) are also waiting > for the same buffer lock: > #5  0x0000561dd715f1fe in PGSemaphoreLock (sema=0x7fed9a817338) at pg_sema.c:327 > #6  0x0000561dd722fe02 in LWLockAcquire (lock=0x7fed9ad9b4e4, mode=LW_SHARED) at lwlock.c:1318 > #7  0x0000561dd71f8423 in LockBuffer (buffer=36, mode=1) at bufmgr.c:4182 Can you share the full backtrace for the autovacuum workers? This looks like four backends all waiting for BUFFER_LOCK_SHARE on the same pg_class page. One backend is in CREATE TABLE, and three are in autovacuum. There are no other apparent processes that would hold the BUFFER_LOCK_EXCLUSIVE blocking these four processes. > Also as a side note, these processes can't be terminated with SIGTERM, I > have to kill them. That suggests they're trying to acquire one LWLock while holding another. I'll recreate your CREATE TABLE stack trace and study its conditions. It's not readily clear to me how that would end up holding relevant lwlocks. Guessing how this happened did lead me to a bad decision in commit a07e03f, but I expect fixing that bad decision won't fix the hang you captured. That commit made index_update_stats() needlessly call RelationGetNumberOfBlocks() and visibilitymap_count() with a pg_class heap buffer lock held. Both do I/O, and the latter can exclusive-lock a visibility map buffer. The attached patch corrects that. Since the hang you captured involved a pg_class heap buffer lock, I don't think this patch will fix that hang. The other inplace updaters are free from similar badness. --dhrMrwYTLVcCbMQ+ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="inplace230-index_update_stats-io-before-buflock-v1.patch" Author: Noah Misch Commit: Noah Misch diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 74d0f30..bef1af6 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2806,6 +2806,9 @@ index_update_stats(Relation rel, bool hasindex, double reltuples) { + bool update_stats; + BlockNumber relpages; + BlockNumber relallvisible; Oid relid = RelationGetRelid(rel); Relation pg_class; ScanKeyData key[1]; @@ -2815,6 +2818,42 @@ index_update_stats(Relation rel, bool dirty; /* + * As a special hack, if we are dealing with an empty table and the + * existing reltuples is -1, we leave that alone. This ensures that + * creating an index as part of CREATE TABLE doesn't cause the table to + * prematurely look like it's been vacuumed. The final rd_rel may be + * different from rel->rd_rel due to e.g. commit of concurrent GRANT, but + * the commands that change reltuples take locks conflicting with ours. + * (Even if a command changed reltuples under a weaker lock, this affects + * only statistics for an empty table.) + */ + if (reltuples == 0 && rel->rd_rel->reltuples < 0) + reltuples = -1; + + /* + * Don't update statistics during binary upgrade, because the indexes are + * created before the data is moved into place. + */ + update_stats = reltuples >= 0 && !IsBinaryUpgrade; + + /* + * Finish I/O and visibility map buffer locks before + * systable_inplace_update_begin() locks the pg_class buffer. The final + * rd_rel may be different from rel->rd_rel due to e.g. commit of + * concurrent GRANT, but no command changes a relkind from non-index to + * index. (Even if one did, relallvisible doesn't break functionality.) + */ + if (update_stats) + { + relpages = RelationGetNumberOfBlocks(rel); + + if (rel->rd_rel->relkind != RELKIND_INDEX) + visibilitymap_count(rel, &relallvisible, NULL); + else /* don't bother for indexes */ + relallvisible = 0; + } + + /* * We always update the pg_class row using a non-transactional, * overwrite-in-place update. There are several reasons for this: * @@ -2858,15 +2897,6 @@ index_update_stats(Relation rel, /* Should this be a more comprehensive test? */ Assert(rd_rel->relkind != RELKIND_PARTITIONED_INDEX); - /* - * As a special hack, if we are dealing with an empty table and the - * existing reltuples is -1, we leave that alone. This ensures that - * creating an index as part of CREATE TABLE doesn't cause the table to - * prematurely look like it's been vacuumed. - */ - if (reltuples == 0 && rd_rel->reltuples < 0) - reltuples = -1; - /* Apply required updates, if any, to copied tuple */ dirty = false; @@ -2876,20 +2906,8 @@ index_update_stats(Relation rel, dirty = true; } - /* - * Avoid updating statistics during binary upgrade, because the indexes - * are created before the data is moved into place. - */ - if (reltuples >= 0 && !IsBinaryUpgrade) + if (update_stats) { - BlockNumber relpages = RelationGetNumberOfBlocks(rel); - BlockNumber relallvisible; - - if (rd_rel->relkind != RELKIND_INDEX) - visibilitymap_count(rel, &relallvisible, NULL); - else /* don't bother for indexes */ - relallvisible = 0; - if (rd_rel->relpages != (int32) relpages) { rd_rel->relpages = (int32) relpages; --dhrMrwYTLVcCbMQ+--