PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
predicate.h File Reference
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for predicate.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NUM_OLDSERXID_BUFFERS   16
 

Functions

void InitPredicateLocks (void)
 
Size PredicateLockShmemSize (void)
 
void CheckPointPredicate (void)
 
bool PageIsPredicateLocked (Relation relation, BlockNumber blkno)
 
Snapshot GetSerializableTransactionSnapshot (Snapshot snapshot)
 
void SetSerializableTransactionSnapshot (Snapshot snapshot, TransactionId sourcexid)
 
void RegisterPredicateLockingXid (TransactionId xid)
 
void PredicateLockRelation (Relation relation, Snapshot snapshot)
 
void PredicateLockPage (Relation relation, BlockNumber blkno, Snapshot snapshot)
 
void PredicateLockTuple (Relation relation, HeapTuple tuple, Snapshot snapshot)
 
void PredicateLockPageSplit (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void PredicateLockPageCombine (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void TransferPredicateLocksToHeapRelation (Relation relation)
 
void ReleasePredicateLocks (bool isCommit)
 
void CheckForSerializableConflictOut (bool valid, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
 
void CheckForSerializableConflictIn (Relation relation, HeapTuple tuple, Buffer buffer)
 
void CheckTableForSerializableConflictIn (Relation relation)
 
void PreCommit_CheckForSerializationFailure (void)
 
void AtPrepare_PredicateLocks (void)
 
void PostPrepare_PredicateLocks (TransactionId xid)
 
void PredicateLockTwoPhaseFinish (TransactionId xid, bool isCommit)
 
void predicatelock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 

Variables

int max_predicate_locks_per_xact
 

Macro Definition Documentation

#define NUM_OLDSERXID_BUFFERS   16

Definition at line 28 of file predicate.h.

Referenced by OldSerXidInit(), and PredicateLockShmemSize().

Function Documentation

void AtPrepare_PredicateLocks ( void  )

Definition at line 4722 of file predicate.c.

References TwoPhasePredicateRecord::data, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, NULL, offsetof, SERIALIZABLEXACT::predicateLocks, RegisterTwoPhaseRecord(), SHMQueueNext(), PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, TwoPhasePredicateLockRecord::target, TWOPHASE_RM_PREDICATELOCK_ID, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, PREDICATELOCK::xactLink, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

Referenced by PrepareTransaction().

4723 {
4724  PREDICATELOCK *predlock;
4725  SERIALIZABLEXACT *sxact;
4726  TwoPhasePredicateRecord record;
4727  TwoPhasePredicateXactRecord *xactRecord;
4728  TwoPhasePredicateLockRecord *lockRecord;
4729 
4730  sxact = MySerializableXact;
4731  xactRecord = &(record.data.xactRecord);
4732  lockRecord = &(record.data.lockRecord);
4733 
4735  return;
4736 
4737  /* Generate an xact record for our SERIALIZABLEXACT */
4739  xactRecord->xmin = MySerializableXact->xmin;
4740  xactRecord->flags = MySerializableXact->flags;
4741 
4742  /*
4743  * Note that we don't include the list of conflicts in our out in the
4744  * statefile, because new conflicts can be added even after the
4745  * transaction prepares. We'll just make a conservative assumption during
4746  * recovery instead.
4747  */
4748 
4750  &record, sizeof(record));
4751 
4752  /*
4753  * Generate a lock record for each lock.
4754  *
4755  * To do this, we need to walk the predicate lock list in our sxact rather
4756  * than using the local predicate lock table because the latter is not
4757  * guaranteed to be accurate.
4758  */
4759  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4760 
4761  predlock = (PREDICATELOCK *)
4762  SHMQueueNext(&(sxact->predicateLocks),
4763  &(sxact->predicateLocks),
4764  offsetof(PREDICATELOCK, xactLink));
4765 
4766  while (predlock != NULL)
4767  {
4769  lockRecord->target = predlock->tag.myTarget->tag;
4770 
4772  &record, sizeof(record));
4773 
4774  predlock = (PREDICATELOCK *)
4775  SHMQueueNext(&(sxact->predicateLocks),
4776  &(predlock->xactLink),
4777  offsetof(PREDICATELOCK, xactLink));
4778  }
4779 
4780  LWLockRelease(SerializablePredicateLockListLock);
4781 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
TwoPhasePredicateRecordType type
union TwoPhasePredicateRecord::@58 data
PREDICATELOCKTARGETTAG target
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1120
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:555
PREDICATELOCKTARGET * myTarget
void CheckForSerializableConflictIn ( Relation  relation,
HeapTuple  tuple,
Buffer  buffer 
)

Definition at line 4243 of file predicate.c.

References BufferGetBlockNumber(), BufferIsValid, CheckTargetForConflictsIn(), RelFileNode::dbNode, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, MyXactDidWrite, NULL, RelationData::rd_id, RelationData::rd_node, SerializationNeededForWrite(), SET_PREDICATELOCKTARGETTAG_PAGE, SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, SxactIsDoomed, and HeapTupleData::t_self.

Referenced by _bt_check_unique(), _bt_doinsert(), heap_delete(), heap_insert(), heap_multi_insert(), heap_update(), and index_insert().

4245 {
4246  PREDICATELOCKTARGETTAG targettag;
4247 
4248  if (!SerializationNeededForWrite(relation))
4249  return;
4250 
4251  /* Check if someone else has already decided that we need to die */
4253  ereport(ERROR,
4254  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4255  errmsg("could not serialize access due to read/write dependencies among transactions"),
4256  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4257  errhint("The transaction might succeed if retried.")));
4258 
4259  /*
4260  * We're doing a write which might cause rw-conflicts now or later.
4261  * Memorize that fact.
4262  */
4263  MyXactDidWrite = true;
4264 
4265  /*
4266  * It is important that we check for locks from the finest granularity to
4267  * the coarsest granularity, so that granularity promotion doesn't cause
4268  * us to miss a lock. The new (coarser) lock will be acquired before the
4269  * old (finer) locks are released.
4270  *
4271  * It is not possible to take and hold a lock across the checks for all
4272  * granularities because each target could be in a separate partition.
4273  */
4274  if (tuple != NULL)
4275  {
4277  relation->rd_node.dbNode,
4278  relation->rd_id,
4279  ItemPointerGetBlockNumber(&(tuple->t_self)),
4280  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4281  CheckTargetForConflictsIn(&targettag);
4282  }
4283 
4284  if (BufferIsValid(buffer))
4285  {
4287  relation->rd_node.dbNode,
4288  relation->rd_id,
4290  CheckTargetForConflictsIn(&targettag);
4291  }
4292 
4294  relation->rd_node.dbNode,
4295  relation->rd_id);
4296  CheckTargetForConflictsIn(&targettag);
4297 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
int errhint(const char *fmt,...)
Definition: elog.c:987
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4065
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:534
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
Oid rd_id
Definition: rel.h:115
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:76
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool MyXactDidWrite
Definition: predicate.c:405
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:66
void CheckForSerializableConflictOut ( bool  valid,
Relation  relation,
HeapTuple  tuple,
Buffer  buffer,
Snapshot  snapshot 
)

Definition at line 3862 of file predicate.c.

References Assert, SERIALIZABLEXACT::earliestOutConflictCommit, elog, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleSatisfiesVacuum(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, NULL, OldSerXidGetMinConflictCommitSeqNo(), RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerializationNeededForRead(), SHMQueueEmpty(), SubTransGetTopmostTransaction(), SXACT_FLAG_DOOMED, SXACT_FLAG_SUMMARY_CONFLICT_OUT, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, HeapTupleData::t_data, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionXmin, SERIALIZABLEXIDTAG::xid, and XidIsConcurrent().

Referenced by bitgetpage(), heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heapgetpage(), heapgettup(), and tablesample_getnext().

3865 {
3866  TransactionId xid;
3867  SERIALIZABLEXIDTAG sxidtag;
3868  SERIALIZABLEXID *sxid;
3869  SERIALIZABLEXACT *sxact;
3870  HTSV_Result htsvResult;
3871 
3872  if (!SerializationNeededForRead(relation, snapshot))
3873  return;
3874 
3875  /* Check if someone else has already decided that we need to die */
3877  {
3878  ereport(ERROR,
3879  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3880  errmsg("could not serialize access due to read/write dependencies among transactions"),
3881  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3882  errhint("The transaction might succeed if retried.")));
3883  }
3884 
3885  /*
3886  * Check to see whether the tuple has been written to by a concurrent
3887  * transaction, either to create it not visible to us, or to delete it
3888  * while it is visible to us. The "visible" bool indicates whether the
3889  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
3890  * is going on with it.
3891  */
3892  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
3893  switch (htsvResult)
3894  {
3895  case HEAPTUPLE_LIVE:
3896  if (visible)
3897  return;
3898  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3899  break;
3901  if (!visible)
3902  return;
3903  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3904  break;
3906  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3907  break;
3909  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3910  break;
3911  case HEAPTUPLE_DEAD:
3912  return;
3913  default:
3914 
3915  /*
3916  * The only way to get to this default clause is if a new value is
3917  * added to the enum type without adding it to this switch
3918  * statement. That's a bug, so elog.
3919  */
3920  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
3921 
3922  /*
3923  * In spite of having all enum values covered and calling elog on
3924  * this default, some compilers think this is a code path which
3925  * allows xid to be used below without initialization. Silence
3926  * that warning.
3927  */
3928  xid = InvalidTransactionId;
3929  }
3932 
3933  /*
3934  * Find top level xid. Bail out if xid is too early to be a conflict, or
3935  * if it's our own xid.
3936  */
3938  return;
3939  xid = SubTransGetTopmostTransaction(xid);
3941  return;
3943  return;
3944 
3945  /*
3946  * Find sxact or summarized info for the top level xid.
3947  */
3948  sxidtag.xid = xid;
3949  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3950  sxid = (SERIALIZABLEXID *)
3952  if (!sxid)
3953  {
3954  /*
3955  * Transaction not found in "normal" SSI structures. Check whether it
3956  * got pushed out to SLRU storage for "old committed" transactions.
3957  */
3958  SerCommitSeqNo conflictCommitSeqNo;
3959 
3960  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
3961  if (conflictCommitSeqNo != 0)
3962  {
3963  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
3965  || conflictCommitSeqNo
3967  ereport(ERROR,
3968  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3969  errmsg("could not serialize access due to read/write dependencies among transactions"),
3970  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
3971  errhint("The transaction might succeed if retried.")));
3972 
3975  ereport(ERROR,
3976  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3977  errmsg("could not serialize access due to read/write dependencies among transactions"),
3978  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
3979  errhint("The transaction might succeed if retried.")));
3980 
3982  }
3983 
3984  /* It's not serializable or otherwise not important. */
3985  LWLockRelease(SerializableXactHashLock);
3986  return;
3987  }
3988  sxact = sxid->myXact;
3989  Assert(TransactionIdEquals(sxact->topXid, xid));
3990  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
3991  {
3992  /* Can't conflict with ourself or a transaction that will roll back. */
3993  LWLockRelease(SerializableXactHashLock);
3994  return;
3995  }
3996 
3997  /*
3998  * We have a conflict out to a transaction which has a conflict out to a
3999  * summarized transaction. That summarized transaction must have
4000  * committed first, and we can't tell when it committed in relation to our
4001  * snapshot acquisition, so something needs to be canceled.
4002  */
4003  if (SxactHasSummaryConflictOut(sxact))
4004  {
4005  if (!SxactIsPrepared(sxact))
4006  {
4007  sxact->flags |= SXACT_FLAG_DOOMED;
4008  LWLockRelease(SerializableXactHashLock);
4009  return;
4010  }
4011  else
4012  {
4013  LWLockRelease(SerializableXactHashLock);
4014  ereport(ERROR,
4015  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4016  errmsg("could not serialize access due to read/write dependencies among transactions"),
4017  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4018  errhint("The transaction might succeed if retried.")));
4019  }
4020  }
4021 
4022  /*
4023  * If this is a read-only transaction and the writing transaction has
4024  * committed, and it doesn't have a rw-conflict to a transaction which
4025  * committed before it, no conflict.
4026  */
4028  && SxactIsCommitted(sxact)
4029  && !SxactHasSummaryConflictOut(sxact)
4030  && (!SxactHasConflictOut(sxact)
4032  {
4033  /* Read-only transaction will appear to run first. No conflict. */
4034  LWLockRelease(SerializableXactHashLock);
4035  return;
4036  }
4037 
4038  if (!XidIsConcurrent(xid))
4039  {
4040  /* This write was already in our snapshot; no conflict. */
4041  LWLockRelease(SerializableXactHashLock);
4042  return;
4043  }
4044 
4046  {
4047  /* We don't want duplicate conflict records in the list. */
4048  LWLockRelease(SerializableXactHashLock);
4049  return;
4050  }
4051 
4052  /*
4053  * Flag the conflict. But first, if this conflict creates a dangerous
4054  * structure, ereport an error.
4055  */
4057  LWLockRelease(SerializableXactHashLock);
4058 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:629
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4419
uint32 TransactionId
Definition: c.h:397
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:269
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:146
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3819
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:379
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
HTSV_Result
Definition: tqual.h:49
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:67
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
union SERIALIZABLEXACT::@57 SeqNo
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
#define ereport(elevel, rest)
Definition: elog.h:122
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:270
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define InvalidSerCommitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo earliestOutConflictCommit
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:940
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:276
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:490
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
void CheckPointPredicate ( void  )

Definition at line 1032 of file predicate.c.

References OldSerXidControlData::headPage, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OldSerXidPage, OldSerXidSlruCtl, SimpleLruFlush(), SimpleLruTruncate(), OldSerXidControlData::tailXid, and TransactionIdIsValid.

Referenced by CheckPointGuts().

1033 {
1034  int tailPage;
1035 
1036  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
1037 
1038  /* Exit quickly if the SLRU is currently not in use. */
1039  if (oldSerXidControl->headPage < 0)
1040  {
1041  LWLockRelease(OldSerXidLock);
1042  return;
1043  }
1044 
1046  {
1047  /* We can truncate the SLRU up to the page containing tailXid */
1048  tailPage = OldSerXidPage(oldSerXidControl->tailXid);
1049  }
1050  else
1051  {
1052  /*
1053  * The SLRU is no longer needed. Truncate to head before we set head
1054  * invalid.
1055  *
1056  * XXX: It's possible that the SLRU is not needed again until XID
1057  * wrap-around has happened, so that the segment containing headPage
1058  * that we leave behind will appear to be new again. In that case it
1059  * won't be removed until XID horizon advances enough to make it
1060  * current again.
1061  */
1062  tailPage = oldSerXidControl->headPage;
1063  oldSerXidControl->headPage = -1;
1064  }
1065 
1066  LWLockRelease(OldSerXidLock);
1067 
1068  /* Truncate away pages that are no longer required */
1070 
1071  /*
1072  * Flush dirty SLRU pages to disk
1073  *
1074  * This is not actually necessary from a correctness point of view. We do
1075  * it merely as a debugging aid.
1076  *
1077  * We're doing this after the truncation to avoid writing pages right
1078  * before deleting the file in which they sit, which would be completely
1079  * pointless.
1080  */
1082 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1165
#define OldSerXidPage(xid)
Definition: predicate.c:331
#define OldSerXidSlruCtl
Definition: predicate.c:312
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1100
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static OldSerXidControl oldSerXidControl
Definition: predicate.c:344
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId tailXid
Definition: predicate.c:338
void CheckTableForSerializableConflictIn ( Relation  relation)

Definition at line 4327 of file predicate.c.

References Assert, RelFileNode::dbNode, FlagRWConflict(), GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_RELATION, hash_seq_init(), hash_seq_search(), i, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myXact, MyXactDidWrite, NULL, NUM_PREDICATELOCK_PARTITIONS, offsetof, PredicateLockHashPartitionLockByIndex, PREDICATELOCKTARGET::predicateLocks, RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, RWConflictExists(), SerializationNeededForWrite(), SHMQueueNext(), PredXactListData::SxactGlobalXmin, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, PREDICATELOCK::targetLink, and TransactionIdIsValid.

Referenced by ExecuteTruncate(), and heap_drop_with_catalog().

4328 {
4329  HASH_SEQ_STATUS seqstat;
4330  PREDICATELOCKTARGET *target;
4331  Oid dbId;
4332  Oid heapId;
4333  int i;
4334 
4335  /*
4336  * Bail out quickly if there are no serializable transactions running.
4337  * It's safe to check this without taking locks because the caller is
4338  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4339  * would matter here can be acquired while that is held.
4340  */
4342  return;
4343 
4344  if (!SerializationNeededForWrite(relation))
4345  return;
4346 
4347  /*
4348  * We're doing a write which might cause rw-conflicts now or later.
4349  * Memorize that fact.
4350  */
4351  MyXactDidWrite = true;
4352 
4353  Assert(relation->rd_index == NULL); /* not an index relation */
4354 
4355  dbId = relation->rd_node.dbNode;
4356  heapId = relation->rd_id;
4357 
4358  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4359  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4361  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4362 
4363  /* Scan through target list */
4365 
4366  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4367  {
4368  PREDICATELOCK *predlock;
4369 
4370  /*
4371  * Check whether this is a target which needs attention.
4372  */
4373  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4374  continue; /* wrong relation id */
4375  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4376  continue; /* wrong database id */
4377 
4378  /*
4379  * Loop through locks for this target and flag conflicts.
4380  */
4381  predlock = (PREDICATELOCK *)
4382  SHMQueueNext(&(target->predicateLocks),
4383  &(target->predicateLocks),
4384  offsetof(PREDICATELOCK, targetLink));
4385  while (predlock)
4386  {
4387  PREDICATELOCK *nextpredlock;
4388 
4389  nextpredlock = (PREDICATELOCK *)
4390  SHMQueueNext(&(target->predicateLocks),
4391  &(predlock->targetLink),
4392  offsetof(PREDICATELOCK, targetLink));
4393 
4394  if (predlock->tag.myXact != MySerializableXact
4396  {
4398  }
4399 
4400  predlock = nextpredlock;
4401  }
4402  }
4403 
4404  /* Release locks in reverse order */
4405  LWLockRelease(SerializableXactHashLock);
4406  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4408  LWLockRelease(SerializablePredicateLockListLock);
4409 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:629
static HTAB * PredicateLockTargetHash
Definition: predicate.c:380
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4419
static PredXactList PredXact
Definition: predicate.c:367
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:534
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
Form_pg_index rd_index
Definition: rel.h:155
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:115
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:248
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:405
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:555
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1563 of file predicate.c.

References Assert, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, GetSafeSnapshot(), GetSerializableTransactionSnapshotInt(), InvalidTransactionId, IsolationIsSerializable, RecoveryInProgress(), XactDeferrable, and XactReadOnly.

Referenced by GetTransactionSnapshot().

1564 {
1566 
1567  /*
1568  * Can't use serializable mode while recovery is still active, as it is,
1569  * for example, on a hot standby. We could get here despite the check in
1570  * check_XactIsoLevel() if default_transaction_isolation is set to
1571  * serializable, so phrase the hint accordingly.
1572  */
1573  if (RecoveryInProgress())
1574  ereport(ERROR,
1575  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1576  errmsg("cannot use serializable mode in a hot standby"),
1577  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1578  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1579 
1580  /*
1581  * A special optimization is available for SERIALIZABLE READ ONLY
1582  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1583  * thereby avoid all SSI overhead once it's running.
1584  */
1586  return GetSafeSnapshot(snapshot);
1587 
1588  return GetSerializableTransactionSnapshotInt(snapshot,
1590 }
bool XactDeferrable
Definition: xact.c:80
int errhint(const char *fmt,...)
Definition: elog.c:987
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1491
int errcode(int sqlerrcode)
Definition: elog.c:575
bool RecoveryInProgress(void)
Definition: xlog.c:7857
#define ERROR
Definition: elog.h:43
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1632
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define InvalidTransactionId
Definition: transam.h:31
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
void InitPredicateLocks ( void  )

Definition at line 1097 of file predicate.c.

References PredXactListData::activeList, PredXactListData::availableList, RWConflictPoolHeaderData::availableList, PredXactListData::CanPartialClearThrough, SERIALIZABLEXACT::commitSeqNo, CreatePredXact(), PredXactListData::element, RWConflictPoolHeaderData::element, HASHCTL::entrysize, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, HASHCTL::hash, HASH_BLOBS, HASH_ELEM, HASH_ENTER, HASH_FIXED_SIZE, HASH_FUNCTION, HASH_PARTITION, hash_search(), PredXactListData::HavePartialClearedThrough, i, SERIALIZABLEXACT::inConflicts, InvalidTransactionId, HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, PredXactListElementData::link, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, NULL, HASHCTL::num_partitions, NUM_PREDICATELOCK_PARTITIONS, PredXactListData::OldCommittedSxact, OldSerXidInit(), SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, predicatelock_hash(), PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXactListDataSize, PredXactListElementDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPoolHeaderDataSize, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SetInvalidVirtualTransactionId, ShmemAlloc(), ShmemInitHash(), ShmemInitStruct(), SHMQueueInit(), SHMQueueInsertBefore(), SXACT_FLAG_COMMITTED, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SERIALIZABLEXACT::topXid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by CreateSharedMemoryAndSemaphores().

1098 {
1099  HASHCTL info;
1100  long max_table_size;
1101  Size requestSize;
1102  bool found;
1103 
1104  /*
1105  * Compute size of predicate lock target hashtable. Note these
1106  * calculations must agree with PredicateLockShmemSize!
1107  */
1108  max_table_size = NPREDICATELOCKTARGETENTS();
1109 
1110  /*
1111  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1112  * per-predicate-lock-target information.
1113  */
1114  MemSet(&info, 0, sizeof(info));
1115  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1116  info.entrysize = sizeof(PREDICATELOCKTARGET);
1118 
1119  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1120  max_table_size,
1121  max_table_size,
1122  &info,
1123  HASH_ELEM | HASH_BLOBS |
1125 
1126  /* Assume an average of 2 xacts per target */
1127  max_table_size *= 2;
1128 
1129  /*
1130  * Reserve a dummy entry in the hash table; we use it to make sure there's
1131  * always one entry available when we need to split or combine a page,
1132  * because running out of space there could mean aborting a
1133  * non-serializable transaction.
1134  */
1136 
1137  /*
1138  * Allocate hash table for PREDICATELOCK structs. This stores per
1139  * xact-lock-of-a-target information.
1140  */
1141  MemSet(&info, 0, sizeof(info));
1142  info.keysize = sizeof(PREDICATELOCKTAG);
1143  info.entrysize = sizeof(PREDICATELOCK);
1144  info.hash = predicatelock_hash;
1146 
1147  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1148  max_table_size,
1149  max_table_size,
1150  &info,
1153 
1154  /*
1155  * Compute size for serializable transaction hashtable. Note these
1156  * calculations must agree with PredicateLockShmemSize!
1157  */
1158  max_table_size = (MaxBackends + max_prepared_xacts);
1159 
1160  /*
1161  * Allocate a list to hold information on transactions participating in
1162  * predicate locking.
1163  *
1164  * Assume an average of 10 predicate locking transactions per backend.
1165  * This allows aggressive cleanup while detail is present before data must
1166  * be summarized for storage in SLRU and the "dummy" transaction.
1167  */
1168  max_table_size *= 10;
1169 
1170  PredXact = ShmemInitStruct("PredXactList",
1172  &found);
1173  if (!found)
1174  {
1175  int i;
1176 
1185  requestSize = mul_size((Size) max_table_size,
1187  PredXact->element = ShmemAlloc(requestSize);
1188  /* Add all elements to available list, clean. */
1189  memset(PredXact->element, 0, requestSize);
1190  for (i = 0; i < max_table_size; i++)
1191  {
1193  &(PredXact->element[i].link));
1194  }
1210  }
1211  /* This never changes, so let's keep a local copy. */
1213 
1214  /*
1215  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1216  * information for serializable transactions which have accessed data.
1217  */
1218  MemSet(&info, 0, sizeof(info));
1219  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1220  info.entrysize = sizeof(SERIALIZABLEXID);
1221 
1222  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1223  max_table_size,
1224  max_table_size,
1225  &info,
1226  HASH_ELEM | HASH_BLOBS |
1227  HASH_FIXED_SIZE);
1228 
1229  /*
1230  * Allocate space for tracking rw-conflicts in lists attached to the
1231  * transactions.
1232  *
1233  * Assume an average of 5 conflicts per transaction. Calculations suggest
1234  * that this will prevent resource exhaustion in even the most pessimal
1235  * loads up to max_connections = 200 with all 200 connections pounding the
1236  * database with serializable transactions. Beyond that, there may be
1237  * occasional transactions canceled when trying to flag conflicts. That's
1238  * probably OK.
1239  */
1240  max_table_size *= 5;
1241 
1242  RWConflictPool = ShmemInitStruct("RWConflictPool",
1244  &found);
1245  if (!found)
1246  {
1247  int i;
1248 
1250  requestSize = mul_size((Size) max_table_size,
1252  RWConflictPool->element = ShmemAlloc(requestSize);
1253  /* Add all elements to available list, clean. */
1254  memset(RWConflictPool->element, 0, requestSize);
1255  for (i = 0; i < max_table_size; i++)
1256  {
1258  &(RWConflictPool->element[i].outLink));
1259  }
1260  }
1261 
1262  /*
1263  * Create or attach to the header for the list of finished serializable
1264  * transactions.
1265  */
1267  ShmemInitStruct("FinishedSerializableTransactions",
1268  sizeof(SHM_QUEUE),
1269  &found);
1270  if (!found)
1272 
1273  /*
1274  * Initialize the SLRU storage for old committed serializable
1275  * transactions.
1276  */
1277  OldSerXidInit();
1278 
1279  /* Pre-calculate the hash and partition lock of the scratch entry */
1282 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:380
#define HASH_ELEM
Definition: hsearch.h:87
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:251
static PredXactList PredXact
Definition: predicate.c:367
TransactionId SxactGlobalXmin
struct SERIALIZABLEXIDTAG SERIALIZABLEXIDTAG
struct PREDICATELOCKTARGET PREDICATELOCKTARGET
Size entrysize
Definition: hsearch.h:73
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1350
static HTAB * SerializableXidHash
Definition: predicate.c:379
#define MemSet(start, val, len)
Definition: c.h:857
static void OldSerXidInit(void)
Definition: predicate.c:790
void * ShmemAlloc(Size size)
Definition: shmem.c:157
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:381
int max_prepared_xacts
Definition: twophase.c:98
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:373
struct PREDICATELOCK PREDICATELOCK
long num_partitions
Definition: hsearch.h:67
union SERIALIZABLEXACT::@57 SeqNo
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
struct PREDICATELOCKTAG PREDICATELOCKTAG
int MaxBackends
Definition: globals.c:126
#define RWConflictDataSize
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:88
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Size keysize
Definition: hsearch.h:72
#define NULL
Definition: c.h:229
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:78
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:356
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:96
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:389
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:317
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:382
static uint32 ScratchTargetTagHash
Definition: predicate.c:390
static LWLock * ScratchPartitionLock
Definition: predicate.c:391
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:556
PredXactListElement element
#define PredXactListElementDataSize
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

Definition at line 1853 of file predicate.c.

References RelFileNode::dbNode, HASH_FIND, hash_search_with_hash_value(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NULL, PredicateLockHashPartitionLock, PredicateLockTargetTagHashCode, RelationData::rd_id, RelationData::rd_node, and SET_PREDICATELOCKTARGETTAG_PAGE.

1854 {
1855  PREDICATELOCKTARGETTAG targettag;
1856  uint32 targettaghash;
1857  LWLock *partitionLock;
1858  PREDICATELOCKTARGET *target;
1859 
1861  relation->rd_node.dbNode,
1862  relation->rd_id,
1863  blkno);
1864 
1865  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1866  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1867  LWLockAcquire(partitionLock, LW_SHARED);
1868  target = (PREDICATELOCKTARGET *)
1870  &targettag, targettaghash,
1871  HASH_FIND, NULL);
1872  LWLockRelease(partitionLock);
1873 
1874  return (target != NULL);
1875 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:380
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
unsigned int uint32
Definition: c.h:268
Oid rd_id
Definition: rel.h:115
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4791 of file predicate.c.

References Assert, hash_destroy(), InvalidSerializableXact, MyXactDidWrite, NULL, SERIALIZABLEXACT::pid, and SxactIsPrepared.

Referenced by PrepareTransaction().

4792 {
4794  return;
4795 
4797 
4798  MySerializableXact->pid = 0;
4799 
4802 
4804  MyXactDidWrite = false;
4805 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
#define InvalidSerializableXact
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static HTAB * LocalPredicateLockHash
Definition: predicate.c:397
static bool MyXactDidWrite
Definition: predicate.c:405
void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4629 of file predicate.c.

References Assert, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, SERIALIZABLEXACT::flags, SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, InvalidSerializableXact, IsolationIsSerializable, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), offsetof, SERIALIZABLEXACT::prepareSeqNo, SHMQueueNext(), SXACT_FLAG_DOOMED, SXACT_FLAG_PREPARED, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, and RWConflictData::sxactOut.

Referenced by CommitTransaction(), and PrepareTransaction().

4630 {
4631  RWConflict nearConflict;
4632 
4634  return;
4635 
4637 
4638  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4639 
4640  /* Check if someone else has already decided that we need to die */
4642  {
4643  LWLockRelease(SerializableXactHashLock);
4644  ereport(ERROR,
4645  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4646  errmsg("could not serialize access due to read/write dependencies among transactions"),
4647  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4648  errhint("The transaction might succeed if retried.")));
4649  }
4650 
4651  nearConflict = (RWConflict)
4654  offsetof(RWConflictData, inLink));
4655  while (nearConflict)
4656  {
4657  if (!SxactIsCommitted(nearConflict->sxactOut)
4658  && !SxactIsDoomed(nearConflict->sxactOut))
4659  {
4660  RWConflict farConflict;
4661 
4662  farConflict = (RWConflict)
4663  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4664  &nearConflict->sxactOut->inConflicts,
4665  offsetof(RWConflictData, inLink));
4666  while (farConflict)
4667  {
4668  if (farConflict->sxactOut == MySerializableXact
4669  || (!SxactIsCommitted(farConflict->sxactOut)
4670  && !SxactIsReadOnly(farConflict->sxactOut)
4671  && !SxactIsDoomed(farConflict->sxactOut)))
4672  {
4673  /*
4674  * Normally, we kill the pivot transaction to make sure we
4675  * make progress if the failing transaction is retried.
4676  * However, we can't kill it if it's already prepared, so
4677  * in that case we commit suicide instead.
4678  */
4679  if (SxactIsPrepared(nearConflict->sxactOut))
4680  {
4681  LWLockRelease(SerializableXactHashLock);
4682  ereport(ERROR,
4683  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4684  errmsg("could not serialize access due to read/write dependencies among transactions"),
4685  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4686  errhint("The transaction might succeed if retried.")));
4687  }
4688  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4689  break;
4690  }
4691  farConflict = (RWConflict)
4692  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4693  &farConflict->inLink,
4694  offsetof(RWConflictData, inLink));
4695  }
4696  }
4697 
4698  nearConflict = (RWConflict)
4700  &nearConflict->inLink,
4701  offsetof(RWConflictData, inLink));
4702  }
4703 
4706 
4707  LWLockRelease(SerializableXactHashLock);
4708 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
int errhint(const char *fmt,...)
Definition: elog.c:987
static PredXactList PredXact
Definition: predicate.c:367
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
#define InvalidSerializableXact
#define SXACT_FLAG_PREPARED
#define ereport(elevel, rest)
Definition: elog.h:122
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define SXACT_FLAG_DOOMED
#define Assert(condition)
Definition: c.h:675
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
void predicatelock_twophase_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4840 of file predicate.c.

References Assert, VirtualTransactionId::backendId, SERIALIZABLEXACT::commitSeqNo, CreatePredicateLock(), CreatePredXact(), TwoPhasePredicateRecord::data, ereport, errcode(), errmsg(), ERROR, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, HASH_ENTER, HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidBackendId, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, VirtualTransactionId::localTransactionId, TwoPhasePredicateRecord::lockRecord, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, SERIALIZABLEXID::myXact, NULL, OldSerXidSetActiveSerXmin(), SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, SERIALIZABLEXACT::prepareSeqNo, RecoverySerCommitSeqNo, SERIALIZABLEXACT::SeqNo, SHMQueueElemInit(), SHMQueueInit(), SXACT_FLAG_SUMMARY_CONFLICT_IN, SXACT_FLAG_SUMMARY_CONFLICT_OUT, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactIsPrepared, SxactIsReadOnly, TwoPhasePredicateLockRecord::target, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollows(), TransactionIdIsValid, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXIDTAG::xid, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

4842 {
4843  TwoPhasePredicateRecord *record;
4844 
4845  Assert(len == sizeof(TwoPhasePredicateRecord));
4846 
4847  record = (TwoPhasePredicateRecord *) recdata;
4848 
4849  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4850  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4851 
4852  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4853  {
4854  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4855  TwoPhasePredicateXactRecord *xactRecord;
4856  SERIALIZABLEXACT *sxact;
4857  SERIALIZABLEXID *sxid;
4858  SERIALIZABLEXIDTAG sxidtag;
4859  bool found;
4860 
4861  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4862 
4863  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4864  sxact = CreatePredXact();
4865  if (!sxact)
4866  ereport(ERROR,
4867  (errcode(ERRCODE_OUT_OF_MEMORY),
4868  errmsg("out of shared memory")));
4869 
4870  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
4871  sxact->vxid.backendId = InvalidBackendId;
4873  sxact->pid = 0;
4874 
4875  /* a prepared xact hasn't committed yet */
4879 
4881 
4882  /*
4883  * Don't need to track this; no transactions running at the time the
4884  * recovered xact started are still active, except possibly other
4885  * prepared xacts and we don't care whether those are RO_SAFE or not.
4886  */
4888 
4889  SHMQueueInit(&(sxact->predicateLocks));
4890  SHMQueueElemInit(&(sxact->finishedLink));
4891 
4892  sxact->topXid = xid;
4893  sxact->xmin = xactRecord->xmin;
4894  sxact->flags = xactRecord->flags;
4895  Assert(SxactIsPrepared(sxact));
4896  if (!SxactIsReadOnly(sxact))
4897  {
4901  }
4902 
4903  /*
4904  * We don't know whether the transaction had any conflicts or not, so
4905  * we'll conservatively assume that it had both a conflict in and a
4906  * conflict out, and represent that with the summary conflict flags.
4907  */
4908  SHMQueueInit(&(sxact->outConflicts));
4909  SHMQueueInit(&(sxact->inConflicts));
4912 
4913  /* Register the transaction's xid */
4914  sxidtag.xid = xid;
4916  &sxidtag,
4917  HASH_ENTER, &found);
4918  Assert(sxid != NULL);
4919  Assert(!found);
4920  sxid->myXact = (SERIALIZABLEXACT *) sxact;
4921 
4922  /*
4923  * Update global xmin. Note that this is a special case compared to
4924  * registering a normal transaction, because the global xmin might go
4925  * backwards. That's OK, because until recovery is over we're not
4926  * going to complete any transactions or create any non-prepared
4927  * transactions, so there's no danger of throwing away.
4928  */
4931  {
4932  PredXact->SxactGlobalXmin = sxact->xmin;
4935  }
4936  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
4937  {
4940  }
4941 
4942  LWLockRelease(SerializableXactHashLock);
4943  }
4944  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
4945  {
4946  /* Lock record. Recreate the PREDICATELOCK */
4947  TwoPhasePredicateLockRecord *lockRecord;
4948  SERIALIZABLEXID *sxid;
4949  SERIALIZABLEXACT *sxact;
4950  SERIALIZABLEXIDTAG sxidtag;
4951  uint32 targettaghash;
4952 
4953  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
4954  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
4955 
4956  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4957  sxidtag.xid = xid;
4958  sxid = (SERIALIZABLEXID *)
4960  LWLockRelease(SerializableXactHashLock);
4961 
4962  Assert(sxid != NULL);
4963  sxact = sxid->myXact;
4964  Assert(sxact != InvalidSerializableXact);
4965 
4966  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
4967  }
4968 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2295
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:367
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:379
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:66
union TwoPhasePredicateRecord::@58 data
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:98
union SERIALIZABLEXACT::@57 SeqNo
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:126
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:268
uint32 LocalTransactionId
Definition: c.h:399
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
#define InvalidBackendId
Definition: backendid.h:23
#define RecoverySerCommitSeqNo
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:981
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TwoPhasePredicateLockRecord lockRecord
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:556
void PredicateLockPage ( Relation  relation,
BlockNumber  blkno,
Snapshot  snapshot 
)

Definition at line 2438 of file predicate.c.

References RelFileNode::dbNode, PredicateLockAcquire(), RelationData::rd_id, RelationData::rd_node, SerializationNeededForRead(), and SET_PREDICATELOCKTARGETTAG_PAGE.

Referenced by _bt_endpoint(), _bt_first(), _bt_readnextpage(), and IndexOnlyNext().

2439 {
2441 
2442  if (!SerializationNeededForRead(relation, snapshot))
2443  return;
2444 
2446  relation->rd_node.dbNode,
2447  relation->rd_id,
2448  blkno);
2449  PredicateLockAcquire(&tag);
2450 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2356
Oid rd_id
Definition: rel.h:115
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:490
void PredicateLockPageCombine ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3113 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead().

3115 {
3116  /*
3117  * Page combines differ from page splits in that we ought to be able to
3118  * remove the locks on the old page after transferring them to the new
3119  * page, instead of duplicating them. However, because we can't edit other
3120  * backends' local lock tables, removing the old lock would leave them
3121  * with an entry in their LocalPredicateLockHash for a lock they're not
3122  * holding, which isn't acceptable. So we wind up having to do the same
3123  * work as a page split, acquiring a lock on the new page and keeping the
3124  * old page locked too. That can lead to some false positives, but should
3125  * be rare in practice.
3126  */
3127  PredicateLockPageSplit(relation, oldblkno, newblkno);
3128 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3028
void PredicateLockPageSplit ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3028 of file predicate.c.

References Assert, BlockNumberIsValid, RelFileNode::dbNode, GetParentPredicateLockTag(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PredicateLockingNeededForRelation(), RelationData::rd_id, RelationData::rd_node, SET_PREDICATELOCKTARGETTAG_PAGE, success, PredXactListData::SxactGlobalXmin, TransactionIdIsValid, and TransferPredicateLocksToNewTarget().

Referenced by _bt_insertonpg(), and PredicateLockPageCombine().

3030 {
3031  PREDICATELOCKTARGETTAG oldtargettag;
3032  PREDICATELOCKTARGETTAG newtargettag;
3033  bool success;
3034 
3035  /*
3036  * Bail out quickly if there are no serializable transactions running.
3037  *
3038  * It's safe to do this check without taking any additional locks. Even if
3039  * a serializable transaction starts concurrently, we know it can't take
3040  * any SIREAD locks on the page being split because the caller is holding
3041  * the associated buffer page lock. Memory reordering isn't an issue; the
3042  * memory barrier in the LWLock acquisition guarantees that this read
3043  * occurs while the buffer page lock is held.
3044  */
3046  return;
3047 
3048  if (!PredicateLockingNeededForRelation(relation))
3049  return;
3050 
3051  Assert(oldblkno != newblkno);
3052  Assert(BlockNumberIsValid(oldblkno));
3053  Assert(BlockNumberIsValid(newblkno));
3054 
3055  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3056  relation->rd_node.dbNode,
3057  relation->rd_id,
3058  oldblkno);
3059  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3060  relation->rd_node.dbNode,
3061  relation->rd_id,
3062  newblkno);
3063 
3064  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3065 
3066  /*
3067  * Try copying the locks over to the new page's tag, creating it if
3068  * necessary.
3069  */
3070  success = TransferPredicateLocksToNewTarget(oldtargettag,
3071  newtargettag,
3072  false);
3073 
3074  if (!success)
3075  {
3076  /*
3077  * No more predicate lock entries are available. Failure isn't an
3078  * option here, so promote the page lock to a relation lock.
3079  */
3080 
3081  /* Get the parent relation lock's lock tag */
3082  success = GetParentPredicateLockTag(&oldtargettag,
3083  &newtargettag);
3084  Assert(success);
3085 
3086  /*
3087  * Move the locks to the parent. This shouldn't fail.
3088  *
3089  * Note that here we are removing locks held by other backends,
3090  * leading to a possible inconsistency in their local lock hash table.
3091  * This is OK because we're replacing it with a lock that covers the
3092  * old one.
3093  */
3094  success = TransferPredicateLocksToNewTarget(oldtargettag,
3095  newtargettag,
3096  true);
3097  Assert(success);
3098  }
3099 
3100  LWLockRelease(SerializablePredicateLockListLock);
3101 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:471
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2595
static PredXactList PredXact
Definition: predicate.c:367
TransactionId SxactGlobalXmin
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static bool success
Definition: pg_basebackup.c:96
Oid rd_id
Definition: rel.h:115
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1917
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 2415 of file predicate.c.

References RelFileNode::dbNode, PredicateLockAcquire(), RelationData::rd_id, RelationData::rd_node, SerializationNeededForRead(), and SET_PREDICATELOCKTARGETTAG_RELATION.

Referenced by _bt_endpoint(), _bt_first(), heap_beginscan_internal(), and index_beginscan_internal().

2416 {
2418 
2419  if (!SerializationNeededForRead(relation, snapshot))
2420  return;
2421 
2423  relation->rd_node.dbNode,
2424  relation->rd_id);
2425  PredicateLockAcquire(&tag);
2426 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2356
Oid rd_id
Definition: rel.h:115
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:490
Size PredicateLockShmemSize ( void  )

Definition at line 1288 of file predicate.c.

References add_size(), hash_estimate_size(), max_prepared_xacts, MaxBackends, mul_size(), NPREDICATELOCKTARGETENTS, NUM_OLDSERXID_BUFFERS, PredXactListDataSize, PredXactListElementDataSize, RWConflictDataSize, RWConflictPoolHeaderDataSize, and SimpleLruShmemSize().

Referenced by CreateSharedMemoryAndSemaphores().

1289 {
1290  Size size = 0;
1291  long max_table_size;
1292 
1293  /* predicate lock target hash table */
1294  max_table_size = NPREDICATELOCKTARGETENTS();
1295  size = add_size(size, hash_estimate_size(max_table_size,
1296  sizeof(PREDICATELOCKTARGET)));
1297 
1298  /* predicate lock hash table */
1299  max_table_size *= 2;
1300  size = add_size(size, hash_estimate_size(max_table_size,
1301  sizeof(PREDICATELOCK)));
1302 
1303  /*
1304  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1305  * margin.
1306  */
1307  size = add_size(size, size / 10);
1308 
1309  /* transaction list */
1310  max_table_size = MaxBackends + max_prepared_xacts;
1311  max_table_size *= 10;
1312  size = add_size(size, PredXactListDataSize);
1313  size = add_size(size, mul_size((Size) max_table_size,
1315 
1316  /* transaction xid table */
1317  size = add_size(size, hash_estimate_size(max_table_size,
1318  sizeof(SERIALIZABLEXID)));
1319 
1320  /* rw-conflict pool */
1321  max_table_size *= 5;
1322  size = add_size(size, RWConflictPoolHeaderDataSize);
1323  size = add_size(size, mul_size((Size) max_table_size,
1325 
1326  /* Head for list of finished serializable transactions. */
1327  size = add_size(size, sizeof(SHM_QUEUE));
1328 
1329  /* Shared memory structures for SLRU tracking of old committed xids. */
1330  size = add_size(size, sizeof(OldSerXidControlData));
1332 
1333  return size;
1334 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:251
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:28
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
int max_prepared_xacts
Definition: twophase.c:98
int MaxBackends
Definition: globals.c:126
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:711
#define RWConflictPoolHeaderDataSize
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:356
#define PredXactListElementDataSize
void PredicateLockTuple ( Relation  relation,
HeapTuple  tuple,
Snapshot  snapshot 
)

Definition at line 2460 of file predicate.c.

References RelFileNode::dbNode, GetTopTransactionIdIfAny(), HeapTupleHeaderGetXmin, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, NULL, PredicateLockAcquire(), PredicateLockExists(), RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, SerializationNeededForRead(), SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, SubTransGetTopmostTransaction(), HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionXmin.

Referenced by bitgetpage(), heap_fetch(), and heap_hot_search_buffer().

2461 {
2463  ItemPointer tid;
2464  TransactionId targetxmin;
2465 
2466  if (!SerializationNeededForRead(relation, snapshot))
2467  return;
2468 
2469  /*
2470  * If it's a heap tuple, return if this xact wrote it.
2471  */
2472  if (relation->rd_index == NULL)
2473  {
2474  TransactionId myxid;
2475 
2476  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2477 
2478  myxid = GetTopTransactionIdIfAny();
2479  if (TransactionIdIsValid(myxid))
2480  {
2482  {
2483  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2484 
2485  if (TransactionIdEquals(xid, myxid))
2486  {
2487  /* We wrote it; we already have a write lock. */
2488  return;
2489  }
2490  }
2491  }
2492  }
2493 
2494  /*
2495  * Do quick-but-not-definitive test for a relation lock first. This will
2496  * never cause a return when the relation is *not* locked, but will
2497  * occasionally let the check continue when there really *is* a relation
2498  * level lock.
2499  */
2501  relation->rd_node.dbNode,
2502  relation->rd_id);
2503  if (PredicateLockExists(&tag))
2504  return;
2505 
2506  tid = &(tuple->t_self);
2508  relation->rd_node.dbNode,
2509  relation->rd_id,
2512  PredicateLockAcquire(&tag);
2513 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:397
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:146
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1890
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:67
Form_pg_index rd_index
Definition: rel.h:155
ItemPointerData t_self
Definition: htup.h:65
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2356
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
Oid rd_id
Definition: rel.h:115
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:76
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:490
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:66
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4813 of file predicate.c.

References HASH_FIND, hash_search(), LW_SHARED, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, MyXactDidWrite, NULL, ReleasePredicateLocks(), and SERIALIZABLEXIDTAG::xid.

Referenced by FinishPreparedTransaction().

4814 {
4815  SERIALIZABLEXID *sxid;
4816  SERIALIZABLEXIDTAG sxidtag;
4817 
4818  sxidtag.xid = xid;
4819 
4820  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4821  sxid = (SERIALIZABLEXID *)
4823  LWLockRelease(SerializableXactHashLock);
4824 
4825  /* xid will not be found if it wasn't a serializable transaction */
4826  if (sxid == NULL)
4827  return;
4828 
4829  /* Release its locks */
4830  MySerializableXact = sxid->myXact;
4831  MyXactDidWrite = true; /* conservatively assume that we wrote
4832  * something */
4833  ReleasePredicateLocks(isCommit);
4834 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
static HTAB * SerializableXidHash
Definition: predicate.c:379
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3185
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static bool MyXactDidWrite
Definition: predicate.c:405
void RegisterPredicateLockingXid ( TransactionId  xid)

Definition at line 1804 of file predicate.c.

References Assert, HASH_ENTER, hash_search(), InvalidSerializableXact, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, SERIALIZABLEXID::myXact, SERIALIZABLEXACT::topXid, TransactionIdIsValid, and SERIALIZABLEXIDTAG::xid.

Referenced by AssignTransactionId().

1805 {
1806  SERIALIZABLEXIDTAG sxidtag;
1807  SERIALIZABLEXID *sxid;
1808  bool found;
1809 
1810  /*
1811  * If we're not tracking predicate lock data for this transaction, we
1812  * should ignore the request and return quickly.
1813  */
1815  return;
1816 
1817  /* We should have a valid XID and be at the top level. */
1819 
1820  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1821 
1822  /* This should only be done once per transaction. */
1824 
1825  MySerializableXact->topXid = xid;
1826 
1827  sxidtag.xid = xid;
1829  &sxidtag,
1830  HASH_ENTER, &found);
1831  Assert(!found);
1832 
1833  /* Initialize the structure. */
1834  sxid->myXact = MySerializableXact;
1835  LWLockRelease(SerializableXactHashLock);
1836 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
static HTAB * SerializableXidHash
Definition: predicate.c:379
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void ReleasePredicateLocks ( bool  isCommit)

Definition at line 3185 of file predicate.c.

References Assert, PredXactListData::CanPartialClearThrough, ClearOldPredicateLocks(), SERIALIZABLEXACT::commitSeqNo, SERIALIZABLEXACT::earliestOutConflictCommit, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, FlagSxactUnsafe(), hash_destroy(), SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, InvalidSerializableXact, IsolationIsSerializable, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyXactDidWrite, VariableCacheData::nextXid, NULL, offsetof, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::prepareSeqNo, ProcSendSignal(), ReleaseOneSerializableXact(), ReleaseRWConflict(), SERIALIZABLEXACT::SeqNo, SetNewSxactGlobalXmin(), ShmemVariableCache, SHMQueueEmpty(), SHMQueueInsertBefore(), SHMQueueNext(), SXACT_FLAG_COMMITTED, SXACT_FLAG_CONFLICT_OUT, SXACT_FLAG_DOOMED, SXACT_FLAG_PREPARED, SXACT_FLAG_READ_ONLY, SXACT_FLAG_RO_SAFE, SXACT_FLAG_ROLLED_BACK, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactHasConflictOut, SxactHasSummaryConflictOut, RWConflictData::sxactIn, SxactIsCommitted, SxactIsDeferrableWaiting, SxactIsDoomed, SxactIsOnFinishedList, SxactIsPrepared, SxactIsReadOnly, SxactIsRolledBack, SxactIsROSafe, SxactIsROUnsafe, RWConflictData::sxactOut, TransactionIdEquals, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by GetSafeSnapshot(), PredicateLockTwoPhaseFinish(), ResourceOwnerReleaseInternal(), and SerializationNeededForRead().

3186 {
3187  bool needToClear;
3188  RWConflict conflict,
3189  nextConflict,
3190  possibleUnsafeConflict;
3191  SERIALIZABLEXACT *roXact;
3192 
3193  /*
3194  * We can't trust XactReadOnly here, because a transaction which started
3195  * as READ WRITE can show as READ ONLY later, e.g., within
3196  * subtransactions. We want to flag a transaction as READ ONLY if it
3197  * commits without writing so that de facto READ ONLY transactions get the
3198  * benefit of some RO optimizations, so we will use this local variable to
3199  * get some cleanup logic right which is based on whether the transaction
3200  * was declared READ ONLY at the top level.
3201  */
3202  bool topLevelIsDeclaredReadOnly;
3203 
3205  {
3207  return;
3208  }
3209 
3210  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3211 
3212  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3213  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3216 
3217  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3219 
3220  /* We'd better not already be on the cleanup list. */
3222 
3223  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3224 
3225  /*
3226  * We don't hold XidGenLock lock here, assuming that TransactionId is
3227  * atomic!
3228  *
3229  * If this value is changing, we don't care that much whether we get the
3230  * old or new value -- it is just used to determine how far
3231  * GlobalSerializableXmin must advance before this transaction can be
3232  * fully cleaned up. The worst that could happen is we wait for one more
3233  * transaction to complete before freeing some RAM; correctness of visible
3234  * behavior is not affected.
3235  */
3237 
3238  /*
3239  * If it's not a commit it's a rollback, and we can clear our locks
3240  * immediately.
3241  */
3242  if (isCommit)
3243  {
3246  /* Recognize implicit read-only transaction (commit without write). */
3247  if (!MyXactDidWrite)
3249  }
3250  else
3251  {
3252  /*
3253  * The DOOMED flag indicates that we intend to roll back this
3254  * transaction and so it should not cause serialization failures for
3255  * other transactions that conflict with it. Note that this flag might
3256  * already be set, if another backend marked this transaction for
3257  * abort.
3258  *
3259  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3260  * has been called, and so the SerializableXact is eligible for
3261  * cleanup. This means it should not be considered when calculating
3262  * SxactGlobalXmin.
3263  */
3266 
3267  /*
3268  * If the transaction was previously prepared, but is now failing due
3269  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3270  * prepare, clear the prepared flag. This simplifies conflict
3271  * checking.
3272  */
3274  }
3275 
3276  if (!topLevelIsDeclaredReadOnly)
3277  {
3279  if (--(PredXact->WritableSxactCount) == 0)
3280  {
3281  /*
3282  * Release predicate locks and rw-conflicts in for all committed
3283  * transactions. There are no longer any transactions which might
3284  * conflict with the locks and no chance for new transactions to
3285  * overlap. Similarly, existing conflicts in can't cause pivots,
3286  * and any conflicts in which could have completed a dangerous
3287  * structure would already have caused a rollback, so any
3288  * remaining ones must be benign.
3289  */
3291  }
3292  }
3293  else
3294  {
3295  /*
3296  * Read-only transactions: clear the list of transactions that might
3297  * make us unsafe. Note that we use 'inLink' for the iteration as
3298  * opposed to 'outLink' for the r/w xacts.
3299  */
3300  possibleUnsafeConflict = (RWConflict)
3303  offsetof(RWConflictData, inLink));
3304  while (possibleUnsafeConflict)
3305  {
3306  nextConflict = (RWConflict)
3308  &possibleUnsafeConflict->inLink,
3309  offsetof(RWConflictData, inLink));
3310 
3311  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3312  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3313 
3314  ReleaseRWConflict(possibleUnsafeConflict);
3315 
3316  possibleUnsafeConflict = nextConflict;
3317  }
3318  }
3319 
3320  /* Check for conflict out to old committed transactions. */
3321  if (isCommit
3324  {
3325  /*
3326  * we don't know which old committed transaction we conflicted with,
3327  * so be conservative and use FirstNormalSerCommitSeqNo here
3328  */
3332  }
3333 
3334  /*
3335  * Release all outConflicts to committed transactions. If we're rolling
3336  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3337  * previously committed transactions.
3338  */
3339  conflict = (RWConflict)
3342  offsetof(RWConflictData, outLink));
3343  while (conflict)
3344  {
3345  nextConflict = (RWConflict)
3347  &conflict->outLink,
3348  offsetof(RWConflictData, outLink));
3349 
3350  if (isCommit
3352  && SxactIsCommitted(conflict->sxactIn))
3353  {
3358  }
3359 
3360  if (!isCommit
3361  || SxactIsCommitted(conflict->sxactIn)
3363  ReleaseRWConflict(conflict);
3364 
3365  conflict = nextConflict;
3366  }
3367 
3368  /*
3369  * Release all inConflicts from committed and read-only transactions. If
3370  * we're rolling back, clear them all.
3371  */
3372  conflict = (RWConflict)
3375  offsetof(RWConflictData, inLink));
3376  while (conflict)
3377  {
3378  nextConflict = (RWConflict)
3380  &conflict->inLink,
3381  offsetof(RWConflictData, inLink));
3382 
3383  if (!isCommit
3384  || SxactIsCommitted(conflict->sxactOut)
3385  || SxactIsReadOnly(conflict->sxactOut))
3386  ReleaseRWConflict(conflict);
3387 
3388  conflict = nextConflict;
3389  }
3390 
3391  if (!topLevelIsDeclaredReadOnly)
3392  {
3393  /*
3394  * Remove ourselves from the list of possible conflicts for concurrent
3395  * READ ONLY transactions, flagging them as unsafe if we have a
3396  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3397  * up if they are known safe or known unsafe.
3398  */
3399  possibleUnsafeConflict = (RWConflict)
3402  offsetof(RWConflictData, outLink));
3403  while (possibleUnsafeConflict)
3404  {
3405  nextConflict = (RWConflict)
3407  &possibleUnsafeConflict->outLink,
3408  offsetof(RWConflictData, outLink));
3409 
3410  roXact = possibleUnsafeConflict->sxactIn;
3411  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3412  Assert(SxactIsReadOnly(roXact));
3413 
3414  /* Mark conflicted if necessary. */
3415  if (isCommit
3416  && MyXactDidWrite
3419  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3420  {
3421  /*
3422  * This releases possibleUnsafeConflict (as well as all other
3423  * possible conflicts for roXact)
3424  */
3425  FlagSxactUnsafe(roXact);
3426  }
3427  else
3428  {
3429  ReleaseRWConflict(possibleUnsafeConflict);
3430 
3431  /*
3432  * If we were the last possible conflict, flag it safe. The
3433  * transaction can now safely release its predicate locks (but
3434  * that transaction's backend has to do that itself).
3435  */
3436  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3437  roXact->flags |= SXACT_FLAG_RO_SAFE;
3438  }
3439 
3440  /*
3441  * Wake up the process for a waiting DEFERRABLE transaction if we
3442  * now know it's either safe or conflicted.
3443  */
3444  if (SxactIsDeferrableWaiting(roXact) &&
3445  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3446  ProcSendSignal(roXact->pid);
3447 
3448  possibleUnsafeConflict = nextConflict;
3449  }
3450  }
3451 
3452  /*
3453  * Check whether it's time to clean up old transactions. This can only be
3454  * done when the last serializable transaction with the oldest xmin among
3455  * serializable transactions completes. We then find the "new oldest"
3456  * xmin and purge any transactions which finished before this transaction
3457  * was launched.
3458  */
3459  needToClear = false;
3461  {
3463  if (--(PredXact->SxactGlobalXminCount) == 0)
3464  {
3466  needToClear = true;
3467  }
3468  }
3469 
3470  LWLockRelease(SerializableXactHashLock);
3471 
3472  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3473 
3474  /* Add this to the list of transactions to check for later cleanup. */
3475  if (isCommit)
3478 
3479  if (!isCommit)
3481 
3482  LWLockRelease(SerializableFinishedListLock);
3483 
3484  if (needToClear)
3486 
3488  MyXactDidWrite = false;
3489 
3490  /* Delete per-transaction lock table */
3492  {
3495  }
3496 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:404
TransactionId finishedBefore
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static PredXactList PredXact
Definition: predicate.c:367
TransactionId SxactGlobalXmin
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3503
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:718
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:254
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:726
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1750
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define SxactIsRolledBack(sxact)
Definition: predicate.c:266
SHM_QUEUE possibleUnsafeConflicts
#define SXACT_FLAG_RO_SAFE
union SERIALIZABLEXACT::@57 SeqNo
#define InvalidSerializableXact
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_PREPARED
SerCommitSeqNo lastCommitBeforeSnapshot
#define SxactIsROSafe(sxact)
Definition: predicate.c:278
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:270
SerCommitSeqNo commitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo CanPartialClearThrough
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
SerCommitSeqNo earliestOutConflictCommit
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:276
#define NULL
Definition: c.h:229
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3660
#define Assert(condition)
Definition: c.h:675
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:277
#define SXACT_FLAG_ROLLED_BACK
SerCommitSeqNo prepareSeqNo
static HTAB * LocalPredicateLockHash
Definition: predicate.c:397
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define IsolationIsSerializable()
Definition: xact.h:44
#define SXACT_FLAG_READ_ONLY
static bool MyXactDidWrite
Definition: predicate.c:405
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:279
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:382
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3135
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
void SetSerializableTransactionSnapshot ( Snapshot  snapshot,
TransactionId  sourcexid 
)

Definition at line 1603 of file predicate.c.

References Assert, ereport, errcode(), errmsg(), ERROR, GetSerializableTransactionSnapshotInt(), IsolationIsSerializable, XactDeferrable, and XactReadOnly.

Referenced by SetTransactionSnapshot().

1605 {
1607 
1608  /*
1609  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1610  * import snapshots, since there's no way to wait for a safe snapshot when
1611  * we're using the snap we're told to. (XXX instead of throwing an error,
1612  * we could just ignore the XactDeferrable flag?)
1613  */
1615  ereport(ERROR,
1616  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1617  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1618 
1619  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcexid);
1620 }
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1632
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3007 of file predicate.c.

References DropAllPredicateLocksFromTable().

Referenced by ATRewriteTable(), cluster_rel(), index_drop(), and reindex_index().

3008 {
3009  DropAllPredicateLocksFromTable(relation, true);
3010 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2811

Variable Documentation

int max_predicate_locks_per_xact