@ -508,7 +508,6 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
BTMetaPageData * metad ;
BTMetaPageData * metad ;
uint32 previouslevel ;
uint32 previouslevel ;
BtreeLevel current ;
BtreeLevel current ;
Snapshot snapshot = SnapshotAny ;
if ( ! readonly )
if ( ! readonly )
elog ( DEBUG1 , " verifying consistency of tree structure for index \" %s \" " ,
elog ( DEBUG1 , " verifying consistency of tree structure for index \" %s \" " ,
@ -559,54 +558,46 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
state - > heaptuplespresent = 0 ;
state - > heaptuplespresent = 0 ;
/*
/*
* Register our own snapshot in ! readonly case , rather than asking
* Register our own snapshot for heapallindexed , rather than asking
* table_index_build_scan ( ) to do this for us later . This needs to
* table_index_build_scan ( ) to do this for us later . This needs to
* happen before index fingerprinting begins , so we can later be
* happen before index fingerprinting begins , so we can later be
* certain that index fingerprinting should have reached all tuples
* certain that index fingerprinting should have reached all tuples
* returned by table_index_build_scan ( ) .
* returned by table_index_build_scan ( ) .
*/
*/
if ( ! state - > readonly )
state - > snapshot = RegisterSnapshot ( GetTransactionSnapshot ( ) ) ;
{
snapshot = RegisterSnapshot ( GetTransactionSnapshot ( ) ) ;
/*
/*
* GetTransactionSnapshot ( ) always acquires a new MVCC snapshot in
* GetTransactionSnapshot ( ) always acquires a new MVCC snapshot in
* READ COMMITTED mode . A new snapshot is guaranteed to have all
* READ COMMITTED mode . A new snapshot is guaranteed to have all the
* the entries it requires in the index .
* entries it requires in the index .
*
*
* We must defend against the possibility that an old xact
* We must defend against the possibility that an old xact snapshot
* snapshot was returned at higher isolation levels when that
* was returned at higher isolation levels when that snapshot is not
* snapshot is not safe for index scans of the target index . This
* safe for index scans of the target index . This is possible when
* is possible when the snapshot sees tuples that are before the
* the snapshot sees tuples that are before the index ' s indcheckxmin
* index ' s indcheckxmin horizon . Throwing an error here should be
* horizon . Throwing an error here should be very rare . It doesn ' t
* very rare . It doesn ' t seem worth using a secondary snapshot to
* seem worth using a secondary snapshot to avoid this .
* avoid this .
*/
*/
if ( IsolationUsesXactSnapshot ( ) & & rel - > rd_index - > indcheckxmin & &
if ( IsolationUsesXactSnapshot ( ) & & rel - > rd_index - > indcheckxmin & &
! TransactionIdPrecedes ( HeapTupleHeaderGetXmin ( rel - > rd_indextuple - > t_data ) ,
! TransactionIdPrecedes ( HeapTupleHeaderGetXmin ( rel - > rd_indextuple - > t_data ) ,
state - > snapshot - > xmin ) )
snapshot - > xmin ) )
ereport ( ERROR ,
ereport ( ERROR ,
errcode ( ERRCODE_T_R_SERIALIZATION_FAILURE ) ,
( errcode ( ERRCODE_T_R_SERIALIZATION_FAILURE ) ,
errmsg ( " index \" %s \" cannot be verified using transaction snapshot " ,
errmsg ( " index \" %s \" cannot be verified using transaction snapshot " ,
RelationGetRelationName ( rel ) ) ) ;
RelationGetRelationName ( rel ) ) ) ) ;
}
}
}
/*
/*
* We need a snapshot to check the uniqueness of the index . For better
* We need a snapshot to check the uniqueness of the index . For better
* performance take it once per index check . If snapshot already taken
* performance , take it once per index check . If one was already taken
* reuse i t.
* above , use tha t.
*/
*/
if ( state - > checkunique )
if ( state - > checkunique )
{
{
state - > indexinfo = BuildIndexInfo ( state - > rel ) ;
state - > indexinfo = BuildIndexInfo ( state - > rel ) ;
if ( state - > indexinfo - > ii_Unique )
{
if ( state - > indexinfo - > ii_Unique & & state - > snapshot = = InvalidSnapshot )
if ( snapshot ! = SnapshotAny )
state - > snapshot = RegisterSnapshot ( GetTransactionSnapshot ( ) ) ;
state - > snapshot = snapshot ;
else
state - > snapshot = RegisterSnapshot ( GetTransactionSnapshot ( ) ) ;
}
}
}
Assert ( ! state - > rootdescend | | state - > readonly ) ;
Assert ( ! state - > rootdescend | | state - > readonly ) ;
@ -681,13 +672,12 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
/*
/*
* Create our own scan for table_index_build_scan ( ) , rather than
* Create our own scan for table_index_build_scan ( ) , rather than
* getting it to do so for us . This is required so that we can
* getting it to do so for us . This is required so that we can
* actually use the MVCC snapshot registered earlier in ! readonly
* actually use the MVCC snapshot registered earlier .
* case .
*
*
* Note that table_index_build_scan ( ) calls heap_endscan ( ) for us .
* Note that table_index_build_scan ( ) calls heap_endscan ( ) for us .
*/
*/
scan = table_beginscan_strat ( state - > heaprel , /* relation */
scan = table_beginscan_strat ( state - > heaprel , /* relation */
snapshot , /* snapshot */
state - > s napshot , /* snapshot */
0 , /* number of keys */
0 , /* number of keys */
NULL , /* scan key */
NULL , /* scan key */
true , /* buffer access strategy OK */
true , /* buffer access strategy OK */
@ -695,16 +685,15 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
/*
/*
* Scan will behave as the first scan of a CREATE INDEX CONCURRENTLY
* Scan will behave as the first scan of a CREATE INDEX CONCURRENTLY
* behaves in ! readonly case .
* behaves .
*
*
* It ' s okay that we don ' t actually use the same lock strength for the
* It ' s okay that we don ' t actually use the same lock strength for the
* heap relation as any other ii_Concurrent caller would in ! readonly
* heap relation as any other ii_Concurrent caller would . We have no
* case . We have no reason to care about a concurrent VACUUM
* reason to care about a concurrent VACUUM operation , since there
* operation , since there isn ' t going to be a second scan of the heap
* isn ' t going to be a second scan of the heap that needs to be sure
* that needs to be sure that there was no concurrent recycling of
* that there was no concurrent recycling of TIDs .
* TIDs .
*/
*/
indexinfo - > ii_Concurrent = ! state - > readonly ;
indexinfo - > ii_Concurrent = true ;
/*
/*
* Don ' t wait for uncommitted tuple xact commit / abort when index is a
* Don ' t wait for uncommitted tuple xact commit / abort when index is a
@ -728,14 +717,11 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
state - > heaptuplespresent , RelationGetRelationName ( heaprel ) ,
state - > heaptuplespresent , RelationGetRelationName ( heaprel ) ,
100.0 * bloom_prop_bits_set ( state - > filter ) ) ) ) ;
100.0 * bloom_prop_bits_set ( state - > filter ) ) ) ) ;
if ( snapshot ! = SnapshotAny )
UnregisterSnapshot ( snapshot ) ;
bloom_free ( state - > filter ) ;
bloom_free ( state - > filter ) ;
}
}
/* Be tidy: */
/* Be tidy: */
if ( snapshot = = SnapshotAny & & s tate - > snapshot ! = InvalidSnapshot )
if ( state - > snapshot ! = InvalidSnapshot )
UnregisterSnapshot ( state - > snapshot ) ;
UnregisterSnapshot ( state - > snapshot ) ;
MemoryContextDelete ( state - > targetcontext ) ;
MemoryContextDelete ( state - > targetcontext ) ;
}
}