Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 813fb03

Browse files
committed
Remove SnapshotNow and HeapTupleSatisfiesNow.
We now use MVCC catalog scans, and, per discussion, have eliminated all other remaining uses of SnapshotNow, so that we can now get rid of it. This will break third-party code which is still using it, which is intentional, as we want such code to be updated to do things the new way.
1 parent aad2a63 commit 813fb03

File tree

5 files changed

+16
-273
lines changed

5 files changed

+16
-273
lines changed

src/backend/catalog/index.c

+8-17
Original file line numberDiff line numberDiff line change
@@ -1258,10 +1258,8 @@ index_constraint_create(Relation heapRelation,
12581258
/*
12591259
* If needed, mark the index as primary and/or deferred in pg_index.
12601260
*
1261-
* Note: since this is a transactional update, it's unsafe against
1262-
* concurrent SnapshotNow scans of pg_index. When making an existing
1263-
* index into a constraint, caller must have a table lock that prevents
1264-
* concurrent table updates; if it's less than a full exclusive lock,
1261+
* Note: When making an existing index into a constraint, caller must
1262+
* have a table lock that prevents concurrent table updates; otherwise,
12651263
* there is a risk that concurrent readers of the table will miss seeing
12661264
* this index at all.
12671265
*/
@@ -2989,17 +2987,18 @@ validate_index_heapscan(Relation heapRelation,
29892987
* index_set_state_flags - adjust pg_index state flags
29902988
*
29912989
* This is used during CREATE/DROP INDEX CONCURRENTLY to adjust the pg_index
2992-
* flags that denote the index's state. We must use an in-place update of
2993-
* the pg_index tuple, because we do not have exclusive lock on the parent
2994-
* table and so other sessions might concurrently be doing SnapshotNow scans
2995-
* of pg_index to identify the table's indexes. A transactional update would
2996-
* risk somebody not seeing the index at all. Because the update is not
2990+
* flags that denote the index's state. Because the update is not
29972991
* transactional and will not roll back on error, this must only be used as
29982992
* the last step in a transaction that has not made any transactional catalog
29992993
* updates!
30002994
*
30012995
* Note that heap_inplace_update does send a cache inval message for the
30022996
* tuple, so other sessions will hear about the update as soon as we commit.
2997+
*
2998+
* NB: In releases prior to PostgreSQL 9.4, the use of a non-transactional
2999+
* update here would have been unsafe; now that MVCC rules apply even for
3000+
* system catalog scans, we could potentially use a transactional update here
3001+
* instead.
30033002
*/
30043003
void
30053004
index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
@@ -3207,14 +3206,6 @@ reindex_index(Oid indexId, bool skip_constraint_checks)
32073206
* be conservative.) In this case advancing the usability horizon is
32083207
* appropriate.
32093208
*
3210-
* Note that if we have to update the tuple, there is a risk of concurrent
3211-
* transactions not seeing it during their SnapshotNow scans of pg_index.
3212-
* While not especially desirable, this is safe because no such
3213-
* transaction could be trying to update the table (since we have
3214-
* ShareLock on it). The worst case is that someone might transiently
3215-
* fail to use the index for a query --- but it was probably unusable
3216-
* before anyway, if we are updating the tuple.
3217-
*
32183209
* Another reason for avoiding unnecessary updates here is that while
32193210
* reindexing pg_index itself, we must not try to update tuples in it.
32203211
* pg_index's indexes should always have these flags in their clean state,

src/backend/catalog/pg_enum.c

+3-24
Original file line numberDiff line numberDiff line change
@@ -462,30 +462,9 @@ AddEnumLabel(Oid enumTypeOid,
462462
* Renumber existing enum elements to have sort positions 1..n.
463463
*
464464
* We avoid doing this unless absolutely necessary; in most installations
465-
* it will never happen. The reason is that updating existing pg_enum
466-
* entries creates hazards for other backends that are concurrently reading
467-
* pg_enum with SnapshotNow semantics. A concurrent SnapshotNow scan could
468-
* see both old and new versions of an updated row as valid, or neither of
469-
* them, if the commit happens between scanning the two versions. It's
470-
* also quite likely for a concurrent scan to see an inconsistent set of
471-
* rows (some members updated, some not).
472-
*
473-
* We can avoid these risks by reading pg_enum with an MVCC snapshot
474-
* instead of SnapshotNow, but that forecloses use of the syscaches.
475-
* We therefore make the following choices:
476-
*
477-
* 1. Any code that is interested in the enumsortorder values MUST read
478-
* pg_enum with an MVCC snapshot, or else acquire lock on the enum type
479-
* to prevent concurrent execution of AddEnumLabel(). The risk of
480-
* seeing inconsistent values of enumsortorder is too high otherwise.
481-
*
482-
* 2. Code that is not examining enumsortorder can use a syscache
483-
* (for example, enum_in and enum_out do so). The worst that can happen
484-
* is a transient failure to find any valid value of the row. This is
485-
* judged acceptable in view of the infrequency of use of RenumberEnumType.
486-
*
487-
* XXX. Now that we have MVCC catalog scans, the above reasoning is no longer
488-
* correct. Should we revisit any decisions here?
465+
* it will never happen. Before we had MVCC catalog scans, this function
466+
* posed various concurrency hazards. It no longer does, but it's still
467+
* extra work, so we don't do it unless it's needed.
489468
*/
490469
static void
491470
RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems)

src/backend/commands/cluster.c

-10
Original file line numberDiff line numberDiff line change
@@ -476,16 +476,6 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD
476476
* mark_index_clustered: mark the specified index as the one clustered on
477477
*
478478
* With indexOid == InvalidOid, will mark all indexes of rel not-clustered.
479-
*
480-
* Note: we do transactional updates of the pg_index rows, which are unsafe
481-
* against concurrent SnapshotNow scans of pg_index. Therefore this is unsafe
482-
* to execute with less than full exclusive lock on the parent table;
483-
* otherwise concurrent executions of RelationGetIndexList could miss indexes.
484-
*
485-
* XXX: Now that we have MVCC catalog access, SnapshotNow scans of pg_index
486-
* shouldn't be common enough to worry about. The above comment needs
487-
* to be updated, and it may be possible to simplify the logic here in other
488-
* ways also.
489479
*/
490480
void
491481
mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)

src/backend/utils/time/tqual.c

+5-218
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@
3030
*
3131
* HeapTupleSatisfiesMVCC()
3232
* visible to supplied snapshot, excludes current command
33-
* HeapTupleSatisfiesNow()
34-
* visible to instant snapshot, excludes current command
3533
* HeapTupleSatisfiesUpdate()
36-
* like HeapTupleSatisfiesNow(), but with user-supplied command
34+
* visible to instant snapshot, with user-supplied command
3735
* counter and more complex result
3836
* HeapTupleSatisfiesSelf()
3937
* visible to instant snapshot and current command
@@ -68,7 +66,6 @@
6866

6967

7068
/* Static variables representing various special snapshot semantics */
71-
SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow};
7269
SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
7370
SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
7471
SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast};
@@ -323,212 +320,6 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
323320
return false;
324321
}
325322

326-
/*
327-
* HeapTupleSatisfiesNow
328-
* True iff heap tuple is valid "now".
329-
*
330-
* Here, we consider the effects of:
331-
* all committed transactions (as of the current instant)
332-
* previous commands of this transaction
333-
*
334-
* Note we do _not_ include changes made by the current command. This
335-
* solves the "Halloween problem" wherein an UPDATE might try to re-update
336-
* its own output tuples, http://en.wikipedia.org/wiki/Halloween_Problem.
337-
*
338-
* Note:
339-
* Assumes heap tuple is valid.
340-
*
341-
* The satisfaction of "now" requires the following:
342-
*
343-
* ((Xmin == my-transaction && inserted by the current transaction
344-
* Cmin < my-command && before this command, and
345-
* (Xmax is null || the row has not been deleted, or
346-
* (Xmax == my-transaction && it was deleted by the current transaction
347-
* Cmax >= my-command))) but not before this command,
348-
* || or
349-
* (Xmin is committed && the row was inserted by a committed transaction, and
350-
* (Xmax is null || the row has not been deleted, or
351-
* (Xmax == my-transaction && the row is being deleted by this transaction
352-
* Cmax >= my-command) || but it's not deleted "yet", or
353-
* (Xmax != my-transaction && the row was deleted by another transaction
354-
* Xmax is not committed)))) that has not been committed
355-
*
356-
*/
357-
bool
358-
HeapTupleSatisfiesNow(HeapTuple htup, Snapshot snapshot, Buffer buffer)
359-
{
360-
HeapTupleHeader tuple = htup->t_data;
361-
Assert(ItemPointerIsValid(&htup->t_self));
362-
Assert(htup->t_tableOid != InvalidOid);
363-
364-
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
365-
{
366-
if (tuple->t_infomask & HEAP_XMIN_INVALID)
367-
return false;
368-
369-
/* Used by pre-9.0 binary upgrades */
370-
if (tuple->t_infomask & HEAP_MOVED_OFF)
371-
{
372-
TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
373-
374-
if (TransactionIdIsCurrentTransactionId(xvac))
375-
return false;
376-
if (!TransactionIdIsInProgress(xvac))
377-
{
378-
if (TransactionIdDidCommit(xvac))
379-
{
380-
SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
381-
InvalidTransactionId);
382-
return false;
383-
}
384-
SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
385-
InvalidTransactionId);
386-
}
387-
}
388-
/* Used by pre-9.0 binary upgrades */
389-
else if (tuple->t_infomask & HEAP_MOVED_IN)
390-
{
391-
TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
392-
393-
if (!TransactionIdIsCurrentTransactionId(xvac))
394-
{
395-
if (TransactionIdIsInProgress(xvac))
396-
return false;
397-
if (TransactionIdDidCommit(xvac))
398-
SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
399-
InvalidTransactionId);
400-
else
401-
{
402-
SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
403-
InvalidTransactionId);
404-
return false;
405-
}
406-
}
407-
}
408-
else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
409-
{
410-
if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false))
411-
return false; /* inserted after scan started */
412-
413-
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
414-
return true;
415-
416-
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
417-
return true;
418-
419-
if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
420-
{
421-
TransactionId xmax;
422-
423-
xmax = HeapTupleGetUpdateXid(tuple);
424-
if (!TransactionIdIsValid(xmax))
425-
return true;
426-
427-
/* updating subtransaction must have aborted */
428-
if (!TransactionIdIsCurrentTransactionId(xmax))
429-
return true;
430-
else
431-
return false;
432-
}
433-
434-
if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
435-
{
436-
/* deleting subtransaction must have aborted */
437-
SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
438-
InvalidTransactionId);
439-
return true;
440-
}
441-
442-
if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
443-
return true; /* deleted after scan started */
444-
else
445-
return false; /* deleted before scan started */
446-
}
447-
else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
448-
return false;
449-
else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
450-
SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
451-
HeapTupleHeaderGetXmin(tuple));
452-
else
453-
{
454-
/* it must have aborted or crashed */
455-
SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
456-
InvalidTransactionId);
457-
return false;
458-
}
459-
}
460-
461-
/* by here, the inserting transaction has committed */
462-
463-
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
464-
return true;
465-
466-
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
467-
{
468-
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
469-
return true;
470-
return false;
471-
}
472-
473-
if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
474-
{
475-
TransactionId xmax;
476-
477-
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
478-
return true;
479-
480-
xmax = HeapTupleGetUpdateXid(tuple);
481-
if (!TransactionIdIsValid(xmax))
482-
return true;
483-
if (TransactionIdIsCurrentTransactionId(xmax))
484-
{
485-
if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
486-
return true; /* deleted after scan started */
487-
else
488-
return false; /* deleted before scan started */
489-
}
490-
if (TransactionIdIsInProgress(xmax))
491-
return true;
492-
if (TransactionIdDidCommit(xmax))
493-
return false;
494-
return true;
495-
}
496-
497-
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
498-
{
499-
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
500-
return true;
501-
if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
502-
return true; /* deleted after scan started */
503-
else
504-
return false; /* deleted before scan started */
505-
}
506-
507-
if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
508-
return true;
509-
510-
if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
511-
{
512-
/* it must have aborted or crashed */
513-
SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
514-
InvalidTransactionId);
515-
return true;
516-
}
517-
518-
/* xmax transaction committed */
519-
520-
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
521-
{
522-
SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
523-
InvalidTransactionId);
524-
return true;
525-
}
526-
527-
SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
528-
HeapTupleHeaderGetRawXmax(tuple));
529-
return false;
530-
}
531-
532323
/*
533324
* HeapTupleSatisfiesAny
534325
* Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
@@ -614,10 +405,10 @@ HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
614405
/*
615406
* HeapTupleSatisfiesUpdate
616407
*
617-
* Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
618-
* code, since UPDATE needs to know more than "is it visible?". Also,
619-
* tuples of my own xact are tested against the passed CommandId not
620-
* CurrentCommandId.
408+
* This function returns a more detailed result code than most of the
409+
* functions in this file, since UPDATE needs to know more than "is it
410+
* visible?". It also allows for user-supplied CommandId rather than
411+
* relying on CurrentCommandId.
621412
*
622413
* The possible return codes are:
623414
*
@@ -1051,10 +842,6 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
1051842
* transactions started after the snapshot was taken
1052843
* changes made by the current command
1053844
*
1054-
* This is the same as HeapTupleSatisfiesNow, except that transactions that
1055-
* were in progress or as yet unstarted when the snapshot was taken will
1056-
* be treated as uncommitted, even if they have committed by now.
1057-
*
1058845
* (Notice, however, that the tuple status hint bits will be updated on the
1059846
* basis of the true state of the transaction, even if we then pretend we
1060847
* can't see it.)

src/include/utils/tqual.h

-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919

2020

2121
/* Static variables representing various special snapshot semantics */
22-
extern PGDLLIMPORT SnapshotData SnapshotNowData;
2322
extern PGDLLIMPORT SnapshotData SnapshotSelfData;
2423
extern PGDLLIMPORT SnapshotData SnapshotAnyData;
2524
extern PGDLLIMPORT SnapshotData SnapshotToastData;
2625

27-
#define SnapshotNow (&SnapshotNowData)
2826
#define SnapshotSelf (&SnapshotSelfData)
2927
#define SnapshotAny (&SnapshotAnyData)
3028
#define SnapshotToast (&SnapshotToastData)
@@ -67,8 +65,6 @@ typedef enum
6765
/* These are the "satisfies" test routines for the various snapshot types */
6866
extern bool HeapTupleSatisfiesMVCC(HeapTuple htup,
6967
Snapshot snapshot, Buffer buffer);
70-
extern bool HeapTupleSatisfiesNow(HeapTuple htup,
71-
Snapshot snapshot, Buffer buffer);
7268
extern bool HeapTupleSatisfiesSelf(HeapTuple htup,
7369
Snapshot snapshot, Buffer buffer);
7470
extern bool HeapTupleSatisfiesAny(HeapTuple htup,

0 commit comments

Comments
 (0)