8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.183 2009/03/31 22:12:47 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.184 2009/04/04 17:40:36 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -130,12 +130,14 @@ DefineIndex(RangeVar *heapRelation,
130
130
int numberOfAttributes ;
131
131
VirtualTransactionId * old_lockholders ;
132
132
VirtualTransactionId * old_snapshots ;
133
+ int n_old_snapshots ;
133
134
LockRelId heaprelid ;
134
135
LOCKTAG heaplocktag ;
135
136
Snapshot snapshot ;
136
137
Relation pg_index ;
137
138
HeapTuple indexTuple ;
138
139
Form_pg_index indexForm ;
140
+ int i ;
139
141
140
142
/*
141
143
* count attributes in index
@@ -611,7 +613,7 @@ DefineIndex(RangeVar *heapRelation,
611
613
* snapshot treats as committed. If such a recently-committed transaction
612
614
* deleted tuples in the table, we will not include them in the index; yet
613
615
* those transactions which see the deleting one as still-in-progress will
614
- * expect them to be there once we mark the index as valid.
616
+ * expect such tuples to be there once we mark the index as valid.
615
617
*
616
618
* We solve this by waiting for all endangered transactions to exit before
617
619
* we mark the index as valid.
@@ -634,10 +636,13 @@ DefineIndex(RangeVar *heapRelation,
634
636
* transactions that might have older snapshots. Obtain a list of VXIDs
635
637
* of such transactions, and wait for them individually.
636
638
*
637
- * We can exclude any running transactions that have xmin >= the xmax of
638
- * our reference snapshot, since they are clearly not interested in any
639
- * missing older tuples. Transactions in other DBs aren't a problem
640
- * either, since they'll never even be able to see this index.
639
+ * We can exclude any running transactions that have xmin > the xmin of
640
+ * our reference snapshot; their oldest snapshot must be newer than ours.
641
+ * We can also exclude any transactions that have xmin = zero, since they
642
+ * evidently have no live snapshot at all (and any one they might be
643
+ * in process of taking is certainly newer than ours). Transactions in
644
+ * other DBs can be ignored too, since they'll never even be able to see
645
+ * this index.
641
646
*
642
647
* We can also exclude autovacuum processes and processes running manual
643
648
* lazy VACUUMs, because they won't be fazed by missing index entries
@@ -647,14 +652,54 @@ DefineIndex(RangeVar *heapRelation,
647
652
*
648
653
* Also, GetCurrentVirtualXIDs never reports our own vxid, so we need not
649
654
* check for that.
655
+ *
656
+ * If a process goes idle-in-transaction with xmin zero, we do not need
657
+ * to wait for it anymore, per the above argument. We do not have the
658
+ * infrastructure right now to stop waiting if that happens, but we can
659
+ * at least avoid the folly of waiting when it is idle at the time we
660
+ * would begin to wait. We do this by repeatedly rechecking the output of
661
+ * GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
662
+ * doesn't show up in the output, we know we can forget about it.
650
663
*/
651
- old_snapshots = GetCurrentVirtualXIDs (snapshot -> xmax , false,
652
- PROC_IS_AUTOVACUUM | PROC_IN_VACUUM );
664
+ old_snapshots = GetCurrentVirtualXIDs (snapshot -> xmin , true, false,
665
+ PROC_IS_AUTOVACUUM | PROC_IN_VACUUM ,
666
+ & n_old_snapshots );
653
667
654
- while ( VirtualTransactionIdIsValid ( * old_snapshots ) )
668
+ for ( i = 0 ; i < n_old_snapshots ; i ++ )
655
669
{
656
- VirtualXactLockTableWait (* old_snapshots );
657
- old_snapshots ++ ;
670
+ if (!VirtualTransactionIdIsValid (old_snapshots [i ]))
671
+ continue ; /* found uninteresting in previous cycle */
672
+
673
+ if (i > 0 )
674
+ {
675
+ /* see if anything's changed ... */
676
+ VirtualTransactionId * newer_snapshots ;
677
+ int n_newer_snapshots ;
678
+ int j ;
679
+ int k ;
680
+
681
+ newer_snapshots = GetCurrentVirtualXIDs (snapshot -> xmin ,
682
+ true, false,
683
+ PROC_IS_AUTOVACUUM | PROC_IN_VACUUM ,
684
+ & n_newer_snapshots );
685
+ for (j = i ; j < n_old_snapshots ; j ++ )
686
+ {
687
+ if (!VirtualTransactionIdIsValid (old_snapshots [j ]))
688
+ continue ; /* found uninteresting in previous cycle */
689
+ for (k = 0 ; k < n_newer_snapshots ; k ++ )
690
+ {
691
+ if (VirtualTransactionIdEquals (old_snapshots [j ],
692
+ newer_snapshots [k ]))
693
+ break ;
694
+ }
695
+ if (k >= n_newer_snapshots ) /* not there anymore */
696
+ SetInvalidVirtualTransactionId (old_snapshots [j ]);
697
+ }
698
+ pfree (newer_snapshots );
699
+ }
700
+
701
+ if (VirtualTransactionIdIsValid (old_snapshots [i ]))
702
+ VirtualXactLockTableWait (old_snapshots [i ]);
658
703
}
659
704
660
705
/*
0 commit comments