From ce05a7df141e2c98f54578ab0dd82b1ac32f3e3b Mon Sep 17 00:00:00 2001 From: Andrey Borodin Date: Tue, 21 Jul 2026 19:44:40 +0500 Subject: [PATCH v6 4/4] doc: document indexallkeysmatch parameter for amcheck B-Tree verification Add indexallkeysmatch to bt_index_check and bt_index_parent_check signatures, describe the parameter, add a dedicated section explaining the verification, and mention it in the corruption detection list. Note that when both heapallindexed and indexallkeysmatch are enabled, two Bloom filters are allocated, each up to maintenance_work_mem, and that the check has the same ~2% per-tuple probability of missing an inconsistency as heapallindexed. Explain which dangling index entry cases are reported at each lock level. Author: Andrey Borodin Reviewed-by: Zsolt Parragi Discussion: https://www.postgresql.org/message-id/flat/432626F9-65DF-4F0D-B345-26CFC3E2CFAC@yandex-team.ru --- doc/src/sgml/amcheck.sgml | 71 +++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/amcheck.sgml b/doc/src/sgml/amcheck.sgml index 13a6bb18897..ec5111ca969 100644 --- a/doc/src/sgml/amcheck.sgml +++ b/doc/src/sgml/amcheck.sgml @@ -61,7 +61,7 @@ - bt_index_check(index regclass, heapallindexed boolean, checkunique boolean) returns void + bt_index_check(index regclass, heapallindexed boolean, checkunique boolean, indexallkeysmatch boolean) returns void bt_index_check @@ -118,7 +118,10 @@ ORDER BY c.relpages DESC LIMIT 10; that span child/parent relationships, but will verify the presence of all heap tuples as index tuples within the index when heapallindexed is - true. When checkunique + true. When indexallkeysmatch + is true, it verifies that each index tuple + points to a heap tuple with the same key (the reverse of + heapallindexed). When checkunique is true bt_index_check will check that no more than one among duplicate entries in unique index is visible. When a routine, lightweight test for @@ -132,7 +135,7 @@ ORDER BY c.relpages DESC LIMIT 10; - bt_index_parent_check(index regclass, heapallindexed boolean, rootdescend boolean, checkunique boolean) returns void + bt_index_parent_check(index regclass, heapallindexed boolean, rootdescend boolean, checkunique boolean, indexallkeysmatch boolean) returns void bt_index_parent_check @@ -145,7 +148,9 @@ ORDER BY c.relpages DESC LIMIT 10; Optionally, when the heapallindexed argument is true, the function verifies the presence of all heap tuples that should be found within the - index. When checkunique + index. When indexallkeysmatch is + true, it verifies that each index tuple + points to a heap tuple with the same key. When checkunique is true bt_index_parent_check will check that no more than one among duplicate entries in unique index is visible. When the optional rootdescend @@ -413,6 +418,57 @@ SET client_min_messages = DEBUG1; single absent or malformed tuple has a new opportunity to be detected with each new verification attempt. + + When both heapallindexed and + indexallkeysmatch are enabled, two Bloom + filters are allocated, each up to maintenance_work_mem. + + + + + + Optional <parameter>indexallkeysmatch</parameter> Verification + + When the indexallkeysmatch argument to B-Tree + verification functions is true, an additional + phase verifies that each index tuple points to a heap tuple with the + same key. This is the reverse of heapallindexed: + heapallindexed checks that every heap tuple is + in the index, while indexallkeysmatch checks + that every index tuple points to a matching heap tuple. + + + The implementation uses a Bloom filter to amortize random heap + lookups. A sequential heap scan first fingerprints all visible + (key, tid) pairs. During the index scan, each leaf tuple is probed + against this filter. Only when the filter says "not present" does + an actual heap fetch and key comparison occur. Corruption is + reported when the heap tuple's key (as computed by + FormIndexDatum) differs from the index tuple's + key, or when an index tuple points to a heap block beyond the end of + the table. Additionally, bt_index_parent_check + reports index tuples pointing to unused heap slots; under the weaker + lock taken by bt_index_check such slots cannot + be reliably distinguished from tuples concurrently removed by + VACUUM, so they are skipped. + + + Like heapallindexed, this check requires an + MVCC snapshot to obtain a consistent view of the heap and index. + The heap lookup follows HOT chains the same way a + regular index scan does; index tuples that point to dead heap tuples + (not visible to the snapshot) are skipped. + + + The summarizing structure is bound in size by + maintenance_work_mem, using the same sizing + approach as heapallindexed. In order to ensure + that there is no more than a 2% probability of failure to detect an + inconsistency for each index tuple that should match a heap tuple, + approximately 2 bytes of memory are needed per tuple. As less memory + is made available per tuple, the probability of missing an + inconsistency slowly increases. + @@ -457,12 +513,15 @@ SET client_min_messages = DEBUG1; Structural inconsistencies between indexes and the heap relations - that are indexed (when heapallindexed - verification is performed). + that are indexed (when heapallindexed or + indexallkeysmatch verification is performed). There is no cross-checking of indexes against their heap relation during normal operation. Symptoms of heap corruption can be subtle. + indexallkeysmatch detects cases where an index + tuple stores a different key than the heap tuple it points to, or + points to a non-existent heap slot. -- 2.50.1 (Apple Git-155)