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.96) (envelope-from ) id 1wQJuw-001RPu-2V for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 07:03:35 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wQJuu-00CajV-2N for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 07:03:33 +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.96) (envelope-from ) id 1wQJuu-00CajM-0g for pgsql-hackers@lists.postgresql.org; Fri, 22 May 2026 07:03:33 +0000 Received: from mail-pj1-x1034.google.com ([2607:f8b0:4864:20::1034]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wQJut-00000000Edf-0AQO for pgsql-hackers@postgresql.org; Fri, 22 May 2026 07:03:32 +0000 Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-368f25ff4c4so3758899a91.2 for ; Fri, 22 May 2026 00:03:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779433409; x=1780038209; darn=postgresql.org; h=to:cc:date:message-id:subject:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=A0+5FxrU1D7OuhDghN8Ae+LDVOBaWsbGWuMx0Y/LmEo=; b=Rk90/uelh6oz/FtgUEuP9BKhdq7AdGA1fduphivuau249ewn4jEaz7ZPQID4SqiYK8 2CXl8CWtkfotKCHBHS+nK/597uXDpIJZZnAzZtnFJP0ZO2ouQoxVtJjUyI0n433u3ccR VmxNprkGT2epFnhEnb18vdKc8ut1lPeRsgLVmjklf8egX8xPlP9ixL15C9zae9mPcvo7 W8yoSS8oqoSxttcn/jmwE3JNDMF0nTp9nWfWTBeZ0aXcdM3eKqqLYyLCNstlmYdhaH9V bFkft2QdWkxzUva+97gFOemMAHa8zPMHZgRP95WCPH3IlwTe07uVIMsSLa5CdkivXwTg lb9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779433409; x=1780038209; h=to:cc:date:message-id:subject:mime-version:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=A0+5FxrU1D7OuhDghN8Ae+LDVOBaWsbGWuMx0Y/LmEo=; b=LGoxOKg/CXfIvPfgQ4sJZ7RxWBRABxriTqsOagxlfLs13DFg5Nv5T3PbxEmJ2FEEMN sgrDa8fZkDGHq8a15+1KGmCbiN/f2prwqiB+HvA1fAC74bMI0Mn4asqszUzUuzJbxcaA Y9MeREAcfYlZZhYuVBa85lMqi5thZboI+lg4SRJim5L75IX3uUm1FSHbGiwR1L5ti5jd oxVb8YQB4GvrGxGbEmr74RP1FQmGMKElS/TkFI9gnMNUTols8XOb5MViPpf2M5fkJZdU aQrFbD8WMQwajAOa8P/BZ5Uxc9frPkS4huy1kMp/W0HVTL4cY0dsnZnFXKjzexqxjykd kbBQ== X-Gm-Message-State: AOJu0YxW/Roky9FZv1mLINZmWUsC56Lqr3ahNNfOTcHEZyfhygrE6YfL CrMIyETNv6ZhnSmMBjPDSn+ZHziWSvZBsYaLQ43PBEwjrtWJd/kQrtH0uKpBTRm+ X-Gm-Gg: Acq92OGR/b8udfcr9iEZlSF85o8Giex6nSG/rpf4iIqj7/HEJUtbJQP+HxOpQwH1hC0 NbEV5SUnrQ4lkNwiktcam200u94Lpbaw/pkqUlCz8vMwxBcyAZyeLnKeI4EqILMQTr+T/spqfc4 uMEMZpkQVV+Ta14WfIdO/b48HBbLmsGRi+fAMb9P1U8izvoilBJm2EschnSVG/2SYKOnyPc3zDm YkOTjFLEFbkhvKtHkDY9ky4acp8fqRqInfLCtiVkkuAVu7AHIWDKfw4mT6Q6C3qjOiqbElwlQaV WB+hOrGlxH70naTVHOlBnaeiLKtnb+HqXblPbSN60KUP964f9QztTZlzvTn5T1/TolLhWqxwFbz RyN2cNUDSdIMQnoHMsvU+fJoGu+7pGOoxxrWxZMX3FaY1hDArD4aAI09UTCZCvI/enTHjnyc/Fp yZaIw9nZ2lq7Pnyvh12eZxceXzkm+OWsc= X-Received: by 2002:a17:90b:5343:b0:368:a27f:9083 with SMTP id 98e67ed59e1d1-36a67761c51mr1960122a91.7.1779433409265; Fri, 22 May 2026 00:03:29 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-36a723cee01sm962409a91.14.2026.05.22.00.03.27 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 May 2026 00:03:28 -0700 (PDT) From: Chao Li Content-Type: multipart/mixed; boundary="Apple-Mail=_362AB958-2B93-4C72-A09E-34A545046DB1" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.600.51.1.1\)) Subject: Fix pg_get_multixact_stats() members_size calculation Message-Id: <819AC1B2-1A71-4244-B081-3ADD85D1725D@gmail.com> Date: Fri, 22 May 2026 15:02:48 +0800 Cc: Michael Paquier , nagnrik@gmail.com To: PostgreSQL-development X-Mailer: Apple Mail (2.3864.600.51.1.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_362AB958-2B93-4C72-A09E-34A545046DB1 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hi, While testing pg_get_multixact_stats(), I found that it can undercount = members_size. This is a simple repro, starting from a fresh cluster. Session 1: ``` evantest=3D# create table t (i int primary key); CREATE TABLE evantest=3D# insert into t values (1); INSERT 0 1 evantest=3D# evantest=3D# begin; BEGIN evantest=3D*# select * from t where i =3D 1 for share; i --- 1 (1 row) ``` Session 2: ``` evantest=3D# begin; BEGIN evantest=3D*# select * from t where i =3D 1 for share; i --- 1 (1 row) evantest=3D*# select * from pg_get_multixact_stats(); num_mxids | num_members | members_size | oldest_multixact -----------+-------------+--------------+------------------ 1 | 2 | 0 | 1 (1 row) ``` num_members is reported as 2, but members_size is reported as 0, which = looks surprising. The current implementation does the division before multiplying by the = member-group size: ``` static inline uint64 MultiXactOffsetStorageSize(MultiXactOffset new_offset, MultiXactOffset old_offset) { Assert(new_offset >=3D old_offset); return (uint64) ((new_offset - old_offset) / = MULTIXACT_MEMBERS_PER_MEMBERGROUP) * MULTIXACT_MEMBERGROUP_SIZE; } ``` Since MULTIXACT_MEMBERS_PER_MEMBERGROUP is 4, any remainder of 1 to 3 = members is truncated. This is less visible with large values, but it = becomes obvious with a small number of members, as in the example above. I checked the related commits, 0e3ad4b96aedee57fc2694e28486fe0ceca8110a = and 97b101776ce23dd6c4abbdae213806bc24ed6133, and I didn't see anything = suggesting that this truncation was intentional. So even though this is = a small issue, I think it is better to fix it before PostgreSQL 19 is = released. The fix is straightforward, just compute the per-member size first, = which is MULTIXACT_MEMBERGROUP_SIZE / MULTIXACT_MEMBERS_PER_MEMBERGROUP, = and then multiply that by (new_offset - old_offset). The doc example also seems to confirm that members_size is meant to be = num_members * 5, without rounding for group alignment or accounting for = the 12 bytes wasted per page: ``` =3D# SELECT *, pg_size_pretty(members_size) members_size_pretty FROM pg_catalog.pg_get_multixact_stats(); num_mxids | num_members | members_size | oldest_multixact | = members_size_pretty = -----------+-------------+--------------+------------------+--------------= ------- 311740299 | 2785241176 | 13926205880 | 2 | 13 GB (1 row) ``` Where 2785241176 * 5 =3D 13926205880. With the fix, the same test reports members_size as 10: ``` evantest=3D*# select * from pg_get_multixact_stats(); num_mxids | num_members | members_size | oldest_multixact -----------+-------------+--------------+------------------ 1 | 2 | 10 | 1 (1 row) ``` The attached patch also updates the existing isolation test to cover = members_size. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_362AB958-2B93-4C72-A09E-34A545046DB1 Content-Disposition: attachment; filename=v1-0001-Fix-pg_get_multixact_stats-members_size-calculati.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0001-Fix-pg_get_multixact_stats-members_size-calculati.patch" Content-Transfer-Encoding: quoted-printable =46rom=206353c2dc45d9cdc64c5206ec576c578a3d2edd08=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20"Chao=20Li=20(Evan)"=20=0A= Date:=20Fri,=2022=20May=202026=2014:47:21=20+0800=0ASubject:=20[PATCH=20= v1]=20Fix=20pg_get_multixact_stats()=20members_size=20calculation=0A=0A= pg_get_multixact_stats()=20reports=20members_size=20as=20the=20storage=20= used=20by=0Athe=20currently=20retained=20multixact=20member=20entries.=20= However,=0AMultiXactOffsetStorageSize()=20divided=20the=20member=20count=20= by=20the=20number=20of=0Amembers=20per=20storage=20group=20before=20= multiplying=20by=20the=20group=20size,=20so=20it=0Arounded=20down=20and=20= reported=20zero=20for=201-3=20retained=20members.=0A=0AThis=20patch=20= changes=20to=20compute=20the=20size=20from=20the=20member=20count=20= directly.=0A=0AExtend=20the=20multixact-stats=20isolation=20test=20to=20= include=20members_size=20in=20its=0Asnapshots=20and=20verify=20that=20it=20= matches=20the=20reported=20member=20count.=0A=0AAuthor:=20Chao=20Li=20= =0AReviewed-by:=0ADiscussion:=20https://postgr.es/m/=0A= ---=0A=20src/include/access/multixact_internal.h=20=20=20=20=20=20=20|=20= =209=20+++--=0A=20.../isolation/expected/multixact-stats.out=20=20=20=20= |=2036=20+++++++++++--------=0A=20= src/test/isolation/specs/multixact-stats.spec=20|=2031=20= ++++++++++------=0A=203=20files=20changed,=2049=20insertions(+),=2027=20= deletions(-)=0A=0Adiff=20--git=20= a/src/include/access/multixact_internal.h=20= b/src/include/access/multixact_internal.h=0Aindex=20= 82349ea0d32..09755511376=20100644=0A---=20= a/src/include/access/multixact_internal.h=0A+++=20= b/src/include/access/multixact_internal.h=0A@@=20-126,9=20+126,14=20@@=20= static=20inline=20uint64=0A=20MultiXactOffsetStorageSize(MultiXactOffset=20= new_offset,=0A=20=09=09=09=09=09=09=20=20=20MultiXactOffset=20= old_offset)=0A=20{=0A+=09uint64=09=09size_per_member;=0A+=0A=20=09= Assert(new_offset=20>=3D=20old_offset);=0A-=09return=20(uint64)=20= ((new_offset=20-=20old_offset)=20/=20MULTIXACT_MEMBERS_PER_MEMBERGROUP)=20= *=0A-=09=09MULTIXACT_MEMBERGROUP_SIZE;=0A+=09= Assert(MULTIXACT_MEMBERGROUP_SIZE=20%=20= MULTIXACT_MEMBERS_PER_MEMBERGROUP=20=3D=3D=200);=0A+=0A+=09= size_per_member=20=3D=20MULTIXACT_MEMBERGROUP_SIZE=20/=20= MULTIXACT_MEMBERS_PER_MEMBERGROUP;=0A+=0A+=09return=20(new_offset=20-=20= old_offset)=20*=20size_per_member;=0A=20}=0A=20=0A=20#endif=09=09=09=09=09= =09=09/*=20MULTIXACT_INTERNAL_H=20*/=0Adiff=20--git=20= a/src/test/isolation/expected/multixact-stats.out=20= b/src/test/isolation/expected/multixact-stats.out=0Aindex=20= 27a6510c4ad..f170b04c3e4=20100644=0A---=20= a/src/test/isolation/expected/multixact-stats.out=0A+++=20= b/src/test/isolation/expected/multixact-stats.out=0A@@=20-3,7=20+3,7=20= @@=20Parsed=20test=20spec=20with=202=20sessions=0A=20starting=20= permutation:=20snap0=20s1_begin=20s1_lock=20snap1=20s2_begin=20s2_lock=20= snap2=20check_while_pinned=20s1_commit=20s2_commit=0A=20step=20snap0:=20=0A= =20=20=20CREATE=20TEMP=20TABLE=20snap0=20AS=0A-=20=20SELECT=20num_mxids,=20= num_members,=20oldest_multixact=0A+=20=20SELECT=20num_mxids,=20= num_members,=20members_size,=20oldest_multixact=0A=20=20=20FROM=20= pg_get_multixact_stats();=0A=20=0A=20step=20s1_begin:=20BEGIN;=0A@@=20= -15,7=20+15,7=20@@=20step=20s1_lock:=20SELECT=201=20FROM=20mxq=20WHERE=20= id=3D1=20FOR=20KEY=20SHARE;=0A=20=0A=20step=20snap1:=20=0A=20=20=20= CREATE=20TEMP=20TABLE=20snap1=20AS=0A-=20=20SELECT=20num_mxids,=20= num_members,=20oldest_multixact=0A+=20=20SELECT=20num_mxids,=20= num_members,=20members_size,=20oldest_multixact=0A=20=20=20FROM=20= pg_get_multixact_stats();=0A=20=0A=20step=20s2_begin:=20BEGIN;=0A@@=20= -27,7=20+27,7=20@@=20step=20s2_lock:=20SELECT=201=20FROM=20mxq=20WHERE=20= id=3D1=20FOR=20KEY=20SHARE;=0A=20=0A=20step=20snap2:=20=0A=20=20=20= CREATE=20TEMP=20TABLE=20snap2=20AS=0A-=20=20SELECT=20num_mxids,=20= num_members,=20oldest_multixact=0A+=20=20SELECT=20num_mxids,=20= num_members,=20members_size,=20oldest_multixact=0A=20=20=20FROM=20= pg_get_multixact_stats();=0A=20=0A=20step=20check_while_pinned:=20=0A@@=20= -39,32=20+39,37=20@@=20step=20check_while_pinned:=0A=20=20=20=20=20= ARRAY[=0A=20=20=20=20=20=20=20'is_init_mxids',=0A=20=20=20=20=20=20=20= 'is_init_members',=0A+=20=20=20=20=20=20'is_init_members_size',=0A=20=20=20= =20=20=20=20'is_init_oldest_mxid',=0A-=20=20=20=20=20=20= 'is_init_oldest_off',=0A=20=20=20=20=20=20=20'is_oldest_mxid_nondec_01',=0A= =20=20=20=20=20=20=20'is_oldest_mxid_nondec_12',=0A-=20=20=20=20=20=20= 'is_oldest_off_nondec_01',=0A-=20=20=20=20=20=20= 'is_oldest_off_nondec_12',=0A=20=20=20=20=20=20=20= 'is_members_increased_ge1',=0A+=20=20=20=20=20=20= 'is_msize_matches_members',=0A=20=20=20=20=20=20=20'is_mxids_nondec_01',=0A= =20=20=20=20=20=20=20'is_mxids_nondec_12',=0A=20=20=20=20=20=20=20= 'is_members_nondec_01',=0A-=20=20=20=20=20=20'is_members_nondec_12'=0A+=20= =20=20=20=20=20'is_members_nondec_12',=0A+=20=20=20=20=20=20= 'is_msize_nondec_01',=0A+=20=20=20=20=20=20'is_msize_nondec_12'=0A=20=20=20= =20=20],=0A=20=20=20=20=20ARRAY[=0A=20=20=20=20=20=20=20(s2.num_mxids=20=20= =20=20=20=20=20=20IS=20NOT=20NULL),=0A=20=20=20=20=20=20=20= (s2.num_members=20=20=20=20=20=20IS=20NOT=20NULL),=0A+=20=20=20=20=20=20= (s2.members_size=20=20=20=20=20IS=20NOT=20NULL),=0A=20=20=20=20=20=20=20= (s2.oldest_multixact=20IS=20NOT=20NULL),=0A=20=0A=20=20=20=20=20=20=20= (s1.oldest_multixact::text::bigint=20>=3D=20= COALESCE(s0.oldest_multixact::text::bigint,=200)),=0A=20=20=20=20=20=20=20= (s2.oldest_multixact::text::bigint=20>=3D=20= COALESCE(s1.oldest_multixact::text::bigint,=200)),=0A=20=0A=20=20=20=20=20= =20=20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200)=20+=201),=0A= +=20=20=20=20=20=20(s2.members_size=20=3D=20s2.num_members=20*=205),=0A=20= =0A=20=20=20=20=20=20=20(s1.num_mxids=20=20=20>=3D=20= COALESCE(s0.num_mxids,=20=20=200)),=0A=20=20=20=20=20=20=20(s2.num_mxids=20= =20=20>=3D=20COALESCE(s1.num_mxids,=20=20=200)),=0A=20=20=20=20=20=20=20= (s1.num_members=20>=3D=20COALESCE(s0.num_members,=200)),=0A-=20=20=20=20=20= =20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200))=0A+=20=20=20=20= =20=20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200)),=0A+=20=20=20= =20=20=20(s1.members_size=20>=3D=20COALESCE(s0.members_size,=200)),=0A+=20= =20=20=20=20=20(s2.members_size=20>=3D=20COALESCE(s1.members_size,=200))=0A= =20=20=20=20=20]=0A=20=20=20)=20AS=20r(assertion,=20ok);=0A=20=0A@@=20= -72,18=20+77,19=20@@=20assertion=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|ok=0A=20------------------------+--=0A=20is_init_mxids=20=20=20=20=20= =20=20=20=20=20=20|t=20=0A=20is_init_members=20=20=20=20=20=20=20=20=20= |t=20=0A+is_init_members_size=20=20=20=20|t=20=0A=20is_init_oldest_mxid=20= =20=20=20=20|t=20=0A-is_init_oldest_off=20=20=20=20=20=20|t=20=0A=20= is_oldest_mxid_nondec_01|t=20=0A=20is_oldest_mxid_nondec_12|t=20=0A= -is_oldest_off_nondec_01=20|t=20=0A-is_oldest_off_nondec_12=20|t=20=0A=20= is_members_increased_ge1|t=20=0A+is_msize_matches_members|t=20=0A=20= is_mxids_nondec_01=20=20=20=20=20=20|t=20=0A-is_mxids_nondec_12=20=20=20=20= =20=20|=20=20=0A-is_members_nondec_01=20=20=20=20|=20=20=0A= -is_members_nondec_12=20=20=20=20|=20=20=0A-(13=20rows)=0A= +is_mxids_nondec_12=20=20=20=20=20=20|t=20=0A+is_members_nondec_01=20=20=20= =20|t=20=0A+is_members_nondec_12=20=20=20=20|t=20=0A+is_msize_nondec_01=20= =20=20=20=20=20|t=20=0A+is_msize_nondec_12=20=20=20=20=20=20|t=20=0A+(14=20= rows)=0A=20=0A=20step=20s1_commit:=20COMMIT;=0A=20step=20s2_commit:=20= COMMIT;=0Adiff=20--git=20a/src/test/isolation/specs/multixact-stats.spec=20= b/src/test/isolation/specs/multixact-stats.spec=0Aindex=20= 07d4b11be6d..bc612e20818=20100644=0A---=20= a/src/test/isolation/specs/multixact-stats.spec=0A+++=20= b/src/test/isolation/specs/multixact-stats.spec=0A@@=20-4,8=20+4,10=20@@=0A= =20#=20is=20pinned=20by=20two=20open=20transactions,=20we=20check=20some=20= patterns=20that=20VACUUM=20and=0A=20#=20FREEZE=20cannot=20violate:=0A=20= #=201)=20"members"=20increased=20by=20at=20least=201=20when=20the=20= second=20session=20locked=20the=20row.=0A-#=202)=20(num_mxids=20/=20= num_members)=20not=20decreased=20compared=20to=20earlier=20snapshots.=0A= -#=203)=20"oldest_*"=20fields=20never=20decreased.=0A+#=202)=20= "members_size"=20reflects=20the=20storage=20used=20by=20the=20member=20= entries.=0A+#=203)=20(num_mxids=20/=20num_members=20/=20members_size)=20= not=20decreased=20compared=20to=0A+#=20=20=20=20earlier=20snapshots.=0A= +#=204)=20"oldest_*"=20fields=20never=20decreased.=0A=20#=0A=20#=20This=20= test=20does=20not=20run=20checks=20after=20releasing=20locks,=20as=20= freezing=20and/or=0A=20#=20truncation=20may=20shrink=20the=20multixact=20= ranges=20calculated.=0A@@=20-39,14=20+41,14=20@@=20step=20s2_commit=20{=20= COMMIT;=20}=0A=20#=20multixacts=20have=20not=20initialized=20yet.=0A=20= step=20snap0=20{=0A=20=20=20CREATE=20TEMP=20TABLE=20snap0=20AS=0A-=20=20= SELECT=20num_mxids,=20num_members,=20oldest_multixact=0A+=20=20SELECT=20= num_mxids,=20num_members,=20members_size,=20oldest_multixact=0A=20=20=20= FROM=20pg_get_multixact_stats();=0A=20}=0A=20=0A=20#=20Save=20multixact=20= state=20after=20s1=20has=20locked=20the=20row.=0A=20step=20snap1=20{=0A=20= =20=20CREATE=20TEMP=20TABLE=20snap1=20AS=0A-=20=20SELECT=20num_mxids,=20= num_members,=20oldest_multixact=0A+=20=20SELECT=20num_mxids,=20= num_members,=20members_size,=20oldest_multixact=0A=20=20=20FROM=20= pg_get_multixact_stats();=0A=20}=0A=20=0A@@=20-54,21=20+56,25=20@@=20= step=20snap1=20{=0A=20#=20a=20multixact=20with=20at=20least=202=20= members.=0A=20step=20snap2=20{=0A=20=20=20CREATE=20TEMP=20TABLE=20snap2=20= AS=0A-=20=20SELECT=20num_mxids,=20num_members,=20oldest_multixact=0A+=20=20= SELECT=20num_mxids,=20num_members,=20members_size,=20oldest_multixact=0A=20= =20=20FROM=20pg_get_multixact_stats();=0A=20}=0A=20=0A=20#=20Pretty,=20= deterministic=20key/value=20outputs=20based=20of=20boolean=20checks:=0A=20= #=20=20=20is_init_mxids=20=20=20=20=20=20=20=20=20=20=20=20:=20num_mxids=20= not=20NULL=0A=20#=20=20=20is_init_members=20=20=20=20=20=20=20=20=20=20:=20= num_members=20not=20NULL=0A+#=20=20=20is_init_members_size=20=20=20=20=20= :=20members_size=20not=20NULL=0A=20#=20=20=20is_init_oldest_mxid=20=20=20= =20=20=20:=20oldest_multixact=20not=20NULL=0A=20#=20=20=20= is_oldest_mxid_nondec_01=20:=20oldest_multixact=20not=20decreased=20= (snap0->snap1)=0A=20#=20=20=20is_oldest_mxid_nondec_12=20:=20= oldest_multixact=20did=20not=20decreased=20(snap1->snap2)=0A=20#=20=20=20= is_members_increased_ge1=20:=20members=20increased=20by=20at=20least=201=20= when=20s2=20joined=0A+#=20=20=20is_msize_matches_members=20:=20= members_size=20matches=20the=20member=20count=0A=20#=20=20=20= is_mxids_nondec_01=20=20=20=20=20=20=20:=20num_mxids=20not=20decreased=20= (snap0->snap1)=0A=20#=20=20=20is_mxids_nondec_12=20=20=20=20=20=20=20:=20= num_mxids=20not=20decreased=20(snap1->snap2)=0A=20#=20=20=20= is_members_nondec_01=20=20=20=20=20:=20num_members=20not=20decreased=20= (snap0->snap1)=0A=20#=20=20=20is_members_nondec_12=20=20=20=20=20:=20= num_members=20not=20decreased=20(snap1->snap2)=0A+#=20=20=20= is_msize_nondec_01=20=20=20=20=20=20=20:=20members_size=20not=20= decreased=20(snap0->snap1)=0A+#=20=20=20is_msize_nondec_12=20=20=20=20=20= =20=20:=20members_size=20not=20decreased=20(snap1->snap2)=0A=20step=20= check_while_pinned=20{=0A=20=20=20SELECT=20r.assertion,=20r.ok=0A=20=20=20= FROM=20snap0=20s0=0A@@=20-78,32=20+84,37=20@@=20step=20= check_while_pinned=20{=0A=20=20=20=20=20ARRAY[=0A=20=20=20=20=20=20=20= 'is_init_mxids',=0A=20=20=20=20=20=20=20'is_init_members',=0A+=20=20=20=20= =20=20'is_init_members_size',=0A=20=20=20=20=20=20=20= 'is_init_oldest_mxid',=0A-=20=20=20=20=20=20'is_init_oldest_off',=0A=20=20= =20=20=20=20=20'is_oldest_mxid_nondec_01',=0A=20=20=20=20=20=20=20= 'is_oldest_mxid_nondec_12',=0A-=20=20=20=20=20=20= 'is_oldest_off_nondec_01',=0A-=20=20=20=20=20=20= 'is_oldest_off_nondec_12',=0A=20=20=20=20=20=20=20= 'is_members_increased_ge1',=0A+=20=20=20=20=20=20= 'is_msize_matches_members',=0A=20=20=20=20=20=20=20'is_mxids_nondec_01',=0A= =20=20=20=20=20=20=20'is_mxids_nondec_12',=0A=20=20=20=20=20=20=20= 'is_members_nondec_01',=0A-=20=20=20=20=20=20'is_members_nondec_12'=0A+=20= =20=20=20=20=20'is_members_nondec_12',=0A+=20=20=20=20=20=20= 'is_msize_nondec_01',=0A+=20=20=20=20=20=20'is_msize_nondec_12'=0A=20=20=20= =20=20],=0A=20=20=20=20=20ARRAY[=0A=20=20=20=20=20=20=20(s2.num_mxids=20=20= =20=20=20=20=20=20IS=20NOT=20NULL),=0A=20=20=20=20=20=20=20= (s2.num_members=20=20=20=20=20=20IS=20NOT=20NULL),=0A+=20=20=20=20=20=20= (s2.members_size=20=20=20=20=20IS=20NOT=20NULL),=0A=20=20=20=20=20=20=20= (s2.oldest_multixact=20IS=20NOT=20NULL),=0A=20=0A=20=20=20=20=20=20=20= (s1.oldest_multixact::text::bigint=20>=3D=20= COALESCE(s0.oldest_multixact::text::bigint,=200)),=0A=20=20=20=20=20=20=20= (s2.oldest_multixact::text::bigint=20>=3D=20= COALESCE(s1.oldest_multixact::text::bigint,=200)),=0A=20=0A=20=20=20=20=20= =20=20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200)=20+=201),=0A= +=20=20=20=20=20=20(s2.members_size=20=3D=20s2.num_members=20*=205),=0A=20= =0A=20=20=20=20=20=20=20(s1.num_mxids=20=20=20>=3D=20= COALESCE(s0.num_mxids,=20=20=200)),=0A=20=20=20=20=20=20=20(s2.num_mxids=20= =20=20>=3D=20COALESCE(s1.num_mxids,=20=20=200)),=0A=20=20=20=20=20=20=20= (s1.num_members=20>=3D=20COALESCE(s0.num_members,=200)),=0A-=20=20=20=20=20= =20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200))=0A+=20=20=20=20= =20=20(s2.num_members=20>=3D=20COALESCE(s1.num_members,=200)),=0A+=20=20=20= =20=20=20(s1.members_size=20>=3D=20COALESCE(s0.members_size,=200)),=0A+=20= =20=20=20=20=20(s2.members_size=20>=3D=20COALESCE(s1.members_size,=200))=0A= =20=20=20=20=20]=0A=20=20=20)=20AS=20r(assertion,=20ok);=0A=20}=0A--=20=0A= 2.50.1=20(Apple=20Git-155)=0A=0A= --Apple-Mail=_362AB958-2B93-4C72-A09E-34A545046DB1--