diff --git a/src/include/access/multixact_internal.h b/src/include/access/multixact_internal.h index 82349ea0d32..ba73b3c2e14 100644 --- a/src/include/access/multixact_internal.h +++ b/src/include/access/multixact_internal.h @@ -126,9 +126,11 @@ static inline uint64 MultiXactOffsetStorageSize(MultiXactOffset new_offset, MultiXactOffset old_offset) { + uint64 size_per_member; + Assert(new_offset >= old_offset); - return (uint64) ((new_offset - old_offset) / MULTIXACT_MEMBERS_PER_MEMBERGROUP) * - MULTIXACT_MEMBERGROUP_SIZE; + size_per_member = MULTIXACT_MEMBERGROUP_SIZE / MULTIXACT_MEMBERS_PER_MEMBERGROUP; + return (new_offset - old_offset) * size_per_member; } #endif /* MULTIXACT_INTERNAL_H */ diff --git a/src/test/isolation/expected/multixact-stats.out b/src/test/isolation/expected/multixact-stats.out index 27a6510c4ad..4685bde6d4c 100644 --- a/src/test/isolation/expected/multixact-stats.out +++ b/src/test/isolation/expected/multixact-stats.out @@ -3,7 +3,7 @@ Parsed test spec with 2 sessions starting permutation: snap0 s1_begin s1_lock snap1 s2_begin s2_lock snap2 check_while_pinned s1_commit s2_commit step snap0: CREATE TEMP TABLE snap0 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); step s1_begin: BEGIN; @@ -15,7 +15,7 @@ step s1_lock: SELECT 1 FROM mxq WHERE id=1 FOR KEY SHARE; step snap1: CREATE TEMP TABLE snap1 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); step s2_begin: BEGIN; @@ -27,7 +27,7 @@ step s2_lock: SELECT 1 FROM mxq WHERE id=1 FOR KEY SHARE; step snap2: CREATE TEMP TABLE snap2 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); step check_while_pinned: @@ -39,21 +39,22 @@ step check_while_pinned: ARRAY[ 'is_init_mxids', 'is_init_members', + 'is_init_members_size', 'is_init_oldest_mxid', - 'is_init_oldest_off', 'is_oldest_mxid_nondec_01', 'is_oldest_mxid_nondec_12', - 'is_oldest_off_nondec_01', - 'is_oldest_off_nondec_12', 'is_members_increased_ge1', 'is_mxids_nondec_01', 'is_mxids_nondec_12', 'is_members_nondec_01', - 'is_members_nondec_12' + 'is_members_nondec_12', + 'is_msize_nondec_01', + 'is_msize_nondec_12' ], ARRAY[ (s2.num_mxids IS NOT NULL), (s2.num_members IS NOT NULL), + (s2.members_size IS NOT NULL), (s2.oldest_multixact IS NOT NULL), (s1.oldest_multixact::text::bigint >= COALESCE(s0.oldest_multixact::text::bigint, 0)), @@ -64,7 +65,9 @@ step check_while_pinned: (s1.num_mxids >= COALESCE(s0.num_mxids, 0)), (s2.num_mxids >= COALESCE(s1.num_mxids, 0)), (s1.num_members >= COALESCE(s0.num_members, 0)), - (s2.num_members >= COALESCE(s1.num_members, 0)) + (s2.num_members >= COALESCE(s1.num_members, 0)), + (s1.members_size >= COALESCE(s0.members_size, 0)), + (s2.members_size >= COALESCE(s1.members_size, 0)) ] ) AS r(assertion, ok); @@ -72,17 +75,17 @@ assertion |ok ------------------------+-- is_init_mxids |t is_init_members |t +is_init_members_size |t is_init_oldest_mxid |t -is_init_oldest_off |t is_oldest_mxid_nondec_01|t is_oldest_mxid_nondec_12|t -is_oldest_off_nondec_01 |t -is_oldest_off_nondec_12 |t is_members_increased_ge1|t is_mxids_nondec_01 |t -is_mxids_nondec_12 | -is_members_nondec_01 | -is_members_nondec_12 | +is_mxids_nondec_12 |t +is_members_nondec_01 |t +is_members_nondec_12 |t +is_msize_nondec_01 |t +is_msize_nondec_12 |t (13 rows) step s1_commit: COMMIT; diff --git a/src/test/isolation/specs/multixact-stats.spec b/src/test/isolation/specs/multixact-stats.spec index 07d4b11be6d..b77c40885e6 100644 --- a/src/test/isolation/specs/multixact-stats.spec +++ b/src/test/isolation/specs/multixact-stats.spec @@ -4,8 +4,10 @@ # is pinned by two open transactions, we check some patterns that VACUUM and # FREEZE cannot violate: # 1) "members" increased by at least 1 when the second session locked the row. -# 2) (num_mxids / num_members) not decreased compared to earlier snapshots. -# 3) "oldest_*" fields never decreased. +# 2) "members_size" reflects the storage used by the member entries. +# 3) (num_mxids / num_members / members_size) not decreased compared to +# earlier snapshots. +# 4) "oldest_*" fields never decreased. # # This test does not run checks after releasing locks, as freezing and/or # truncation may shrink the multixact ranges calculated. @@ -39,14 +41,14 @@ step s2_commit { COMMIT; } # multixacts have not initialized yet. step snap0 { CREATE TEMP TABLE snap0 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); } # Save multixact state after s1 has locked the row. step snap1 { CREATE TEMP TABLE snap1 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); } @@ -54,21 +56,24 @@ step snap1 { # a multixact with at least 2 members. step snap2 { CREATE TEMP TABLE snap2 AS - SELECT num_mxids, num_members, oldest_multixact + SELECT num_mxids, num_members, members_size, oldest_multixact FROM pg_get_multixact_stats(); } # Pretty, deterministic key/value outputs based of boolean checks: # is_init_mxids : num_mxids not NULL # is_init_members : num_members not NULL +# is_init_members_size : members_size not NULL # is_init_oldest_mxid : oldest_multixact not NULL # is_oldest_mxid_nondec_01 : oldest_multixact not decreased (snap0->snap1) -# is_oldest_mxid_nondec_12 : oldest_multixact did not decreased (snap1->snap2) +# is_oldest_mxid_nondec_12 : oldest_multixact not decreased (snap1->snap2) # is_members_increased_ge1 : members increased by at least 1 when s2 joined # is_mxids_nondec_01 : num_mxids not decreased (snap0->snap1) # is_mxids_nondec_12 : num_mxids not decreased (snap1->snap2) # is_members_nondec_01 : num_members not decreased (snap0->snap1) # is_members_nondec_12 : num_members not decreased (snap1->snap2) +# is_msize_nondec_01 : members_size not decreased (snap0->snap1) +# is_msize_nondec_12 : members_size not decreased (snap1->snap2) step check_while_pinned { SELECT r.assertion, r.ok FROM snap0 s0 @@ -78,21 +83,22 @@ step check_while_pinned { ARRAY[ 'is_init_mxids', 'is_init_members', + 'is_init_members_size', 'is_init_oldest_mxid', - 'is_init_oldest_off', 'is_oldest_mxid_nondec_01', 'is_oldest_mxid_nondec_12', - 'is_oldest_off_nondec_01', - 'is_oldest_off_nondec_12', 'is_members_increased_ge1', 'is_mxids_nondec_01', 'is_mxids_nondec_12', 'is_members_nondec_01', - 'is_members_nondec_12' + 'is_members_nondec_12', + 'is_msize_nondec_01', + 'is_msize_nondec_12' ], ARRAY[ (s2.num_mxids IS NOT NULL), (s2.num_members IS NOT NULL), + (s2.members_size IS NOT NULL), (s2.oldest_multixact IS NOT NULL), (s1.oldest_multixact::text::bigint >= COALESCE(s0.oldest_multixact::text::bigint, 0)), @@ -103,7 +109,9 @@ step check_while_pinned { (s1.num_mxids >= COALESCE(s0.num_mxids, 0)), (s2.num_mxids >= COALESCE(s1.num_mxids, 0)), (s1.num_members >= COALESCE(s0.num_members, 0)), - (s2.num_members >= COALESCE(s1.num_members, 0)) + (s2.num_members >= COALESCE(s1.num_members, 0)), + (s1.members_size >= COALESCE(s0.members_size, 0)), + (s2.members_size >= COALESCE(s1.members_size, 0)) ] ) AS r(assertion, ok); }