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 1jZNpI-0007Ea-6x for pgsql-hackers@arkaria.postgresql.org; Fri, 15 May 2020 00:03:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1jZNpG-00073j-Rc for pgsql-hackers@arkaria.postgresql.org; Fri, 15 May 2020 00:03:42 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jZNpG-00073c-HK for pgsql-hackers@lists.postgresql.org; Fri, 15 May 2020 00:03:42 +0000 Received: from mail-pf1-x443.google.com ([2607:f8b0:4864:20::443]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jZNpD-0004wP-LC for pgsql-hackers@postgresql.org; Fri, 15 May 2020 00:03:42 +0000 Received: by mail-pf1-x443.google.com with SMTP id 145so97709pfw.13 for ; Thu, 14 May 2020 17:03:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:message-id:to:cc:subject:from:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=ZPna0Uo8lvNrzTGXvYixNlTcKbHsfPeEqfV/1CsSEC4=; b=LiWoTlCuPEU9Vb+Cj3fIfy/2eFcbvyPjtm+tAdICwGBorF3akSJc7Kd6RWTjV6GAcO vcXol9cGNIze4xAiwcEq0hmek9JTglo0+NA5N5KuC5t74ZBb9+XldJBIBeO6Axi0w45m 35T6YMf2e+lFFdbgkeCPQudTPdzTBbUDYJMkUxQcMz6kAHN0X2ManqYWHn4z1s8sQZTq r0ku0Oe7eRQ0GJBI1S9m1vp6b8Zt85SSV3iboABndyAPgkR0m5mF4MGaVkM/xE/xLJn3 0fCD096ibGwvswANUCCjZM7O3bwno9l5w1QdHayvC+ts3JO1uwqgqZT8LDjbx6vHMAYQ iruw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:to:cc:subject:from:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=ZPna0Uo8lvNrzTGXvYixNlTcKbHsfPeEqfV/1CsSEC4=; b=dR2bxh7uoqEV84foiA89d1Ljbbef1K4SfOWxR/DBS6EcGwQquxjLrGcpAthsRIM4Fi 46eerCxJ/Yxao1JJX4D8vYhKmGbG2DlHz6hHkOM1lUIYy8ZqP3twlUktJK/WiAG7kwAr Y5bPwwi302swc4n5WMwwO6EkOZVs/J1ifSIpZ1IHuXYafZz9arYtaNZ1v8Jbg+N9wLFn vRr8D7dgBKbnbge83BQp9jSYuLs6WstZca3d2zu2r3Z79Y4HyslrMgFiv0bKXEDvk7gD f2vysgzwsbRp0rjwiVXv8saJAJnfAJ6EBQ+K4y9iIsl6GPOzt2/Chb1T3ZAttHd9GVwD oZlQ== X-Gm-Message-State: AOAM531wbob7VRa0iinZEnfN/hGmkbZqp9Qqbe0DQbk4XdJBmfeZxZq5 A3QzYaE/HAYxvyWASU4RwKU= X-Google-Smtp-Source: ABdhPJzzScVbg7Jp7UQpr4I5x2S6sRnS2FuIH+3+7dmWFMZbxiHx6wNt3w8O+W5HXixy60GKjYuqcg== X-Received: by 2002:a63:f750:: with SMTP id f16mr574337pgk.136.1589501017294; Thu, 14 May 2020 17:03:37 -0700 (PDT) Received: from localhost (ag027197.dynamic.ppp.asahi-net.or.jp. [157.107.27.197]) by smtp.gmail.com with ESMTPSA id i11sm135181pjs.44.2020.05.14.17.03.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 May 2020 17:03:36 -0700 (PDT) Date: Fri, 15 May 2020 09:03:33 +0900 (JST) Message-Id: <20200515.090333.24867479329066911.horikyota.ntt@gmail.com> To: x4mmm@yandex-team.ru Cc: pgsql-hackers@postgresql.org Subject: Re: MultiXact\SLRU buffers configuration From: Kyotaro Horiguchi In-Reply-To: <102F673B-C9C5-4823-A92F-96799FC61ED0@yandex-team.ru> References: <3B099683-ECCD-43CD-A3D6-F08C3745002A@yandex-team.ru> <20200514.151659.1224056315528271804.horikyota.ntt@gmail.com> <102F673B-C9C5-4823-A92F-96799FC61ED0@yandex-team.ru> User-Agent: Mew version 6.8 on Emacs 26.1 Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Fri_May_15_09_03_33_2020_372)--" Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk ----Next_Part(Fri_May_15_09_03_33_2020_372)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit At Thu, 14 May 2020 11:44:01 +0500, "Andrey M. Borodin" wrote in > > GetMultiXactIdMembers believes that 4 is successfully done if 2 > > returned valid offset, but actually that is not obvious. > > > > If we add a single giant lock just to isolate ,say, > > GetMultiXactIdMember and RecordNewMultiXact, it reduces concurrency > > unnecessarily. Perhaps we need finer-grained locking-key for standby > > that works similary to buffer lock on primary, that doesn't cause > > confilicts between irrelevant mxids. > > > We can just replay members before offsets. If offset is already there - members are there too. > But I'd be happy if we could mitigate those 1000us too - with a hint about last maixd state in a shared MX state, for example. Generally in such cases, condition variables would work. In the attached PoC, the reader side gets no penalty in the "likely" code path. The writer side always calls ConditionVariableBroadcast but the waiter list is empty in almost all cases. But I couldn't cause the situation where the sleep 1000u is reached. > Actually, if we read empty mxid array instead of something that is replayed just yet - it's not a problem of inconsistency, because transaction in this mxid could not commit before we started. ISTM. > So instead of fix, we, probably, can just add a comment. If this reasoning is correct. The step 4 of the reader side reads the members of the target mxid. It is already written if the offset of the *next* mxid is filled-in. regards. -- Kyotaro Horiguchi NTT Open Source Software Center ----Next_Part(Fri_May_15_09_03_33_2020_372)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="mxid_wait_instead_of_sleep.patch" diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index e2aa5c9ce4..9db8f6cddd 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -82,6 +82,7 @@ #include "lib/ilist.h" #include "miscadmin.h" #include "pg_trace.h" +#include "pgstat.h" #include "postmaster/autovacuum.h" #include "storage/lmgr.h" #include "storage/pmsignal.h" @@ -233,6 +234,7 @@ typedef struct MultiXactStateData /* support for members anti-wraparound measures */ MultiXactOffset offsetStopLimit; /* known if oldestOffsetKnown */ + ConditionVariable nextoff_cv; /* * Per-backend data starts here. We have two arrays stored in the area * immediately following the MultiXactStateData struct. Each is indexed by @@ -873,6 +875,14 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, /* Exchange our lock */ LWLockRelease(MultiXactOffsetControlLock); + /* + * Let everybody know the offset of this mxid is recorded now. The waiters + * are waiting for the offset of the mxid next of the target to know the + * number of members of the target mxid, so we don't need to wait for + * members of this mxid are recorded. + */ + ConditionVariableBroadcast(&MultiXactState->nextoff_cv); + LWLockAcquire(MultiXactMemberControlLock, LW_EXCLUSIVE); prev_pageno = -1; @@ -1367,9 +1377,19 @@ retry: if (nextMXOffset == 0) { /* Corner case 2: next multixact is still being filled in */ + + /* + * The recorder of the next mxid is just before writing the offset. + * Wait for the offset to be written. + */ + ConditionVariablePrepareToSleep(&MultiXactState->nextoff_cv); + LWLockRelease(MultiXactOffsetControlLock); CHECK_FOR_INTERRUPTS(); - pg_usleep(1000L); + + ConditionVariableSleep(&MultiXactState->nextoff_cv, + WAIT_EVENT_WAIT_NEXT_MXMEMBERS); + ConditionVariableCancelSleep(); goto retry; } @@ -1847,6 +1867,7 @@ MultiXactShmemInit(void) /* Make sure we zero out the per-backend state */ MemSet(MultiXactState, 0, SHARED_MULTIXACT_STATE_SIZE); + ConditionVariableInit(&MultiXactState->nextoff_cv); } else Assert(found); diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 0ecd29a1d9..1ac6b37188 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -3879,6 +3879,9 @@ pgstat_get_wait_ipc(WaitEventIPC w) case WAIT_EVENT_SYNC_REP: event_name = "SyncRep"; break; + case WAIT_EVENT_WAIT_NEXT_MXMEMBERS: + event_name = "Mact/WaitNextXactMembers"; + break; /* no default case, so that compiler will warn */ } diff --git a/src/include/pgstat.h b/src/include/pgstat.h index ae9a39573c..e79bba0bef 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -886,7 +886,8 @@ typedef enum WAIT_EVENT_REPLICATION_ORIGIN_DROP, WAIT_EVENT_REPLICATION_SLOT_DROP, WAIT_EVENT_SAFE_SNAPSHOT, - WAIT_EVENT_SYNC_REP + WAIT_EVENT_SYNC_REP, + WAIT_EVENT_WAIT_NEXT_MXMEMBERS } WaitEventIPC; /* ---------- ----Next_Part(Fri_May_15_09_03_33_2020_372)----