From 0a75015e109f5c58db9440215e8a88540c5ed119 Mon Sep 17 00:00:00 2001 From: Arseniy Mukhin Date: Tue, 22 Jul 2025 17:37:13 +0300 Subject: [PATCH v8 3/4] amcheck: common_verify - register snapshot with indcheckxmin check Moves check to common_verify. Every index needs it for heapallindexed check. --- contrib/amcheck/verify_common.c | 29 +++++++++++++++++++++++++++++ contrib/amcheck/verify_common.h | 2 ++ contrib/amcheck/verify_nbtree.c | 23 +---------------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/contrib/amcheck/verify_common.c b/contrib/amcheck/verify_common.c index a31ce06ed99..bbcefe82898 100644 --- a/contrib/amcheck/verify_common.c +++ b/contrib/amcheck/verify_common.c @@ -189,3 +189,32 @@ index_checkable(Relation rel, Oid am_id) return amcheck_index_mainfork_expected(rel); } + +/* + * GetTransactionSnapshot() always acquires a new MVCC snapshot in + * READ COMMITTED mode. A new snapshot is guaranteed to have all + * the entries it requires in the index. + * + * We must defend against the possibility that an old xact + * snapshot was returned at higher isolation levels when that + * snapshot is not safe for index scans of the target index. This + * is possible when the snapshot sees tuples that are before the + * index's indcheckxmin horizon. Throwing an error here should be + * very rare. It doesn't seem worth using a secondary snapshot to + * avoid this. + */ +Snapshot +RegisterSnapshotAndCheckIndexCheckXMin(Relation idxrel) +{ + Snapshot snapshot = RegisterSnapshot(GetTransactionSnapshot()); + + if (IsolationUsesXactSnapshot() && idxrel->rd_index->indcheckxmin && + !TransactionIdPrecedes(HeapTupleHeaderGetXmin(idxrel->rd_indextuple->t_data), + snapshot->xmin)) + ereport(ERROR, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("index \"%s\" cannot be verified using transaction snapshot", + RelationGetRelationName(idxrel)))); + + return snapshot; +} diff --git a/contrib/amcheck/verify_common.h b/contrib/amcheck/verify_common.h index 3f4c57f963d..7679e33da77 100644 --- a/contrib/amcheck/verify_common.h +++ b/contrib/amcheck/verify_common.h @@ -26,3 +26,5 @@ extern void amcheck_lock_relation_and_check(Oid indrelid, Oid am_id, IndexDoCheckCallback check, LOCKMODE lockmode, void *state); + +extern Snapshot RegisterSnapshotAndCheckIndexCheckXMin(Relation idxrel); diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 0949c88983a..c9aa9044045 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -441,28 +441,7 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace, */ if (!state->readonly) { - snapshot = RegisterSnapshot(GetTransactionSnapshot()); - - /* - * GetTransactionSnapshot() always acquires a new MVCC snapshot in - * READ COMMITTED mode. A new snapshot is guaranteed to have all - * the entries it requires in the index. - * - * We must defend against the possibility that an old xact - * snapshot was returned at higher isolation levels when that - * snapshot is not safe for index scans of the target index. This - * is possible when the snapshot sees tuples that are before the - * index's indcheckxmin horizon. Throwing an error here should be - * very rare. It doesn't seem worth using a secondary snapshot to - * avoid this. - */ - if (IsolationUsesXactSnapshot() && rel->rd_index->indcheckxmin && - !TransactionIdPrecedes(HeapTupleHeaderGetXmin(rel->rd_indextuple->t_data), - snapshot->xmin)) - ereport(ERROR, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("index \"%s\" cannot be verified using transaction snapshot", - RelationGetRelationName(rel)))); + snapshot = RegisterSnapshotAndCheckIndexCheckXMin(state->rel); } } -- 2.43.0