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 1ufG7e-004ax4-Dk for pgsql-hackers@arkaria.postgresql.org; Fri, 25 Jul 2025 10:57:55 +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 1ufG7d-00HLe7-B8 for pgsql-hackers@arkaria.postgresql.org; Fri, 25 Jul 2025 10:57:53 +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 1ufG7c-00HLdz-Sk for pgsql-hackers@lists.postgresql.org; Fri, 25 Jul 2025 10:57:53 +0000 Received: from mail-vs1-xe36.google.com ([2607:f8b0:4864:20::e36]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1ufG7b-000hx8-0U for pgsql-hackers@postgresql.org; Fri, 25 Jul 2025 10:57:52 +0000 Received: by mail-vs1-xe36.google.com with SMTP id ada2fe7eead31-4f7e63f3ef6so639722137.0 for ; Fri, 25 Jul 2025 03:57:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1753441069; x=1754045869; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=zRjF761lsZrxv+zuM77tLSAeIbGl4IHwohls5hRashg=; b=SDmmAk5E/t4ThH01bX+mdxxX5MwEj2P5bOg93ebazqqMvY1RynvkfOM+qWErEHH+Tg sfKtRyBcrx2Ju1oCVdrWOfqWy/roYPuFuUX4JQln6ZLHHshl9pgdcJlG4t2JPUu5qKcd f3Xpx8M//2dpnAKMzxWavvvMGFZ3IKFN0YTMl39yThNKBor7kp2CaGcC9lO+BG23tquY 2n+XzJRODbh+58IrJLUpR6JHmEcDIY2hH2vLVy9O8Uq+MnPFaOkr4UIufolXozqKRRqd nc3VD1HRmIrMijveuOJ6mRw/9EI5M4As8/HsBfTBANZkFZi7u2pV/tymFUPETCJ0ipxS ilXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753441069; x=1754045869; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zRjF761lsZrxv+zuM77tLSAeIbGl4IHwohls5hRashg=; b=lFn+56lOdgSYInHrfXX6yDorUJ2m1EQWhqUcZ/EU+Y/y3x2kedRV4wQzz+Aj0ab912 bacSwL9aemM4J4jXG/YC7dfK9gcxuWS5CSeDhU+01+DVpK5ajhFruVYSbl++haJB/3xh Whovparp0fQHpH/hkISkTFmVCAih0YWK/o/OHwL0Xl2fsD7XbXlwGJT6VOU9ixhOyAhY L2swlYWq0E8D/+sb54NYkynpYP8fpQY6WSJbkzZnZbvlVKc+tW5cZQfmIJNraWgt4xTl l0C4MtEsSRIqsZDGN9eifucWUtPm+sm6STFThEU5LG6NyRLVKh4zbY++uPJor6VejK7F Sjag== X-Forwarded-Encrypted: i=1; AJvYcCWUJIbKc32ns/qjCSF218H/AmoylPmwwVbUbSsu1m0WXVY7cAgQgaAv7kCZkzdbcF29NCDih2IgXXAe/WmV@postgresql.org X-Gm-Message-State: AOJu0YwowI+/KReV2RE9idYTd766DXHz/OjhFcySeq/qkOG2ts0/4jAK w8nF6j+O0YWFJTTklqgdxjk1rVrTumHG6n39l3KCpHzTs2Ntm8pMW1UCMeXG3AplWH3Wn0iIWMx LOmkcR7DCzZ2zhMQwlffxadptmg6RIf0= X-Gm-Gg: ASbGncueQxkoqRz/WelaurVPgJSpFPQnLU/G89pY5kvX4583PVKdivun2bDEom+YV30 d5+dBpy2ro7+YAq8M9DL77W1PFUd7Mf0Wh3193Rz4jAREeUQeIrVGCXb+h8LkyaQS34dUY1N0GJ fGyJ5Nt6kxXpszBU/b0Mjc0PTcpj/TY6MB2Ioxr+i5e7UW4vSpl0MM55BJeeQlP4gE/ttKtsLvd lRj8D+G X-Google-Smtp-Source: AGHT+IHTkX1zd8MzfQaScSSvj+2+tVDtBf5krr3LolO/dbtT6bLlp/2AVqdMxF5/EQT2sQaASr8ls6TonIXJ2bE9KQQ= X-Received: by 2002:a05:6102:5ccb:b0:4e7:f3d3:a283 with SMTP id ada2fe7eead31-4fa3ff93bf8mr289664137.25.1753441069207; Fri, 25 Jul 2025 03:57:49 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Ashutosh Bapat Date: Fri, 25 Jul 2025 16:27:37 +0530 X-Gm-Features: Ac12FXxpi8D55otPph4VNE9KkWvWjrwQiReXEYWuJgC2k9rcfvU-2yOM7FxumGQ Message-ID: Subject: Re: [Proposal] Expose internal MultiXact member count function for efficient monitoring To: Naga Appani Cc: Kirill Reshke , pgsql-hackers@postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Jun 10, 2025 at 7:50=E2=80=AFPM Naga Appani wro= te: > > On Tue, Mar 11, 2025 at 4:48=E2=80=AFAM Kirill Reshke wrote: > > > > On Tue, 11 Mar 2025 at 14:37, Naga Appani wrote: > > > > > > > > > > > > On Mon, Mar 10, 2025 at 10:43=E2=80=AFAM Naga Appani wrote: > > >> > > >> Hi, > > >> > > > > Hi > > > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > Proposal > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > The internal ReadMultiXactCounts() function, implemented in multixact= .c, directly calculates the number of MultiXact members by reading live sta= te from shared memory. This approach avoids the performance issues of the c= urrent filesystem-based estimation methods. > > > > This proposal looks sane. It is indeed helpful to keep an eye out for > > multixact usage in systems that are heavily loaded. > > > > > By exposing ReadMultiXactCounts() for external use, we can provide Po= stgreSQL users with an efficient way to monitor MultiXact member usage. Thi= s could be particularly useful for integrating with tools like Amazon RDS P= erformance Insights and Amazon CloudWatch to provide enhanced database insi= ghts and proactive managed monitoring for users. > > > > > > Please let me know if this approach is acceptable, so I=E2=80=99ll go= ahead and submit a patch. > > > > Let's give it a try! > > Hi, > > As a follow-up, I=E2=80=99m submitting a patch that introduces a SQL-call= able > function to retrieve MultiXact usage metrics. Although the motivation > has been discussed earlier in this thread, I=E2=80=99m including a brief = recap > below to provide context for the patch itself. > > While wraparound due to MultiXacts (MXID) is less frequent than XID > wraparound, it can still lead to aggressive/wraparound vacuum behavior > or downtime in certain workloads =E2=80=94 especially those involving for= eign > keys, shared row locks, or long-lived transactions. Currently, users > have no SQL-level visibility into MultiXact member consumption, which > makes it hard to proactively respond before issues arise. I see mxid_age() will just give mxid consumption but not members consumption. So just that function is not enough. > > Sample output > ------------- > multixacts | members > ------------+------------ > 182371396 | 2826221174 > (1 row) > > Performance comparison > ---------------------- > While performance is not the primary motivation for this patch, it > becomes important in monitoring scenarios where frequent polling is > expected. The proposed function executes in sub-millisecond time and > avoids any filesystem I/O, making it well-suited for lightweight, > periodic monitoring. > > Implementation | Used size | MultiXact members > | Time (ms) | Relative cost > -------------------------------------+-----------+-------------------+---= --------+---------------- > Community (pg_ls_multixactdir) | 8642 MB | 1.8 billion | > 96.879 | 1.00 (baseline) > Linux (du command) | 8642 MB | 1.8 billion | > 96 | 1.00 > Proposal (ReadMultiXactCounts-based) | N/A | 1.99 billion | > 0.167 | ~580x faster > > Documentation > ------------- > - A new section is added to func.sgml to group multixact-related function= s > - A reference to this new function is included in the "Multixacts and > Wraparound" subsection of maintenance.sgml > > To keep related functions grouped together, we can consider moving > mxid_age() into the new section as well unless there are objections to > relocating it from the current section. In [1], we decided to document pg_get_multixact_member() in section "Transaction ID and Snapshot Information Functions". I think the discussion in the email thread applies to this function as well. + + MultiXact Information Functions + + + + pg_get_multixact_count + pg_get_multixact_count () + record + + + Returns a record with the fields multixacts and members: + + + multixacts: Number of MultiXacts assigned. + PostgreSQL initiates aggressive autovacuum when this value grows beyond the threshold + defined by autovacuum_multixact_freeze_max_age, which is based on + the age of datminmxid. For more details, se= e + + Routine Vacuuming: Multixact Wraparound. + + + members: Number of MultiXact member entries created. + These are stored in files under the pg_multixact/members subdirectory. + Wraparound occurs after approximately 4.29 billion entries (~20=E2=80=AFGiB). PostgreSQL initiates + aggressive autovacuum when the number of members created exceeds approximately 2.145 billion + or when storage consumption in pg_multixact/members approaches 10=E2=80=AFGiB. + + + + The description here doesn't follow the format of the other functions in this section. We usually explain the inputs and outputs of the function but not how to use the outputs. In this case, you might want to just refer to Multixact Wraparound section under Routine Vacuuming chapter rather than describing the autovacuum behaviour. You can do that by inserting instead of a full URL. These links are appropriately resolved when creating HTML to version specific links. The URL you have used will always point to "Current" version. + + The pg_get_multixact_count + function provides a way to check how many multixacts and member entries have been allocated. This can + be useful for identifying unusual multixact activity, monitoring progress toward wraparound, anticipating + system-wide aggressive autovacuum as usage approaches critical thresholds, or verifying whether autovacuum + is keeping up with demand. + + This is the right place to go in details of how the function can be used; not the function documentation itself. I am yet to make up whether we need the whole description. I think the first line is enough and goes well with the rest of the section. + + if (!ReadMultiXactCounts(&multixacts, &members)) + ereport(ERROR, + (errmsg("could not read multixact counts"))); Throwing an error causes the surrounding transaction to abort, so it should be avoided in a monitoring/reporting function if possible. In this case for example, we could throw a warning instead or report NULL values. If ReadMultiXactCounts() returns false, MultiXactMemberFreezeThreshold() returns 0, which will cause the autovacuum to be more aggressive. I think it will be good to highlight that in the function description since that's one of the objectives of this function: to know when the autovacuum is going to be more aggressive. + + values[0] =3D UInt32GetDatum(multixacts); + values[1] =3D UInt32GetDatum(members); + + tuple =3D heap_form_tuple(tupdesc, values, nulls); + PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); +} In PG14+, the transaction wraparound is triggered if the size of the directory exceeds 10GB. This function does not help monitoring that condition. So a user will need to use du or pg_ls_multixactdir() anyway, which defeats the purpose of this function being more efficient than those methods. Am I correct? Can we also report the size of the directory in this function? The patch needs tests. [1] https://www.postgresql.org/message-id/aF8b_fp_9Va58vB9%40nathan --=20 Best Wishes, Ashutosh Bapat