PostgreSQL Source Code  git master
predicate.h File Reference
#include "storage/lock.h"
#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, VirtualTransactionId *sourcevxid, int sourcepid)
 
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
 
int max_predicate_locks_per_relation
 
int max_predicate_locks_per_page
 

Macro Definition Documentation

◆ NUM_OLDSERXID_BUFFERS

#define NUM_OLDSERXID_BUFFERS   16

Definition at line 31 of file predicate.h.

Referenced by OldSerXidInit(), and PredicateLockShmemSize().

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

Definition at line 4805 of file predicate.c.

References TwoPhasePredicateRecord::data, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, 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().

4806 {
4807  PREDICATELOCK *predlock;
4808  SERIALIZABLEXACT *sxact;
4809  TwoPhasePredicateRecord record;
4810  TwoPhasePredicateXactRecord *xactRecord;
4811  TwoPhasePredicateLockRecord *lockRecord;
4812 
4813  sxact = MySerializableXact;
4814  xactRecord = &(record.data.xactRecord);
4815  lockRecord = &(record.data.lockRecord);
4816 
4818  return;
4819 
4820  /* Generate an xact record for our SERIALIZABLEXACT */
4822  xactRecord->xmin = MySerializableXact->xmin;
4823  xactRecord->flags = MySerializableXact->flags;
4824 
4825  /*
4826  * Note that we don't include the list of conflicts in our out in the
4827  * statefile, because new conflicts can be added even after the
4828  * transaction prepares. We'll just make a conservative assumption during
4829  * recovery instead.
4830  */
4831 
4833  &record, sizeof(record));
4834 
4835  /*
4836  * Generate a lock record for each lock.
4837  *
4838  * To do this, we need to walk the predicate lock list in our sxact rather
4839  * than using the local predicate lock table because the latter is not
4840  * guaranteed to be accurate.
4841  */
4842  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4843 
4844  predlock = (PREDICATELOCK *)
4845  SHMQueueNext(&(sxact->predicateLocks),
4846  &(sxact->predicateLocks),
4847  offsetof(PREDICATELOCK, xactLink));
4848 
4849  while (predlock != NULL)
4850  {
4852  lockRecord->target = predlock->tag.myTarget->tag;
4853 
4855  &record, sizeof(record));
4856 
4857  predlock = (PREDICATELOCK *)
4858  SHMQueueNext(&(sxact->predicateLocks),
4859  &(predlock->xactLink),
4860  offsetof(PREDICATELOCK, xactLink));
4861  }
4862 
4863  LWLockRelease(SerializablePredicateLockListLock);
4864 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
TwoPhasePredicateRecordType type
PREDICATELOCKTARGETTAG target
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1164
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
#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
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
union TwoPhasePredicateRecord::@101 data
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:603
PREDICATELOCKTARGET * myTarget

◆ CheckForSerializableConflictIn()

void CheckForSerializableConflictIn ( Relation  relation,
HeapTuple  tuple,
Buffer  buffer 
)

Definition at line 4326 of file predicate.c.

References BufferGetBlockNumber(), BufferIsValid, CheckTargetForConflictsIn(), RelFileNode::dbNode, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, MyXactDidWrite, 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().

4328 {
4329  PREDICATELOCKTARGETTAG targettag;
4330 
4331  if (!SerializationNeededForWrite(relation))
4332  return;
4333 
4334  /* Check if someone else has already decided that we need to die */
4336  ereport(ERROR,
4337  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4338  errmsg("could not serialize access due to read/write dependencies among transactions"),
4339  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4340  errhint("The transaction might succeed if retried.")));
4341 
4342  /*
4343  * We're doing a write which might cause rw-conflicts now or later.
4344  * Memorize that fact.
4345  */
4346  MyXactDidWrite = true;
4347 
4348  /*
4349  * It is important that we check for locks from the finest granularity to
4350  * the coarsest granularity, so that granularity promotion doesn't cause
4351  * us to miss a lock. The new (coarser) lock will be acquired before the
4352  * old (finer) locks are released.
4353  *
4354  * It is not possible to take and hold a lock across the checks for all
4355  * granularities because each target could be in a separate partition.
4356  */
4357  if (tuple != NULL)
4358  {
4360  relation->rd_node.dbNode,
4361  relation->rd_id,
4362  ItemPointerGetBlockNumber(&(tuple->t_self)),
4363  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4364  CheckTargetForConflictsIn(&targettag);
4365  }
4366 
4367  if (BufferIsValid(buffer))
4368  {
4370  relation->rd_node.dbNode,
4371  relation->rd_id,
4373  CheckTargetForConflictsIn(&targettag);
4374  }
4375 
4377  relation->rd_node.dbNode,
4378  relation->rd_id);
4379  CheckTargetForConflictsIn(&targettag);
4380 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
int errhint(const char *fmt,...)
Definition: elog.c:987
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4148
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:544
#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:269
#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:116
RelFileNode rd_node
Definition: rel.h:85
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool MyXactDidWrite
Definition: predicate.c:414
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76

◆ CheckForSerializableConflictOut()

void CheckForSerializableConflictOut ( bool  valid,
Relation  relation,
HeapTuple  tuple,
Buffer  buffer,
Snapshot  snapshot 
)

Definition at line 3945 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, 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().

3948 {
3949  TransactionId xid;
3950  SERIALIZABLEXIDTAG sxidtag;
3951  SERIALIZABLEXID *sxid;
3952  SERIALIZABLEXACT *sxact;
3953  HTSV_Result htsvResult;
3954 
3955  if (!SerializationNeededForRead(relation, snapshot))
3956  return;
3957 
3958  /* Check if someone else has already decided that we need to die */
3960  {
3961  ereport(ERROR,
3962  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3963  errmsg("could not serialize access due to read/write dependencies among transactions"),
3964  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3965  errhint("The transaction might succeed if retried.")));
3966  }
3967 
3968  /*
3969  * Check to see whether the tuple has been written to by a concurrent
3970  * transaction, either to create it not visible to us, or to delete it
3971  * while it is visible to us. The "visible" bool indicates whether the
3972  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
3973  * is going on with it.
3974  */
3975  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
3976  switch (htsvResult)
3977  {
3978  case HEAPTUPLE_LIVE:
3979  if (visible)
3980  return;
3981  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3982  break;
3984  if (!visible)
3985  return;
3986  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3987  break;
3989  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3990  break;
3992  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3993  break;
3994  case HEAPTUPLE_DEAD:
3995  return;
3996  default:
3997 
3998  /*
3999  * The only way to get to this default clause is if a new value is
4000  * added to the enum type without adding it to this switch
4001  * statement. That's a bug, so elog.
4002  */
4003  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
4004 
4005  /*
4006  * In spite of having all enum values covered and calling elog on
4007  * this default, some compilers think this is a code path which
4008  * allows xid to be used below without initialization. Silence
4009  * that warning.
4010  */
4011  xid = InvalidTransactionId;
4012  }
4015 
4016  /*
4017  * Find top level xid. Bail out if xid is too early to be a conflict, or
4018  * if it's our own xid.
4019  */
4021  return;
4022  xid = SubTransGetTopmostTransaction(xid);
4024  return;
4026  return;
4027 
4028  /*
4029  * Find sxact or summarized info for the top level xid.
4030  */
4031  sxidtag.xid = xid;
4032  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4033  sxid = (SERIALIZABLEXID *)
4034  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4035  if (!sxid)
4036  {
4037  /*
4038  * Transaction not found in "normal" SSI structures. Check whether it
4039  * got pushed out to SLRU storage for "old committed" transactions.
4040  */
4041  SerCommitSeqNo conflictCommitSeqNo;
4042 
4043  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
4044  if (conflictCommitSeqNo != 0)
4045  {
4046  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4048  || conflictCommitSeqNo
4050  ereport(ERROR,
4051  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4052  errmsg("could not serialize access due to read/write dependencies among transactions"),
4053  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4054  errhint("The transaction might succeed if retried.")));
4055 
4058  ereport(ERROR,
4059  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4060  errmsg("could not serialize access due to read/write dependencies among transactions"),
4061  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4062  errhint("The transaction might succeed if retried.")));
4063 
4065  }
4066 
4067  /* It's not serializable or otherwise not important. */
4068  LWLockRelease(SerializableXactHashLock);
4069  return;
4070  }
4071  sxact = sxid->myXact;
4072  Assert(TransactionIdEquals(sxact->topXid, xid));
4073  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4074  {
4075  /* Can't conflict with ourself or a transaction that will roll back. */
4076  LWLockRelease(SerializableXactHashLock);
4077  return;
4078  }
4079 
4080  /*
4081  * We have a conflict out to a transaction which has a conflict out to a
4082  * summarized transaction. That summarized transaction must have
4083  * committed first, and we can't tell when it committed in relation to our
4084  * snapshot acquisition, so something needs to be canceled.
4085  */
4086  if (SxactHasSummaryConflictOut(sxact))
4087  {
4088  if (!SxactIsPrepared(sxact))
4089  {
4090  sxact->flags |= SXACT_FLAG_DOOMED;
4091  LWLockRelease(SerializableXactHashLock);
4092  return;
4093  }
4094  else
4095  {
4096  LWLockRelease(SerializableXactHashLock);
4097  ereport(ERROR,
4098  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4099  errmsg("could not serialize access due to read/write dependencies among transactions"),
4100  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4101  errhint("The transaction might succeed if retried.")));
4102  }
4103  }
4104 
4105  /*
4106  * If this is a read-only transaction and the writing transaction has
4107  * committed, and it doesn't have a rw-conflict to a transaction which
4108  * committed before it, no conflict.
4109  */
4111  && SxactIsCommitted(sxact)
4112  && !SxactHasSummaryConflictOut(sxact)
4113  && (!SxactHasConflictOut(sxact)
4115  {
4116  /* Read-only transaction will appear to run first. No conflict. */
4117  LWLockRelease(SerializableXactHashLock);
4118  return;
4119  }
4120 
4121  if (!XidIsConcurrent(xid))
4122  {
4123  /* This write was already in our snapshot; no conflict. */
4124  LWLockRelease(SerializableXactHashLock);
4125  return;
4126  }
4127 
4129  {
4130  /* We don't want duplicate conflict records in the list. */
4131  LWLockRelease(SerializableXactHashLock);
4132  return;
4133  }
4134 
4135  /*
4136  * Flag the conflict. But first, if this conflict creates a dangerous
4137  * structure, ereport an error.
4138  */
4140  LWLockRelease(SerializableXactHashLock);
4141 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:639
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:4502
uint32 TransactionId
Definition: c.h:455
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:271
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3902
#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:388
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
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:1722
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define ERROR
Definition: elog.h:43
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:405
#define ereport(elevel, rest)
Definition: elog.h:122
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:272
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define InvalidSerCommitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo earliestOutConflictCommit
union SERIALIZABLEXACT::@100 SeqNo
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:951
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:278
#define Assert(condition)
Definition: c.h:680
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:500
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:266

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1043 of file predicate.c.

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

Referenced by CheckPointGuts().

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

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)

Definition at line 4410 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, 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().

4411 {
4412  HASH_SEQ_STATUS seqstat;
4413  PREDICATELOCKTARGET *target;
4414  Oid dbId;
4415  Oid heapId;
4416  int i;
4417 
4418  /*
4419  * Bail out quickly if there are no serializable transactions running.
4420  * It's safe to check this without taking locks because the caller is
4421  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4422  * would matter here can be acquired while that is held.
4423  */
4425  return;
4426 
4427  if (!SerializationNeededForWrite(relation))
4428  return;
4429 
4430  /*
4431  * We're doing a write which might cause rw-conflicts now or later.
4432  * Memorize that fact.
4433  */
4434  MyXactDidWrite = true;
4435 
4436  Assert(relation->rd_index == NULL); /* not an index relation */
4437 
4438  dbId = relation->rd_node.dbNode;
4439  heapId = relation->rd_id;
4440 
4441  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4442  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4444  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4445 
4446  /* Scan through target list */
4448 
4449  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4450  {
4451  PREDICATELOCK *predlock;
4452 
4453  /*
4454  * Check whether this is a target which needs attention.
4455  */
4456  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4457  continue; /* wrong relation id */
4458  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4459  continue; /* wrong database id */
4460 
4461  /*
4462  * Loop through locks for this target and flag conflicts.
4463  */
4464  predlock = (PREDICATELOCK *)
4465  SHMQueueNext(&(target->predicateLocks),
4466  &(target->predicateLocks),
4467  offsetof(PREDICATELOCK, targetLink));
4468  while (predlock)
4469  {
4470  PREDICATELOCK *nextpredlock;
4471 
4472  nextpredlock = (PREDICATELOCK *)
4473  SHMQueueNext(&(target->predicateLocks),
4474  &(predlock->targetLink),
4475  offsetof(PREDICATELOCK, targetLink));
4476 
4477  if (predlock->tag.myXact != MySerializableXact
4479  {
4481  }
4482 
4483  predlock = nextpredlock;
4484  }
4485  }
4486 
4487  /* Release locks in reverse order */
4488  LWLockRelease(SerializableXactHashLock);
4489  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4491  LWLockRelease(SerializablePredicateLockListLock);
4492 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:639
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4502
static PredXactList PredXact
Definition: predicate.c:376
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:544
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
Form_pg_index rd_index
Definition: rel.h:159
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:116
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 Assert(condition)
Definition: c.h:680
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:250
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:414
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:603
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1636 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

1637 {
1639 
1640  /*
1641  * Can't use serializable mode while recovery is still active, as it is,
1642  * for example, on a hot standby. We could get here despite the check in
1643  * check_XactIsoLevel() if default_transaction_isolation is set to
1644  * serializable, so phrase the hint accordingly.
1645  */
1646  if (RecoveryInProgress())
1647  ereport(ERROR,
1648  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1649  errmsg("cannot use serializable mode in a hot standby"),
1650  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1651  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1652 
1653  /*
1654  * A special optimization is available for SERIALIZABLE READ ONLY
1655  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1656  * thereby avoid all SSI overhead once it's running.
1657  */
1659  return GetSafeSnapshot(snapshot);
1660 
1661  return GetSerializableTransactionSnapshotInt(snapshot,
1662  NULL, InvalidPid);
1663 }
bool XactDeferrable
Definition: xact.c:80
int errhint(const char *fmt,...)
Definition: elog.c:987
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1514
int errcode(int sqlerrcode)
Definition: elog.c:575
bool RecoveryInProgress(void)
Definition: xlog.c:7922
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1707
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:680
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define InvalidPid
Definition: miscadmin.h:31

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

Definition at line 1108 of file predicate.c.

References PredXactListData::activeList, Assert, 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, IsUnderPostmaster, HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, PredXactListElementData::link, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, 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().

1109 {
1110  HASHCTL info;
1111  long max_table_size;
1112  Size requestSize;
1113  bool found;
1114 
1115 #ifndef EXEC_BACKEND
1117 #endif
1118 
1119  /*
1120  * Compute size of predicate lock target hashtable. Note these
1121  * calculations must agree with PredicateLockShmemSize!
1122  */
1123  max_table_size = NPREDICATELOCKTARGETENTS();
1124 
1125  /*
1126  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1127  * per-predicate-lock-target information.
1128  */
1129  MemSet(&info, 0, sizeof(info));
1130  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1131  info.entrysize = sizeof(PREDICATELOCKTARGET);
1133 
1134  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1135  max_table_size,
1136  max_table_size,
1137  &info,
1138  HASH_ELEM | HASH_BLOBS |
1140 
1141  /*
1142  * Reserve a dummy entry in the hash table; we use it to make sure there's
1143  * always one entry available when we need to split or combine a page,
1144  * because running out of space there could mean aborting a
1145  * non-serializable transaction.
1146  */
1147  if (!IsUnderPostmaster)
1148  {
1150  HASH_ENTER, &found);
1151  Assert(!found);
1152  }
1153 
1154  /* Pre-calculate the hash and partition lock of the scratch entry */
1157 
1158  /*
1159  * Allocate hash table for PREDICATELOCK structs. This stores per
1160  * xact-lock-of-a-target information.
1161  */
1162  MemSet(&info, 0, sizeof(info));
1163  info.keysize = sizeof(PREDICATELOCKTAG);
1164  info.entrysize = sizeof(PREDICATELOCK);
1165  info.hash = predicatelock_hash;
1167 
1168  /* Assume an average of 2 xacts per target */
1169  max_table_size *= 2;
1170 
1171  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1172  max_table_size,
1173  max_table_size,
1174  &info,
1177 
1178  /*
1179  * Compute size for serializable transaction hashtable. Note these
1180  * calculations must agree with PredicateLockShmemSize!
1181  */
1182  max_table_size = (MaxBackends + max_prepared_xacts);
1183 
1184  /*
1185  * Allocate a list to hold information on transactions participating in
1186  * predicate locking.
1187  *
1188  * Assume an average of 10 predicate locking transactions per backend.
1189  * This allows aggressive cleanup while detail is present before data must
1190  * be summarized for storage in SLRU and the "dummy" transaction.
1191  */
1192  max_table_size *= 10;
1193 
1194  PredXact = ShmemInitStruct("PredXactList",
1196  &found);
1197  Assert(found == IsUnderPostmaster);
1198  if (!found)
1199  {
1200  int i;
1201 
1210  requestSize = mul_size((Size) max_table_size,
1212  PredXact->element = ShmemAlloc(requestSize);
1213  /* Add all elements to available list, clean. */
1214  memset(PredXact->element, 0, requestSize);
1215  for (i = 0; i < max_table_size; i++)
1216  {
1218  &(PredXact->element[i].link));
1219  }
1235  }
1236  /* This never changes, so let's keep a local copy. */
1238 
1239  /*
1240  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1241  * information for serializable transactions which have accessed data.
1242  */
1243  MemSet(&info, 0, sizeof(info));
1244  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1245  info.entrysize = sizeof(SERIALIZABLEXID);
1246 
1247  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1248  max_table_size,
1249  max_table_size,
1250  &info,
1251  HASH_ELEM | HASH_BLOBS |
1252  HASH_FIXED_SIZE);
1253 
1254  /*
1255  * Allocate space for tracking rw-conflicts in lists attached to the
1256  * transactions.
1257  *
1258  * Assume an average of 5 conflicts per transaction. Calculations suggest
1259  * that this will prevent resource exhaustion in even the most pessimal
1260  * loads up to max_connections = 200 with all 200 connections pounding the
1261  * database with serializable transactions. Beyond that, there may be
1262  * occasional transactions canceled when trying to flag conflicts. That's
1263  * probably OK.
1264  */
1265  max_table_size *= 5;
1266 
1267  RWConflictPool = ShmemInitStruct("RWConflictPool",
1269  &found);
1270  Assert(found == IsUnderPostmaster);
1271  if (!found)
1272  {
1273  int i;
1274 
1276  requestSize = mul_size((Size) max_table_size,
1278  RWConflictPool->element = ShmemAlloc(requestSize);
1279  /* Add all elements to available list, clean. */
1280  memset(RWConflictPool->element, 0, requestSize);
1281  for (i = 0; i < max_table_size; i++)
1282  {
1284  &(RWConflictPool->element[i].outLink));
1285  }
1286  }
1287 
1288  /*
1289  * Create or attach to the header for the list of finished serializable
1290  * transactions.
1291  */
1293  ShmemInitStruct("FinishedSerializableTransactions",
1294  sizeof(SHM_QUEUE),
1295  &found);
1296  Assert(found == IsUnderPostmaster);
1297  if (!found)
1299 
1300  /*
1301  * Initialize the SLRU storage for old committed serializable
1302  * transactions.
1303  */
1304  OldSerXidInit();
1305 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
#define HASH_ELEM
Definition: hsearch.h:87
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:253
static PredXactList PredXact
Definition: predicate.c:376
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:1373
static HTAB * SerializableXidHash
Definition: predicate.c:388
#define MemSet(start, val, len)
Definition: c.h:863
static void OldSerXidInit(void)
Definition: predicate.c:800
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:904
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:390
int max_prepared_xacts
Definition: twophase.c:117
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:382
struct PREDICATELOCK PREDICATELOCK
long num_partitions
Definition: hsearch.h:67
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
bool IsUnderPostmaster
Definition: globals.c:101
#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:291
Size keysize
Definition: hsearch.h:72
union SERIALIZABLEXACT::@100 SeqNo
#define Assert(condition)
Definition: c.h:680
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:414
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:96
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:354
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:398
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:391
static uint32 ScratchTargetTagHash
Definition: predicate.c:399
static LWLock * ScratchPartitionLock
Definition: predicate.c:400
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:566
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

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

Definition at line 1929 of file predicate.c.

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

1930 {
1931  PREDICATELOCKTARGETTAG targettag;
1932  uint32 targettaghash;
1933  LWLock *partitionLock;
1934  PREDICATELOCKTARGET *target;
1935 
1937  relation->rd_node.dbNode,
1938  relation->rd_id,
1939  blkno);
1940 
1941  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1942  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1943  LWLockAcquire(partitionLock, LW_SHARED);
1944  target = (PREDICATELOCKTARGET *)
1946  &targettag, targettaghash,
1947  HASH_FIND, NULL);
1948  LWLockRelease(partitionLock);
1949 
1950  return (target != NULL);
1951 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:917
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
unsigned int uint32
Definition: c.h:306
Oid rd_id
Definition: rel.h:116
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
RelFileNode rd_node
Definition: rel.h:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4874 of file predicate.c.

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

Referenced by PrepareTransaction().

4875 {
4877  return;
4878 
4880 
4881  MySerializableXact->pid = 0;
4882 
4884  LocalPredicateLockHash = NULL;
4885 
4887  MyXactDidWrite = false;
4888 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:812
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:680
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
static bool MyXactDidWrite
Definition: predicate.c:414

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4712 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().

4713 {
4714  RWConflict nearConflict;
4715 
4717  return;
4718 
4720 
4721  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4722 
4723  /* Check if someone else has already decided that we need to die */
4725  {
4726  LWLockRelease(SerializableXactHashLock);
4727  ereport(ERROR,
4728  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4729  errmsg("could not serialize access due to read/write dependencies among transactions"),
4730  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4731  errhint("The transaction might succeed if retried.")));
4732  }
4733 
4734  nearConflict = (RWConflict)
4737  offsetof(RWConflictData, inLink));
4738  while (nearConflict)
4739  {
4740  if (!SxactIsCommitted(nearConflict->sxactOut)
4741  && !SxactIsDoomed(nearConflict->sxactOut))
4742  {
4743  RWConflict farConflict;
4744 
4745  farConflict = (RWConflict)
4746  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4747  &nearConflict->sxactOut->inConflicts,
4748  offsetof(RWConflictData, inLink));
4749  while (farConflict)
4750  {
4751  if (farConflict->sxactOut == MySerializableXact
4752  || (!SxactIsCommitted(farConflict->sxactOut)
4753  && !SxactIsReadOnly(farConflict->sxactOut)
4754  && !SxactIsDoomed(farConflict->sxactOut)))
4755  {
4756  /*
4757  * Normally, we kill the pivot transaction to make sure we
4758  * make progress if the failing transaction is retried.
4759  * However, we can't kill it if it's already prepared, so
4760  * in that case we commit suicide instead.
4761  */
4762  if (SxactIsPrepared(nearConflict->sxactOut))
4763  {
4764  LWLockRelease(SerializableXactHashLock);
4765  ereport(ERROR,
4766  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4767  errmsg("could not serialize access due to read/write dependencies among transactions"),
4768  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4769  errhint("The transaction might succeed if retried.")));
4770  }
4771  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4772  break;
4773  }
4774  farConflict = (RWConflict)
4775  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4776  &farConflict->inLink,
4777  offsetof(RWConflictData, inLink));
4778  }
4779  }
4780 
4781  nearConflict = (RWConflict)
4783  &nearConflict->inLink,
4784  offsetof(RWConflictData, inLink));
4785  }
4786 
4789 
4790  LWLockRelease(SerializableXactHashLock);
4791 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
int errhint(const char *fmt,...)
Definition: elog.c:987
static PredXactList PredXact
Definition: predicate.c:376
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#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:680
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:603
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

void predicatelock_twophase_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4923 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, 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.

4925 {
4926  TwoPhasePredicateRecord *record;
4927 
4928  Assert(len == sizeof(TwoPhasePredicateRecord));
4929 
4930  record = (TwoPhasePredicateRecord *) recdata;
4931 
4932  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4933  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4934 
4935  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4936  {
4937  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4938  TwoPhasePredicateXactRecord *xactRecord;
4939  SERIALIZABLEXACT *sxact;
4940  SERIALIZABLEXID *sxid;
4941  SERIALIZABLEXIDTAG sxidtag;
4942  bool found;
4943 
4944  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4945 
4946  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4947  sxact = CreatePredXact();
4948  if (!sxact)
4949  ereport(ERROR,
4950  (errcode(ERRCODE_OUT_OF_MEMORY),
4951  errmsg("out of shared memory")));
4952 
4953  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
4954  sxact->vxid.backendId = InvalidBackendId;
4956  sxact->pid = 0;
4957 
4958  /* a prepared xact hasn't committed yet */
4962 
4964 
4965  /*
4966  * Don't need to track this; no transactions running at the time the
4967  * recovered xact started are still active, except possibly other
4968  * prepared xacts and we don't care whether those are RO_SAFE or not.
4969  */
4971 
4972  SHMQueueInit(&(sxact->predicateLocks));
4973  SHMQueueElemInit(&(sxact->finishedLink));
4974 
4975  sxact->topXid = xid;
4976  sxact->xmin = xactRecord->xmin;
4977  sxact->flags = xactRecord->flags;
4978  Assert(SxactIsPrepared(sxact));
4979  if (!SxactIsReadOnly(sxact))
4980  {
4984  }
4985 
4986  /*
4987  * We don't know whether the transaction had any conflicts or not, so
4988  * we'll conservatively assume that it had both a conflict in and a
4989  * conflict out, and represent that with the summary conflict flags.
4990  */
4991  SHMQueueInit(&(sxact->outConflicts));
4992  SHMQueueInit(&(sxact->inConflicts));
4995 
4996  /* Register the transaction's xid */
4997  sxidtag.xid = xid;
4999  &sxidtag,
5000  HASH_ENTER, &found);
5001  Assert(sxid != NULL);
5002  Assert(!found);
5003  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5004 
5005  /*
5006  * Update global xmin. Note that this is a special case compared to
5007  * registering a normal transaction, because the global xmin might go
5008  * backwards. That's OK, because until recovery is over we're not
5009  * going to complete any transactions or create any non-prepared
5010  * transactions, so there's no danger of throwing away.
5011  */
5014  {
5015  PredXact->SxactGlobalXmin = sxact->xmin;
5018  }
5019  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5020  {
5023  }
5024 
5025  LWLockRelease(SerializableXactHashLock);
5026  }
5027  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5028  {
5029  /* Lock record. Recreate the PREDICATELOCK */
5030  TwoPhasePredicateLockRecord *lockRecord;
5031  SERIALIZABLEXID *sxid;
5032  SERIALIZABLEXACT *sxact;
5033  SERIALIZABLEXIDTAG sxidtag;
5034  uint32 targettaghash;
5035 
5036  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5037  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5038 
5039  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5040  sxidtag.xid = xid;
5041  sxid = (SERIALIZABLEXID *)
5042  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5043  LWLockRelease(SerializableXactHashLock);
5044 
5045  Assert(sxid != NULL);
5046  sxact = sxid->myXact;
5047  Assert(sxact != InvalidSerializableXact);
5048 
5049  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5050  }
5051 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2378
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:376
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:388
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:66
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:126
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:306
uint32 LocalTransactionId
Definition: c.h:457
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
#define InvalidBackendId
Definition: backendid.h:23
union SERIALIZABLEXACT::@100 SeqNo
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:680
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:992
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
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
union TwoPhasePredicateRecord::@101 data
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TwoPhasePredicateLockRecord lockRecord
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:566

◆ PredicateLockPage()

void PredicateLockPage ( Relation  relation,
BlockNumber  blkno,
Snapshot  snapshot 
)

Definition at line 2521 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().

2522 {
2524 
2525  if (!SerializationNeededForRead(relation, snapshot))
2526  return;
2527 
2529  relation->rd_node.dbNode,
2530  relation->rd_id,
2531  blkno);
2532  PredicateLockAcquire(&tag);
2533 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:500

◆ PredicateLockPageCombine()

void PredicateLockPageCombine ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3196 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead().

3198 {
3199  /*
3200  * Page combines differ from page splits in that we ought to be able to
3201  * remove the locks on the old page after transferring them to the new
3202  * page, instead of duplicating them. However, because we can't edit other
3203  * backends' local lock tables, removing the old lock would leave them
3204  * with an entry in their LocalPredicateLockHash for a lock they're not
3205  * holding, which isn't acceptable. So we wind up having to do the same
3206  * work as a page split, acquiring a lock on the new page and keeping the
3207  * old page locked too. That can lead to some false positives, but should
3208  * be rare in practice.
3209  */
3210  PredicateLockPageSplit(relation, oldblkno, newblkno);
3211 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3111

◆ PredicateLockPageSplit()

void PredicateLockPageSplit ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3111 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().

3113 {
3114  PREDICATELOCKTARGETTAG oldtargettag;
3115  PREDICATELOCKTARGETTAG newtargettag;
3116  bool success;
3117 
3118  /*
3119  * Bail out quickly if there are no serializable transactions running.
3120  *
3121  * It's safe to do this check without taking any additional locks. Even if
3122  * a serializable transaction starts concurrently, we know it can't take
3123  * any SIREAD locks on the page being split because the caller is holding
3124  * the associated buffer page lock. Memory reordering isn't an issue; the
3125  * memory barrier in the LWLock acquisition guarantees that this read
3126  * occurs while the buffer page lock is held.
3127  */
3129  return;
3130 
3131  if (!PredicateLockingNeededForRelation(relation))
3132  return;
3133 
3134  Assert(oldblkno != newblkno);
3135  Assert(BlockNumberIsValid(oldblkno));
3136  Assert(BlockNumberIsValid(newblkno));
3137 
3138  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3139  relation->rd_node.dbNode,
3140  relation->rd_id,
3141  oldblkno);
3142  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3143  relation->rd_node.dbNode,
3144  relation->rd_id,
3145  newblkno);
3146 
3147  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3148 
3149  /*
3150  * Try copying the locks over to the new page's tag, creating it if
3151  * necessary.
3152  */
3153  success = TransferPredicateLocksToNewTarget(oldtargettag,
3154  newtargettag,
3155  false);
3156 
3157  if (!success)
3158  {
3159  /*
3160  * No more predicate lock entries are available. Failure isn't an
3161  * option here, so promote the page lock to a relation lock.
3162  */
3163 
3164  /* Get the parent relation lock's lock tag */
3165  success = GetParentPredicateLockTag(&oldtargettag,
3166  &newtargettag);
3167  Assert(success);
3168 
3169  /*
3170  * Move the locks to the parent. This shouldn't fail.
3171  *
3172  * Note that here we are removing locks held by other backends,
3173  * leading to a possible inconsistency in their local lock hash table.
3174  * This is OK because we're replacing it with a lock that covers the
3175  * old one.
3176  */
3177  success = TransferPredicateLocksToNewTarget(oldtargettag,
3178  newtargettag,
3179  true);
3180  Assert(success);
3181  }
3182 
3183  LWLockRelease(SerializablePredicateLockListLock);
3184 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:481
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2678
static PredXactList PredXact
Definition: predicate.c:376
TransactionId SxactGlobalXmin
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
static bool success
Definition: pg_basebackup.c:99
Oid rd_id
Definition: rel.h:116
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1993
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:680
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 2498 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().

2499 {
2501 
2502  if (!SerializationNeededForRead(relation, snapshot))
2503  return;
2504 
2506  relation->rd_node.dbNode,
2507  relation->rd_id);
2508  PredicateLockAcquire(&tag);
2509 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:500

◆ PredicateLockShmemSize()

Size PredicateLockShmemSize ( void  )

Definition at line 1311 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().

1312 {
1313  Size size = 0;
1314  long max_table_size;
1315 
1316  /* predicate lock target hash table */
1317  max_table_size = NPREDICATELOCKTARGETENTS();
1318  size = add_size(size, hash_estimate_size(max_table_size,
1319  sizeof(PREDICATELOCKTARGET)));
1320 
1321  /* predicate lock hash table */
1322  max_table_size *= 2;
1323  size = add_size(size, hash_estimate_size(max_table_size,
1324  sizeof(PREDICATELOCK)));
1325 
1326  /*
1327  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1328  * margin.
1329  */
1330  size = add_size(size, size / 10);
1331 
1332  /* transaction list */
1333  max_table_size = MaxBackends + max_prepared_xacts;
1334  max_table_size *= 10;
1335  size = add_size(size, PredXactListDataSize);
1336  size = add_size(size, mul_size((Size) max_table_size,
1338 
1339  /* transaction xid table */
1340  size = add_size(size, hash_estimate_size(max_table_size,
1341  sizeof(SERIALIZABLEXID)));
1342 
1343  /* rw-conflict pool */
1344  max_table_size *= 5;
1345  size = add_size(size, RWConflictPoolHeaderDataSize);
1346  size = add_size(size, mul_size((Size) max_table_size,
1348 
1349  /* Head for list of finished serializable transactions. */
1350  size = add_size(size, sizeof(SHM_QUEUE));
1351 
1352  /* Shared memory structures for SLRU tracking of old committed xids. */
1353  size = add_size(size, sizeof(OldSerXidControlData));
1355 
1356  return size;
1357 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:253
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:31
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:126
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:730
#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:414
#define PredXactListElementDataSize

◆ PredicateLockTuple()

void PredicateLockTuple ( Relation  relation,
HeapTuple  tuple,
Snapshot  snapshot 
)

Definition at line 2543 of file predicate.c.

References RelFileNode::dbNode, GetTopTransactionIdIfAny(), HeapTupleHeaderGetXmin, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, 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().

2544 {
2546  ItemPointer tid;
2547  TransactionId targetxmin;
2548 
2549  if (!SerializationNeededForRead(relation, snapshot))
2550  return;
2551 
2552  /*
2553  * If it's a heap tuple, return if this xact wrote it.
2554  */
2555  if (relation->rd_index == NULL)
2556  {
2557  TransactionId myxid;
2558 
2559  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2560 
2561  myxid = GetTopTransactionIdIfAny();
2562  if (TransactionIdIsValid(myxid))
2563  {
2565  {
2566  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2567 
2568  if (TransactionIdEquals(xid, myxid))
2569  {
2570  /* We wrote it; we already have a write lock. */
2571  return;
2572  }
2573  }
2574  }
2575  }
2576 
2577  /*
2578  * Do quick-but-not-definitive test for a relation lock first. This will
2579  * never cause a return when the relation is *not* locked, but will
2580  * occasionally let the check continue when there really *is* a relation
2581  * level lock.
2582  */
2584  relation->rd_node.dbNode,
2585  relation->rd_id);
2586  if (PredicateLockExists(&tag))
2587  return;
2588 
2589  tid = &(tuple->t_self);
2591  relation->rd_node.dbNode,
2592  relation->rd_id,
2595  PredicateLockAcquire(&tag);
2596 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:455
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1966
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:159
ItemPointerData t_self
Definition: htup.h:65
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:405
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:500
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4896 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

4897 {
4898  SERIALIZABLEXID *sxid;
4899  SERIALIZABLEXIDTAG sxidtag;
4900 
4901  sxidtag.xid = xid;
4902 
4903  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4904  sxid = (SERIALIZABLEXID *)
4905  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4906  LWLockRelease(SerializableXactHashLock);
4907 
4908  /* xid will not be found if it wasn't a serializable transaction */
4909  if (sxid == NULL)
4910  return;
4911 
4912  /* Release its locks */
4913  MySerializableXact = sxid->myXact;
4914  MyXactDidWrite = true; /* conservatively assume that we wrote
4915  * something */
4916  ReleasePredicateLocks(isCommit);
4917 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
static HTAB * SerializableXidHash
Definition: predicate.c:388
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3268
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
static bool MyXactDidWrite
Definition: predicate.c:414

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

Definition at line 1880 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().

1881 {
1882  SERIALIZABLEXIDTAG sxidtag;
1883  SERIALIZABLEXID *sxid;
1884  bool found;
1885 
1886  /*
1887  * If we're not tracking predicate lock data for this transaction, we
1888  * should ignore the request and return quickly.
1889  */
1891  return;
1892 
1893  /* We should have a valid XID and be at the top level. */
1895 
1896  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1897 
1898  /* This should only be done once per transaction. */
1900 
1901  MySerializableXact->topXid = xid;
1902 
1903  sxidtag.xid = xid;
1905  &sxidtag,
1906  HASH_ENTER, &found);
1907  Assert(!found);
1908 
1909  /* Initialize the structure. */
1910  sxid->myXact = MySerializableXact;
1911  LWLockRelease(SerializableXactHashLock);
1912 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
static HTAB * SerializableXidHash
Definition: predicate.c:388
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:680
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit)

Definition at line 3268 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, 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().

3269 {
3270  bool needToClear;
3271  RWConflict conflict,
3272  nextConflict,
3273  possibleUnsafeConflict;
3274  SERIALIZABLEXACT *roXact;
3275 
3276  /*
3277  * We can't trust XactReadOnly here, because a transaction which started
3278  * as READ WRITE can show as READ ONLY later, e.g., within
3279  * subtransactions. We want to flag a transaction as READ ONLY if it
3280  * commits without writing so that de facto READ ONLY transactions get the
3281  * benefit of some RO optimizations, so we will use this local variable to
3282  * get some cleanup logic right which is based on whether the transaction
3283  * was declared READ ONLY at the top level.
3284  */
3285  bool topLevelIsDeclaredReadOnly;
3286 
3288  {
3289  Assert(LocalPredicateLockHash == NULL);
3290  return;
3291  }
3292 
3293  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3294 
3295  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3296  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3299 
3300  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3302 
3303  /* We'd better not already be on the cleanup list. */
3305 
3306  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3307 
3308  /*
3309  * We don't hold XidGenLock lock here, assuming that TransactionId is
3310  * atomic!
3311  *
3312  * If this value is changing, we don't care that much whether we get the
3313  * old or new value -- it is just used to determine how far
3314  * GlobalSerializableXmin must advance before this transaction can be
3315  * fully cleaned up. The worst that could happen is we wait for one more
3316  * transaction to complete before freeing some RAM; correctness of visible
3317  * behavior is not affected.
3318  */
3320 
3321  /*
3322  * If it's not a commit it's a rollback, and we can clear our locks
3323  * immediately.
3324  */
3325  if (isCommit)
3326  {
3329  /* Recognize implicit read-only transaction (commit without write). */
3330  if (!MyXactDidWrite)
3332  }
3333  else
3334  {
3335  /*
3336  * The DOOMED flag indicates that we intend to roll back this
3337  * transaction and so it should not cause serialization failures for
3338  * other transactions that conflict with it. Note that this flag might
3339  * already be set, if another backend marked this transaction for
3340  * abort.
3341  *
3342  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3343  * has been called, and so the SerializableXact is eligible for
3344  * cleanup. This means it should not be considered when calculating
3345  * SxactGlobalXmin.
3346  */
3349 
3350  /*
3351  * If the transaction was previously prepared, but is now failing due
3352  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3353  * prepare, clear the prepared flag. This simplifies conflict
3354  * checking.
3355  */
3357  }
3358 
3359  if (!topLevelIsDeclaredReadOnly)
3360  {
3362  if (--(PredXact->WritableSxactCount) == 0)
3363  {
3364  /*
3365  * Release predicate locks and rw-conflicts in for all committed
3366  * transactions. There are no longer any transactions which might
3367  * conflict with the locks and no chance for new transactions to
3368  * overlap. Similarly, existing conflicts in can't cause pivots,
3369  * and any conflicts in which could have completed a dangerous
3370  * structure would already have caused a rollback, so any
3371  * remaining ones must be benign.
3372  */
3374  }
3375  }
3376  else
3377  {
3378  /*
3379  * Read-only transactions: clear the list of transactions that might
3380  * make us unsafe. Note that we use 'inLink' for the iteration as
3381  * opposed to 'outLink' for the r/w xacts.
3382  */
3383  possibleUnsafeConflict = (RWConflict)
3386  offsetof(RWConflictData, inLink));
3387  while (possibleUnsafeConflict)
3388  {
3389  nextConflict = (RWConflict)
3391  &possibleUnsafeConflict->inLink,
3392  offsetof(RWConflictData, inLink));
3393 
3394  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3395  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3396 
3397  ReleaseRWConflict(possibleUnsafeConflict);
3398 
3399  possibleUnsafeConflict = nextConflict;
3400  }
3401  }
3402 
3403  /* Check for conflict out to old committed transactions. */
3404  if (isCommit
3407  {
3408  /*
3409  * we don't know which old committed transaction we conflicted with,
3410  * so be conservative and use FirstNormalSerCommitSeqNo here
3411  */
3415  }
3416 
3417  /*
3418  * Release all outConflicts to committed transactions. If we're rolling
3419  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3420  * previously committed transactions.
3421  */
3422  conflict = (RWConflict)
3425  offsetof(RWConflictData, outLink));
3426  while (conflict)
3427  {
3428  nextConflict = (RWConflict)
3430  &conflict->outLink,
3431  offsetof(RWConflictData, outLink));
3432 
3433  if (isCommit
3435  && SxactIsCommitted(conflict->sxactIn))
3436  {
3441  }
3442 
3443  if (!isCommit
3444  || SxactIsCommitted(conflict->sxactIn)
3446  ReleaseRWConflict(conflict);
3447 
3448  conflict = nextConflict;
3449  }
3450 
3451  /*
3452  * Release all inConflicts from committed and read-only transactions. If
3453  * we're rolling back, clear them all.
3454  */
3455  conflict = (RWConflict)
3458  offsetof(RWConflictData, inLink));
3459  while (conflict)
3460  {
3461  nextConflict = (RWConflict)
3463  &conflict->inLink,
3464  offsetof(RWConflictData, inLink));
3465 
3466  if (!isCommit
3467  || SxactIsCommitted(conflict->sxactOut)
3468  || SxactIsReadOnly(conflict->sxactOut))
3469  ReleaseRWConflict(conflict);
3470 
3471  conflict = nextConflict;
3472  }
3473 
3474  if (!topLevelIsDeclaredReadOnly)
3475  {
3476  /*
3477  * Remove ourselves from the list of possible conflicts for concurrent
3478  * READ ONLY transactions, flagging them as unsafe if we have a
3479  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3480  * up if they are known safe or known unsafe.
3481  */
3482  possibleUnsafeConflict = (RWConflict)
3485  offsetof(RWConflictData, outLink));
3486  while (possibleUnsafeConflict)
3487  {
3488  nextConflict = (RWConflict)
3490  &possibleUnsafeConflict->outLink,
3491  offsetof(RWConflictData, outLink));
3492 
3493  roXact = possibleUnsafeConflict->sxactIn;
3494  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3495  Assert(SxactIsReadOnly(roXact));
3496 
3497  /* Mark conflicted if necessary. */
3498  if (isCommit
3499  && MyXactDidWrite
3502  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3503  {
3504  /*
3505  * This releases possibleUnsafeConflict (as well as all other
3506  * possible conflicts for roXact)
3507  */
3508  FlagSxactUnsafe(roXact);
3509  }
3510  else
3511  {
3512  ReleaseRWConflict(possibleUnsafeConflict);
3513 
3514  /*
3515  * If we were the last possible conflict, flag it safe. The
3516  * transaction can now safely release its predicate locks (but
3517  * that transaction's backend has to do that itself).
3518  */
3519  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3520  roXact->flags |= SXACT_FLAG_RO_SAFE;
3521  }
3522 
3523  /*
3524  * Wake up the process for a waiting DEFERRABLE transaction if we
3525  * now know it's either safe or conflicted.
3526  */
3527  if (SxactIsDeferrableWaiting(roXact) &&
3528  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3529  ProcSendSignal(roXact->pid);
3530 
3531  possibleUnsafeConflict = nextConflict;
3532  }
3533  }
3534 
3535  /*
3536  * Check whether it's time to clean up old transactions. This can only be
3537  * done when the last serializable transaction with the oldest xmin among
3538  * serializable transactions completes. We then find the "new oldest"
3539  * xmin and purge any transactions which finished before this transaction
3540  * was launched.
3541  */
3542  needToClear = false;
3544  {
3546  if (--(PredXact->SxactGlobalXminCount) == 0)
3547  {
3549  needToClear = true;
3550  }
3551  }
3552 
3553  LWLockRelease(SerializableXactHashLock);
3554 
3555  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3556 
3557  /* Add this to the list of transactions to check for later cleanup. */
3558  if (isCommit)
3561 
3562  if (!isCommit)
3564 
3565  LWLockRelease(SerializableFinishedListLock);
3566 
3567  if (needToClear)
3569 
3571  MyXactDidWrite = false;
3572 
3573  /* Delete per-transaction lock table */
3574  if (LocalPredicateLockHash != NULL)
3575  {
3577  LocalPredicateLockHash = NULL;
3578  }
3579 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
TransactionId finishedBefore
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:812
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static PredXactList PredXact
Definition: predicate.c:376
TransactionId SxactGlobalXmin
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3586
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:728
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:256
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:736
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1722
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1786
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define SxactIsRolledBack(sxact)
Definition: predicate.c:268
SHM_QUEUE possibleUnsafeConflicts
#define SXACT_FLAG_RO_SAFE
#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:280
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:272
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
union SERIALIZABLEXACT::@100 SeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:278
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3743
#define Assert(condition)
Definition: c.h:680
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:279
#define SXACT_FLAG_ROLLED_BACK
SerCommitSeqNo prepareSeqNo
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1118
#define IsolationIsSerializable()
Definition: xact.h:44
#define SXACT_FLAG_READ_ONLY
static bool MyXactDidWrite
Definition: predicate.c:414
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:281
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:391
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3218
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:603
SERIALIZABLEXACT * sxactOut

◆ SetSerializableTransactionSnapshot()

void SetSerializableTransactionSnapshot ( Snapshot  snapshot,
VirtualTransactionId sourcevxid,
int  sourcepid 
)

Definition at line 1676 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1679 {
1681 
1682  /*
1683  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1684  * import snapshots, since there's no way to wait for a safe snapshot when
1685  * we're using the snap we're told to. (XXX instead of throwing an error,
1686  * we could just ignore the XactDeferrable flag?)
1687  */
1689  ereport(ERROR,
1690  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1691  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1692 
1693  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1694  sourcepid);
1695 }
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1707
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:680
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3090 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3091 {
3092  DropAllPredicateLocksFromTable(relation, true);
3093 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2894

Variable Documentation

◆ max_predicate_locks_per_page

int max_predicate_locks_per_page

Definition at line 365 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

int max_predicate_locks_per_relation

Definition at line 364 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

int max_predicate_locks_per_xact

Definition at line 363 of file predicate.c.

Referenced by GetSerializableTransactionSnapshotInt(), and MaxPredicateChildLocks().