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
 

Typedefs

typedef void * SerializableXactHandle
 

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, bool isReadOnlySafe)
 
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)
 
SerializableXactHandle ShareSerializableXact (void)
 
void AttachSerializableXact (SerializableXactHandle handle)
 

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().

Typedef Documentation

◆ SerializableXactHandle

typedef void* SerializableXactHandle

Definition at line 37 of file predicate.h.

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

Definition at line 4906 of file predicate.c.

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

4907 {
4908  PREDICATELOCK *predlock;
4909  SERIALIZABLEXACT *sxact;
4910  TwoPhasePredicateRecord record;
4911  TwoPhasePredicateXactRecord *xactRecord;
4912  TwoPhasePredicateLockRecord *lockRecord;
4913 
4914  sxact = MySerializableXact;
4915  xactRecord = &(record.data.xactRecord);
4916  lockRecord = &(record.data.lockRecord);
4917 
4919  return;
4920 
4921  /* Generate an xact record for our SERIALIZABLEXACT */
4923  xactRecord->xmin = MySerializableXact->xmin;
4924  xactRecord->flags = MySerializableXact->flags;
4925 
4926  /*
4927  * Note that we don't include the list of conflicts in our out in the
4928  * statefile, because new conflicts can be added even after the
4929  * transaction prepares. We'll just make a conservative assumption during
4930  * recovery instead.
4931  */
4932 
4934  &record, sizeof(record));
4935 
4936  /*
4937  * Generate a lock record for each lock.
4938  *
4939  * To do this, we need to walk the predicate lock list in our sxact rather
4940  * than using the local predicate lock table because the latter is not
4941  * guaranteed to be accurate.
4942  */
4943  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4944 
4945  /*
4946  * No need to take sxact->predicateLockListLock in parallel mode because
4947  * there cannot be any parallel workers running while we are preparing a
4948  * transaction.
4949  */
4951 
4952  predlock = (PREDICATELOCK *)
4953  SHMQueueNext(&(sxact->predicateLocks),
4954  &(sxact->predicateLocks),
4955  offsetof(PREDICATELOCK, xactLink));
4956 
4957  while (predlock != NULL)
4958  {
4960  lockRecord->target = predlock->tag.myTarget->tag;
4961 
4963  &record, sizeof(record));
4964 
4965  predlock = (PREDICATELOCK *)
4966  SHMQueueNext(&(sxact->predicateLocks),
4967  &(predlock->xactLink),
4968  offsetof(PREDICATELOCK, xactLink));
4969  }
4970 
4971  LWLockRelease(SerializablePredicateLockListLock);
4972 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
TwoPhasePredicateRecordType type
PREDICATELOCKTARGETTAG target
union TwoPhasePredicateRecord::@110 data
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1203
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
#define IsParallelWorker()
Definition: parallel.h:60
bool ParallelContextActive(void)
Definition: parallel.c:944
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
#define Assert(condition)
Definition: c.h:733
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:656
PREDICATELOCKTARGET * myTarget

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5176 of file predicate.c.

References Assert, CreateLocalPredicateLockHash(), and InvalidSerializableXact.

Referenced by ParallelWorkerMain().

5177 {
5178 
5180 
5181  MySerializableXact = (SERIALIZABLEXACT *) handle;
5184 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:733
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1855

◆ CheckForSerializableConflictIn()

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

Definition at line 4426 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(), _hash_doinsert(), ginEntryInsert(), ginFindLeafPage(), ginHeapTupleFastInsert(), gistinserttuples(), heap_delete(), heap_insert(), heap_multi_insert(), heap_update(), and index_insert().

4428 {
4429  PREDICATELOCKTARGETTAG targettag;
4430 
4431  if (!SerializationNeededForWrite(relation))
4432  return;
4433 
4434  /* Check if someone else has already decided that we need to die */
4436  ereport(ERROR,
4437  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4438  errmsg("could not serialize access due to read/write dependencies among transactions"),
4439  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4440  errhint("The transaction might succeed if retried.")));
4441 
4442  /*
4443  * We're doing a write which might cause rw-conflicts now or later.
4444  * Memorize that fact.
4445  */
4446  MyXactDidWrite = true;
4447 
4448  /*
4449  * It is important that we check for locks from the finest granularity to
4450  * the coarsest granularity, so that granularity promotion doesn't cause
4451  * us to miss a lock. The new (coarser) lock will be acquired before the
4452  * old (finer) locks are released.
4453  *
4454  * It is not possible to take and hold a lock across the checks for all
4455  * granularities because each target could be in a separate partition.
4456  */
4457  if (tuple != NULL)
4458  {
4460  relation->rd_node.dbNode,
4461  relation->rd_id,
4462  ItemPointerGetBlockNumber(&(tuple->t_self)),
4463  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4464  CheckTargetForConflictsIn(&targettag);
4465  }
4466 
4467  if (BufferIsValid(buffer))
4468  {
4470  relation->rd_node.dbNode,
4471  relation->rd_id,
4472  BufferGetBlockNumber(buffer));
4473  CheckTargetForConflictsIn(&targettag);
4474  }
4475 
4477  relation->rd_node.dbNode,
4478  relation->rd_id);
4479  CheckTargetForConflictsIn(&targettag);
4480 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
int errhint(const char *fmt,...)
Definition: elog.c:1071
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4244
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:608
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:561
#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:984
#define SxactIsDoomed(sxact)
Definition: predicate.c:278
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:141
Oid rd_id
Definition: rel.h:85
RelFileNode rd_node
Definition: rel.h:54
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
int errmsg(const char *fmt,...)
Definition: elog.c:822
static bool MyXactDidWrite
Definition: predicate.c:420
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ CheckForSerializableConflictOut()

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

Definition at line 4041 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 heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heapam_scan_bitmap_next_block(), heapam_scan_sample_next_tuple(), heapgetpage(), and heapgettup().

4044 {
4045  TransactionId xid;
4046  SERIALIZABLEXIDTAG sxidtag;
4047  SERIALIZABLEXID *sxid;
4048  SERIALIZABLEXACT *sxact;
4049  HTSV_Result htsvResult;
4050 
4051  if (!SerializationNeededForRead(relation, snapshot))
4052  return;
4053 
4054  /* Check if someone else has already decided that we need to die */
4056  {
4057  ereport(ERROR,
4058  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4059  errmsg("could not serialize access due to read/write dependencies among transactions"),
4060  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4061  errhint("The transaction might succeed if retried.")));
4062  }
4063 
4064  /*
4065  * Check to see whether the tuple has been written to by a concurrent
4066  * transaction, either to create it not visible to us, or to delete it
4067  * while it is visible to us. The "visible" bool indicates whether the
4068  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
4069  * is going on with it.
4070  */
4071  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
4072  switch (htsvResult)
4073  {
4074  case HEAPTUPLE_LIVE:
4075  if (visible)
4076  return;
4077  xid = HeapTupleHeaderGetXmin(tuple->t_data);
4078  break;
4080  if (!visible)
4081  return;
4082  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
4083  break;
4085  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
4086  break;
4088  xid = HeapTupleHeaderGetXmin(tuple->t_data);
4089  break;
4090  case HEAPTUPLE_DEAD:
4091  return;
4092  default:
4093 
4094  /*
4095  * The only way to get to this default clause is if a new value is
4096  * added to the enum type without adding it to this switch
4097  * statement. That's a bug, so elog.
4098  */
4099  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
4100 
4101  /*
4102  * In spite of having all enum values covered and calling elog on
4103  * this default, some compilers think this is a code path which
4104  * allows xid to be used below without initialization. Silence
4105  * that warning.
4106  */
4107  xid = InvalidTransactionId;
4108  }
4111 
4112  /*
4113  * Find top level xid. Bail out if xid is too early to be a conflict, or
4114  * if it's our own xid.
4115  */
4117  return;
4118  xid = SubTransGetTopmostTransaction(xid);
4120  return;
4122  return;
4123 
4124  /*
4125  * Find sxact or summarized info for the top level xid.
4126  */
4127  sxidtag.xid = xid;
4128  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4129  sxid = (SERIALIZABLEXID *)
4130  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4131  if (!sxid)
4132  {
4133  /*
4134  * Transaction not found in "normal" SSI structures. Check whether it
4135  * got pushed out to SLRU storage for "old committed" transactions.
4136  */
4137  SerCommitSeqNo conflictCommitSeqNo;
4138 
4139  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
4140  if (conflictCommitSeqNo != 0)
4141  {
4142  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4144  || conflictCommitSeqNo
4146  ereport(ERROR,
4147  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4148  errmsg("could not serialize access due to read/write dependencies among transactions"),
4149  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4150  errhint("The transaction might succeed if retried.")));
4151 
4154  ereport(ERROR,
4155  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4156  errmsg("could not serialize access due to read/write dependencies among transactions"),
4157  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4158  errhint("The transaction might succeed if retried.")));
4159 
4161  }
4162 
4163  /* It's not serializable or otherwise not important. */
4164  LWLockRelease(SerializableXactHashLock);
4165  return;
4166  }
4167  sxact = sxid->myXact;
4168  Assert(TransactionIdEquals(sxact->topXid, xid));
4169  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4170  {
4171  /* Can't conflict with ourself or a transaction that will roll back. */
4172  LWLockRelease(SerializableXactHashLock);
4173  return;
4174  }
4175 
4176  /*
4177  * We have a conflict out to a transaction which has a conflict out to a
4178  * summarized transaction. That summarized transaction must have
4179  * committed first, and we can't tell when it committed in relation to our
4180  * snapshot acquisition, so something needs to be canceled.
4181  */
4182  if (SxactHasSummaryConflictOut(sxact))
4183  {
4184  if (!SxactIsPrepared(sxact))
4185  {
4186  sxact->flags |= SXACT_FLAG_DOOMED;
4187  LWLockRelease(SerializableXactHashLock);
4188  return;
4189  }
4190  else
4191  {
4192  LWLockRelease(SerializableXactHashLock);
4193  ereport(ERROR,
4194  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4195  errmsg("could not serialize access due to read/write dependencies among transactions"),
4196  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4197  errhint("The transaction might succeed if retried.")));
4198  }
4199  }
4200 
4201  /*
4202  * If this is a read-only transaction and the writing transaction has
4203  * committed, and it doesn't have a rw-conflict to a transaction which
4204  * committed before it, no conflict.
4205  */
4207  && SxactIsCommitted(sxact)
4208  && !SxactHasSummaryConflictOut(sxact)
4209  && (!SxactHasConflictOut(sxact)
4211  {
4212  /* Read-only transaction will appear to run first. No conflict. */
4213  LWLockRelease(SerializableXactHashLock);
4214  return;
4215  }
4216 
4217  if (!XidIsConcurrent(xid))
4218  {
4219  /* This write was already in our snapshot; no conflict. */
4220  LWLockRelease(SerializableXactHashLock);
4221  return;
4222  }
4223 
4225  {
4226  /* We don't want duplicate conflict records in the list. */
4227  LWLockRelease(SerializableXactHashLock);
4228  return;
4229  }
4230 
4231  /*
4232  * Flag the conflict. But first, if this conflict creates a dangerous
4233  * structure, ereport an error.
4234  */
4236  LWLockRelease(SerializableXactHashLock);
4237 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:365
#define SxactIsReadOnly(sxact)
Definition: predicate.c:279
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:656
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4602
uint32 TransactionId
Definition: c.h:508
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:280
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3998
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
int errcode(int sqlerrcode)
Definition: elog.c:608
static HTAB * SerializableXidHash
Definition: predicate.c:394
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
TransactionId TransactionXmin
Definition: snapmgr.c:166
HeapTupleHeader t_data
Definition: htup.h:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SxactIsDoomed(sxact)
Definition: predicate.c:278
#define ERROR
Definition: elog.h:43
union SERIALIZABLEXACT::@109 SeqNo
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:409
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
#define ereport(elevel, rest)
Definition: elog.h:141
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:281
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:926
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:287
#define Assert(condition)
Definition: c.h:733
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:517
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
HTSV_Result
Definition: heapam.h:86
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define SxactIsCommitted(sxact)
Definition: predicate.c:275

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1018 of file predicate.c.

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

Referenced by CheckPointGuts().

1019 {
1020  int tailPage;
1021 
1022  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
1023 
1024  /* Exit quickly if the SLRU is currently not in use. */
1025  if (oldSerXidControl->headPage < 0)
1026  {
1027  LWLockRelease(OldSerXidLock);
1028  return;
1029  }
1030 
1032  {
1033  /* We can truncate the SLRU up to the page containing tailXid */
1034  tailPage = OldSerXidPage(oldSerXidControl->tailXid);
1035  }
1036  else
1037  {
1038  /*
1039  * The SLRU is no longer needed. Truncate to head before we set head
1040  * invalid.
1041  *
1042  * XXX: It's possible that the SLRU is not needed again until XID
1043  * wrap-around has happened, so that the segment containing headPage
1044  * that we leave behind will appear to be new again. In that case it
1045  * won't be removed until XID horizon advances enough to make it
1046  * current again.
1047  */
1048  tailPage = oldSerXidControl->headPage;
1049  oldSerXidControl->headPage = -1;
1050  }
1051 
1052  LWLockRelease(OldSerXidLock);
1053 
1054  /* Truncate away pages that are no longer required */
1056 
1057  /*
1058  * Flush dirty SLRU pages to disk
1059  *
1060  * This is not actually necessary from a correctness point of view. We do
1061  * it merely as a debugging aid.
1062  *
1063  * We're doing this after the truncation to avoid writing pages right
1064  * before deleting the file in which they sit, which would be completely
1065  * pointless.
1066  */
1068 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1184
#define OldSerXidPage(xid)
Definition: predicate.c:341
#define OldSerXidSlruCtl
Definition: predicate.c:324
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1119
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static OldSerXidControl oldSerXidControl
Definition: predicate.c:352
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId tailXid
Definition: predicate.c:347

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)

Definition at line 4510 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 ExecuteTruncateGuts(), and heap_drop_with_catalog().

4511 {
4512  HASH_SEQ_STATUS seqstat;
4513  PREDICATELOCKTARGET *target;
4514  Oid dbId;
4515  Oid heapId;
4516  int i;
4517 
4518  /*
4519  * Bail out quickly if there are no serializable transactions running.
4520  * It's safe to check this without taking locks because the caller is
4521  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4522  * would matter here can be acquired while that is held.
4523  */
4525  return;
4526 
4527  if (!SerializationNeededForWrite(relation))
4528  return;
4529 
4530  /*
4531  * We're doing a write which might cause rw-conflicts now or later.
4532  * Memorize that fact.
4533  */
4534  MyXactDidWrite = true;
4535 
4536  Assert(relation->rd_index == NULL); /* not an index relation */
4537 
4538  dbId = relation->rd_node.dbNode;
4539  heapId = relation->rd_id;
4540 
4541  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4542  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4544  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4545 
4546  /* Scan through target list */
4548 
4549  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4550  {
4551  PREDICATELOCK *predlock;
4552 
4553  /*
4554  * Check whether this is a target which needs attention.
4555  */
4556  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4557  continue; /* wrong relation id */
4558  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4559  continue; /* wrong database id */
4560 
4561  /*
4562  * Loop through locks for this target and flag conflicts.
4563  */
4564  predlock = (PREDICATELOCK *)
4565  SHMQueueNext(&(target->predicateLocks),
4566  &(target->predicateLocks),
4567  offsetof(PREDICATELOCK, targetLink));
4568  while (predlock)
4569  {
4570  PREDICATELOCK *nextpredlock;
4571 
4572  nextpredlock = (PREDICATELOCK *)
4573  SHMQueueNext(&(target->predicateLocks),
4574  &(predlock->targetLink),
4575  offsetof(PREDICATELOCK, targetLink));
4576 
4577  if (predlock->tag.myXact != MySerializableXact
4579  {
4581  }
4582 
4583  predlock = nextpredlock;
4584  }
4585  }
4586 
4587  /* Release locks in reverse order */
4588  LWLockRelease(SerializableXactHashLock);
4589  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4591  LWLockRelease(SerializablePredicateLockListLock);
4592 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:656
static HTAB * PredicateLockTargetHash
Definition: predicate.c:395
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4602
static PredXactList PredXact
Definition: predicate.c:382
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:561
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
Form_pg_index rd_index
Definition: rel.h:143
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:85
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:54
#define Assert(condition)
Definition: c.h:733
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:259
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:420
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:656
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1613 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

1614 {
1616 
1617  /*
1618  * Can't use serializable mode while recovery is still active, as it is,
1619  * for example, on a hot standby. We could get here despite the check in
1620  * check_XactIsoLevel() if default_transaction_isolation is set to
1621  * serializable, so phrase the hint accordingly.
1622  */
1623  if (RecoveryInProgress())
1624  ereport(ERROR,
1625  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1626  errmsg("cannot use serializable mode in a hot standby"),
1627  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1628  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1629 
1630  /*
1631  * A special optimization is available for SERIALIZABLE READ ONLY
1632  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1633  * thereby avoid all SSI overhead once it's running.
1634  */
1636  return GetSafeSnapshot(snapshot);
1637 
1638  return GetSerializableTransactionSnapshotInt(snapshot,
1639  NULL, InvalidPid);
1640 }
bool XactDeferrable
Definition: xact.c:80
int errhint(const char *fmt,...)
Definition: elog.c:1071
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1491
int errcode(int sqlerrcode)
Definition: elog.c:608
bool RecoveryInProgress(void)
Definition: xlog.c:7931
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1695
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define ereport(elevel, rest)
Definition: elog.h:141
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:733
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define IsolationIsSerializable()
Definition: xact.h:52
#define InvalidPid
Definition: miscadmin.h:32

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

Definition at line 1083 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, LWLockInitialize(), LWTRANCHE_SXACT, 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::predicateLockListLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXactListDataSize, PredXactListElementDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPoolHeaderDataSize, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SetInvalidVirtualTransactionId, ShmemAlloc(), ShmemInitHash(), ShmemInitStruct(), SHMQueueInit(), SHMQueueInsertBefore(), PredXactListElementData::sxact, SXACT_FLAG_COMMITTED, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SERIALIZABLEXACT::topXid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by CreateSharedMemoryAndSemaphores().

1084 {
1085  HASHCTL info;
1086  long max_table_size;
1087  Size requestSize;
1088  bool found;
1089 
1090 #ifndef EXEC_BACKEND
1092 #endif
1093 
1094  /*
1095  * Compute size of predicate lock target hashtable. Note these
1096  * calculations must agree with PredicateLockShmemSize!
1097  */
1098  max_table_size = NPREDICATELOCKTARGETENTS();
1099 
1100  /*
1101  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1102  * per-predicate-lock-target information.
1103  */
1104  MemSet(&info, 0, sizeof(info));
1105  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1106  info.entrysize = sizeof(PREDICATELOCKTARGET);
1108 
1109  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1110  max_table_size,
1111  max_table_size,
1112  &info,
1113  HASH_ELEM | HASH_BLOBS |
1115 
1116  /*
1117  * Reserve a dummy entry in the hash table; we use it to make sure there's
1118  * always one entry available when we need to split or combine a page,
1119  * because running out of space there could mean aborting a
1120  * non-serializable transaction.
1121  */
1122  if (!IsUnderPostmaster)
1123  {
1125  HASH_ENTER, &found);
1126  Assert(!found);
1127  }
1128 
1129  /* Pre-calculate the hash and partition lock of the scratch entry */
1132 
1133  /*
1134  * Allocate hash table for PREDICATELOCK structs. This stores per
1135  * xact-lock-of-a-target information.
1136  */
1137  MemSet(&info, 0, sizeof(info));
1138  info.keysize = sizeof(PREDICATELOCKTAG);
1139  info.entrysize = sizeof(PREDICATELOCK);
1140  info.hash = predicatelock_hash;
1142 
1143  /* Assume an average of 2 xacts per target */
1144  max_table_size *= 2;
1145 
1146  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1147  max_table_size,
1148  max_table_size,
1149  &info,
1152 
1153  /*
1154  * Compute size for serializable transaction hashtable. Note these
1155  * calculations must agree with PredicateLockShmemSize!
1156  */
1157  max_table_size = (MaxBackends + max_prepared_xacts);
1158 
1159  /*
1160  * Allocate a list to hold information on transactions participating in
1161  * predicate locking.
1162  *
1163  * Assume an average of 10 predicate locking transactions per backend.
1164  * This allows aggressive cleanup while detail is present before data must
1165  * be summarized for storage in SLRU and the "dummy" transaction.
1166  */
1167  max_table_size *= 10;
1168 
1169  PredXact = ShmemInitStruct("PredXactList",
1171  &found);
1172  Assert(found == IsUnderPostmaster);
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  LWTRANCHE_SXACT);
1195  &(PredXact->element[i].link));
1196  }
1212  }
1213  /* This never changes, so let's keep a local copy. */
1215 
1216  /*
1217  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1218  * information for serializable transactions which have accessed data.
1219  */
1220  MemSet(&info, 0, sizeof(info));
1221  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1222  info.entrysize = sizeof(SERIALIZABLEXID);
1223 
1224  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1225  max_table_size,
1226  max_table_size,
1227  &info,
1228  HASH_ELEM | HASH_BLOBS |
1229  HASH_FIXED_SIZE);
1230 
1231  /*
1232  * Allocate space for tracking rw-conflicts in lists attached to the
1233  * transactions.
1234  *
1235  * Assume an average of 5 conflicts per transaction. Calculations suggest
1236  * that this will prevent resource exhaustion in even the most pessimal
1237  * loads up to max_connections = 200 with all 200 connections pounding the
1238  * database with serializable transactions. Beyond that, there may be
1239  * occasional transactions canceled when trying to flag conflicts. That's
1240  * probably OK.
1241  */
1242  max_table_size *= 5;
1243 
1244  RWConflictPool = ShmemInitStruct("RWConflictPool",
1246  &found);
1247  Assert(found == IsUnderPostmaster);
1248  if (!found)
1249  {
1250  int i;
1251 
1253  requestSize = mul_size((Size) max_table_size,
1255  RWConflictPool->element = ShmemAlloc(requestSize);
1256  /* Add all elements to available list, clean. */
1257  memset(RWConflictPool->element, 0, requestSize);
1258  for (i = 0; i < max_table_size; i++)
1259  {
1261  &(RWConflictPool->element[i].outLink));
1262  }
1263  }
1264 
1265  /*
1266  * Create or attach to the header for the list of finished serializable
1267  * transactions.
1268  */
1270  ShmemInitStruct("FinishedSerializableTransactions",
1271  sizeof(SHM_QUEUE),
1272  &found);
1273  Assert(found == IsUnderPostmaster);
1274  if (!found)
1276 
1277  /*
1278  * Initialize the SLRU storage for old committed serializable
1279  * transactions.
1280  */
1281  OldSerXidInit();
1282 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:395
#define HASH_ELEM
Definition: hsearch.h:87
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:262
static PredXactList PredXact
Definition: predicate.c:382
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:394
#define MemSet(start, val, len)
Definition: c.h:956
static void OldSerXidInit(void)
Definition: predicate.c:817
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:906
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:256
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:396
int max_prepared_xacts
Definition: twophase.c:117
union SERIALIZABLEXACT::@109 SeqNo
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:388
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:135
#define RWConflictDataSize
VirtualTransactionId vxid
bool IsUnderPostmaster
Definition: globals.c:109
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:678
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:301
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:733
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:467
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:96
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:360
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:404
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:397
static uint32 ScratchTargetTagHash
Definition: predicate.c:405
static LWLock * ScratchPartitionLock
Definition: predicate.c:406
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:583
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 1924 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.

1925 {
1926  PREDICATELOCKTARGETTAG targettag;
1927  uint32 targettaghash;
1928  LWLock *partitionLock;
1929  PREDICATELOCKTARGET *target;
1930 
1932  relation->rd_node.dbNode,
1933  relation->rd_id,
1934  blkno);
1935 
1936  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1937  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1938  LWLockAcquire(partitionLock, LW_SHARED);
1939  target = (PREDICATELOCKTARGET *)
1941  &targettag, targettaghash,
1942  HASH_FIND, NULL);
1943  LWLockRelease(partitionLock);
1944 
1945  return (target != NULL);
1946 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:395
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:256
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
unsigned int uint32
Definition: c.h:359
Oid rd_id
Definition: rel.h:85
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:301
RelFileNode rd_node
Definition: rel.h:54
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4982 of file predicate.c.

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

Referenced by PrepareTransaction().

4983 {
4985  return;
4986 
4988 
4989  MySerializableXact->pid = 0;
4990 
4992  LocalPredicateLockHash = NULL;
4993 
4995  MyXactDidWrite = false;
4996 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:814
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:733
static HTAB * LocalPredicateLockHash
Definition: predicate.c:412
static bool MyXactDidWrite
Definition: predicate.c:420

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4812 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, SxactIsPartiallyReleased, SxactIsPrepared, SxactIsReadOnly, and RWConflictData::sxactOut.

Referenced by CommitTransaction(), and PrepareTransaction().

4813 {
4814  RWConflict nearConflict;
4815 
4817  return;
4818 
4820 
4821  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4822 
4823  /* Check if someone else has already decided that we need to die */
4825  {
4827  LWLockRelease(SerializableXactHashLock);
4828  ereport(ERROR,
4829  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4830  errmsg("could not serialize access due to read/write dependencies among transactions"),
4831  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4832  errhint("The transaction might succeed if retried.")));
4833  }
4834 
4835  nearConflict = (RWConflict)
4838  offsetof(RWConflictData, inLink));
4839  while (nearConflict)
4840  {
4841  if (!SxactIsCommitted(nearConflict->sxactOut)
4842  && !SxactIsDoomed(nearConflict->sxactOut))
4843  {
4844  RWConflict farConflict;
4845 
4846  farConflict = (RWConflict)
4847  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4848  &nearConflict->sxactOut->inConflicts,
4849  offsetof(RWConflictData, inLink));
4850  while (farConflict)
4851  {
4852  if (farConflict->sxactOut == MySerializableXact
4853  || (!SxactIsCommitted(farConflict->sxactOut)
4854  && !SxactIsReadOnly(farConflict->sxactOut)
4855  && !SxactIsDoomed(farConflict->sxactOut)))
4856  {
4857  /*
4858  * Normally, we kill the pivot transaction to make sure we
4859  * make progress if the failing transaction is retried.
4860  * However, we can't kill it if it's already prepared, so
4861  * in that case we commit suicide instead.
4862  */
4863  if (SxactIsPrepared(nearConflict->sxactOut))
4864  {
4865  LWLockRelease(SerializableXactHashLock);
4866  ereport(ERROR,
4867  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4868  errmsg("could not serialize access due to read/write dependencies among transactions"),
4869  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4870  errhint("The transaction might succeed if retried.")));
4871  }
4872  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4873  break;
4874  }
4875  farConflict = (RWConflict)
4876  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4877  &farConflict->inLink,
4878  offsetof(RWConflictData, inLink));
4879  }
4880  }
4881 
4882  nearConflict = (RWConflict)
4884  &nearConflict->inLink,
4885  offsetof(RWConflictData, inLink));
4886  }
4887 
4890 
4891  LWLockRelease(SerializableXactHashLock);
4892 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:279
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
int errhint(const char *fmt,...)
Definition: elog.c:1071
static PredXactList PredXact
Definition: predicate.c:382
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:608
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SxactIsDoomed(sxact)
Definition: predicate.c:278
#define ERROR
Definition: elog.h:43
#define InvalidSerializableXact
#define SXACT_FLAG_PREPARED
#define ereport(elevel, rest)
Definition: elog.h:141
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:733
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define SxactIsPartiallyReleased(sxact)
Definition: predicate.c:291
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define IsolationIsSerializable()
Definition: xact.h:52
#define SxactIsCommitted(sxact)
Definition: predicate.c:275
#define offsetof(type, field)
Definition: c.h:656
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

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

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

5033 {
5034  TwoPhasePredicateRecord *record;
5035 
5036  Assert(len == sizeof(TwoPhasePredicateRecord));
5037 
5038  record = (TwoPhasePredicateRecord *) recdata;
5039 
5040  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
5041  (record->type == TWOPHASEPREDICATERECORD_LOCK));
5042 
5043  if (record->type == TWOPHASEPREDICATERECORD_XACT)
5044  {
5045  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
5046  TwoPhasePredicateXactRecord *xactRecord;
5047  SERIALIZABLEXACT *sxact;
5048  SERIALIZABLEXID *sxid;
5049  SERIALIZABLEXIDTAG sxidtag;
5050  bool found;
5051 
5052  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
5053 
5054  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
5055  sxact = CreatePredXact();
5056  if (!sxact)
5057  ereport(ERROR,
5058  (errcode(ERRCODE_OUT_OF_MEMORY),
5059  errmsg("out of shared memory")));
5060 
5061  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
5062  sxact->vxid.backendId = InvalidBackendId;
5064  sxact->pid = 0;
5065 
5066  /* a prepared xact hasn't committed yet */
5070 
5072 
5073  /*
5074  * Don't need to track this; no transactions running at the time the
5075  * recovered xact started are still active, except possibly other
5076  * prepared xacts and we don't care whether those are RO_SAFE or not.
5077  */
5079 
5080  SHMQueueInit(&(sxact->predicateLocks));
5081  SHMQueueElemInit(&(sxact->finishedLink));
5082 
5083  sxact->topXid = xid;
5084  sxact->xmin = xactRecord->xmin;
5085  sxact->flags = xactRecord->flags;
5086  Assert(SxactIsPrepared(sxact));
5087  if (!SxactIsReadOnly(sxact))
5088  {
5092  }
5093 
5094  /*
5095  * We don't know whether the transaction had any conflicts or not, so
5096  * we'll conservatively assume that it had both a conflict in and a
5097  * conflict out, and represent that with the summary conflict flags.
5098  */
5099  SHMQueueInit(&(sxact->outConflicts));
5100  SHMQueueInit(&(sxact->inConflicts));
5103 
5104  /* Register the transaction's xid */
5105  sxidtag.xid = xid;
5107  &sxidtag,
5108  HASH_ENTER, &found);
5109  Assert(sxid != NULL);
5110  Assert(!found);
5111  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5112 
5113  /*
5114  * Update global xmin. Note that this is a special case compared to
5115  * registering a normal transaction, because the global xmin might go
5116  * backwards. That's OK, because until recovery is over we're not
5117  * going to complete any transactions or create any non-prepared
5118  * transactions, so there's no danger of throwing away.
5119  */
5122  {
5123  PredXact->SxactGlobalXmin = sxact->xmin;
5126  }
5127  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5128  {
5131  }
5132 
5133  LWLockRelease(SerializableXactHashLock);
5134  }
5135  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5136  {
5137  /* Lock record. Recreate the PREDICATELOCK */
5138  TwoPhasePredicateLockRecord *lockRecord;
5139  SERIALIZABLEXID *sxid;
5140  SERIALIZABLEXACT *sxact;
5141  SERIALIZABLEXIDTAG sxidtag;
5142  uint32 targettaghash;
5143 
5144  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5145  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5146 
5147  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5148  sxidtag.xid = xid;
5149  sxid = (SERIALIZABLEXID *)
5150  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5151  LWLockRelease(SerializableXactHashLock);
5152 
5153  Assert(sxid != NULL);
5154  sxact = sxid->myXact;
5155  Assert(sxact != InvalidSerializableXact);
5156 
5157  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5158  }
5159 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:279
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2379
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:382
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:608
static HTAB * SerializableXidHash
Definition: predicate.c:394
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:66
PREDICATELOCKTARGETTAG target
union TwoPhasePredicateRecord::@110 data
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
union SERIALIZABLEXACT::@109 SeqNo
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:135
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:359
uint32 LocalTransactionId
Definition: c.h:510
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:301
#define InvalidBackendId
Definition: backendid.h:23
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:733
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:967
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:583

◆ PredicateLockPage()

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

Definition at line 2526 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(), _hash_first(), _hash_readnext(), collectMatchBitmap(), gistScanPage(), IndexOnlyNext(), moveRightIfItNeeded(), scanPendingInsert(), and startScanEntry().

2527 {
2529 
2530  if (!SerializationNeededForRead(relation, snapshot))
2531  return;
2532 
2534  relation->rd_node.dbNode,
2535  relation->rd_id,
2536  blkno);
2537  PredicateLockAcquire(&tag);
2538 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2444
Oid rd_id
Definition: rel.h:85
RelFileNode rd_node
Definition: rel.h:54
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:517

◆ PredicateLockPageCombine()

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

Definition at line 3187 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

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

◆ PredicateLockPageSplit()

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

Definition at line 3102 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(), _hash_splitbucket(), createPostingTree(), ginPlaceToPage(), gistplacetopage(), and PredicateLockPageCombine().

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

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 2503 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(), and index_beginscan_internal().

2504 {
2506 
2507  if (!SerializationNeededForRead(relation, snapshot))
2508  return;
2509 
2511  relation->rd_node.dbNode,
2512  relation->rd_id);
2513  PredicateLockAcquire(&tag);
2514 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2444
Oid rd_id
Definition: rel.h:85
RelFileNode rd_node
Definition: rel.h:54
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:517

◆ PredicateLockShmemSize()

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:262
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:31
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:144
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:135
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:732
#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:467
#define PredXactListElementDataSize

◆ PredicateLockTuple()

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

Definition at line 2548 of file predicate.c.

References RelFileNode::dbNode, HeapTupleHeaderGetXmin, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, PredicateLockAcquire(), PredicateLockExists(), RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, SerializationNeededForRead(), SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, HeapTupleData::t_data, HeapTupleData::t_self, and TransactionIdIsCurrentTransactionId().

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

2549 {
2551  ItemPointer tid;
2552 
2553  if (!SerializationNeededForRead(relation, snapshot))
2554  return;
2555 
2556  /*
2557  * If it's a heap tuple, return if this xact wrote it.
2558  */
2559  if (relation->rd_index == NULL)
2560  {
2561  /* If we wrote it; we already have a write lock. */
2563  return;
2564  }
2565 
2566  /*
2567  * Do quick-but-not-definitive test for a relation lock first. This will
2568  * never cause a return when the relation is *not* locked, but will
2569  * occasionally let the check continue when there really *is* a relation
2570  * level lock.
2571  */
2573  relation->rd_node.dbNode,
2574  relation->rd_id);
2575  if (PredicateLockExists(&tag))
2576  return;
2577 
2578  tid = &(tuple->t_self);
2580  relation->rd_node.dbNode,
2581  relation->rd_id,
2584  PredicateLockAcquire(&tag);
2585 }
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1961
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
HeapTupleHeader t_data
Definition: htup.h:68
Form_pg_index rd_index
Definition: rel.h:143
ItemPointerData t_self
Definition: htup.h:65
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2444
Oid rd_id
Definition: rel.h:85
RelFileNode rd_node
Definition: rel.h:54
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:517
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 5004 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

5005 {
5006  SERIALIZABLEXID *sxid;
5007  SERIALIZABLEXIDTAG sxidtag;
5008 
5009  sxidtag.xid = xid;
5010 
5011  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5012  sxid = (SERIALIZABLEXID *)
5013  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5014  LWLockRelease(SerializableXactHashLock);
5015 
5016  /* xid will not be found if it wasn't a serializable transaction */
5017  if (sxid == NULL)
5018  return;
5019 
5020  /* Release its locks */
5021  MySerializableXact = sxid->myXact;
5022  MyXactDidWrite = true; /* conservatively assume that we wrote
5023  * something */
5024  ReleasePredicateLocks(isCommit, false);
5025 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
static HTAB * SerializableXidHash
Definition: predicate.c:394
SERIALIZABLEXACT * myXact
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
Definition: predicate.c:3267
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static bool MyXactDidWrite
Definition: predicate.c:420

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

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

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

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)

Definition at line 3267 of file predicate.c.

References Assert, PredXactListData::CanPartialClearThrough, ClearOldPredicateLocks(), SERIALIZABLEXACT::commitSeqNo, SERIALIZABLEXACT::earliestOutConflictCommit, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, FlagSxactUnsafe(), SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, InvalidSerializableXact, IsInParallelMode(), IsolationIsSerializable, IsParallelWorker, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, MyXactDidWrite, VariableCacheData::nextFullXid, offsetof, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, ParallelContextActive(), SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::prepareSeqNo, ProcSendSignal(), ReleaseOneSerializableXact(), ReleasePredicateLocksLocal(), ReleaseRWConflict(), SavedSerializableXact, SERIALIZABLEXACT::SeqNo, SetNewSxactGlobalXmin(), ShmemVariableCache, SHMQueueEmpty(), SHMQueueInsertBefore(), SHMQueueNext(), SXACT_FLAG_COMMITTED, SXACT_FLAG_CONFLICT_OUT, SXACT_FLAG_DOOMED, SXACT_FLAG_PARTIALLY_RELEASED, 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, SxactIsPartiallyReleased, SxactIsPrepared, SxactIsReadOnly, SxactIsRolledBack, SxactIsROSafe, SxactIsROUnsafe, RWConflictData::sxactOut, TransactionIdEquals, PredXactListData::WritableSxactCount, XidFromFullTransactionId, and SERIALIZABLEXACT::xmin.

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

3268 {
3269  bool needToClear;
3270  RWConflict conflict,
3271  nextConflict,
3272  possibleUnsafeConflict;
3273  SERIALIZABLEXACT *roXact;
3274 
3275  /*
3276  * We can't trust XactReadOnly here, because a transaction which started
3277  * as READ WRITE can show as READ ONLY later, e.g., within
3278  * subtransactions. We want to flag a transaction as READ ONLY if it
3279  * commits without writing so that de facto READ ONLY transactions get the
3280  * benefit of some RO optimizations, so we will use this local variable to
3281  * get some cleanup logic right which is based on whether the transaction
3282  * was declared READ ONLY at the top level.
3283  */
3284  bool topLevelIsDeclaredReadOnly;
3285 
3286  /* We can't be both committing and releasing early due to RO_SAFE. */
3287  Assert(!(isCommit && isReadOnlySafe));
3288 
3289  /* Are we at the end of a transaction, that is, a commit or abort? */
3290  if (!isReadOnlySafe)
3291  {
3292  /*
3293  * Parallel workers mustn't release predicate locks at the end of
3294  * their transaction. The leader will do that at the end of its
3295  * transaction.
3296  */
3297  if (IsParallelWorker())
3298  {
3300  return;
3301  }
3302 
3303  /*
3304  * By the time the leader in a parallel query reaches end of
3305  * transaction, it has waited for all workers to exit.
3306  */
3308 
3309  /*
3310  * If the leader in a parallel query earlier stashed a partially
3311  * released SERIALIZABLEXACT for final clean-up at end of transaction
3312  * (because workers might still have been accessing it), then it's
3313  * time to restore it.
3314  */
3316  {
3321  }
3322  }
3323 
3325  {
3326  Assert(LocalPredicateLockHash == NULL);
3327  return;
3328  }
3329 
3330  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3331 
3332  /*
3333  * If the transaction is committing, but it has been partially released
3334  * already, then treat this as a roll back. It was marked as rolled back.
3335  */
3337  isCommit = false;
3338 
3339  /*
3340  * If we're called in the middle of a transaction because we discovered
3341  * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3342  * it (that is, release the predicate locks and conflicts, but not the
3343  * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3344  */
3345  if (isReadOnlySafe && IsInParallelMode())
3346  {
3347  /*
3348  * The leader needs to stash a pointer to it, so that it can
3349  * completely release it at end-of-transaction.
3350  */
3351  if (!IsParallelWorker())
3353 
3354  /*
3355  * The first backend to reach this condition will partially release
3356  * the SERIALIZABLEXACT. All others will just clear their
3357  * backend-local state so that they stop doing SSI checks for the rest
3358  * of the transaction.
3359  */
3361  {
3362  LWLockRelease(SerializableXactHashLock);
3364  return;
3365  }
3366  else
3367  {
3369  /* ... and proceed to perform the partial release below. */
3370  }
3371  }
3372  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3373  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3377 
3378  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3380 
3381  /* We'd better not already be on the cleanup list. */
3383 
3384  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3385 
3386  /*
3387  * We don't hold XidGenLock lock here, assuming that TransactionId is
3388  * atomic!
3389  *
3390  * If this value is changing, we don't care that much whether we get the
3391  * old or new value -- it is just used to determine how far
3392  * SxactGlobalXmin must advance before this transaction can be fully
3393  * cleaned up. The worst that could happen is we wait for one more
3394  * transaction to complete before freeing some RAM; correctness of visible
3395  * behavior is not affected.
3396  */
3398 
3399  /*
3400  * If it's not a commit it's either a rollback or a read-only transaction
3401  * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3402  */
3403  if (isCommit)
3404  {
3407  /* Recognize implicit read-only transaction (commit without write). */
3408  if (!MyXactDidWrite)
3410  }
3411  else
3412  {
3413  /*
3414  * The DOOMED flag indicates that we intend to roll back this
3415  * transaction and so it should not cause serialization failures for
3416  * other transactions that conflict with it. Note that this flag might
3417  * already be set, if another backend marked this transaction for
3418  * abort.
3419  *
3420  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3421  * has been called, and so the SerializableXact is eligible for
3422  * cleanup. This means it should not be considered when calculating
3423  * SxactGlobalXmin.
3424  */
3427 
3428  /*
3429  * If the transaction was previously prepared, but is now failing due
3430  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3431  * prepare, clear the prepared flag. This simplifies conflict
3432  * checking.
3433  */
3435  }
3436 
3437  if (!topLevelIsDeclaredReadOnly)
3438  {
3440  if (--(PredXact->WritableSxactCount) == 0)
3441  {
3442  /*
3443  * Release predicate locks and rw-conflicts in for all committed
3444  * transactions. There are no longer any transactions which might
3445  * conflict with the locks and no chance for new transactions to
3446  * overlap. Similarly, existing conflicts in can't cause pivots,
3447  * and any conflicts in which could have completed a dangerous
3448  * structure would already have caused a rollback, so any
3449  * remaining ones must be benign.
3450  */
3452  }
3453  }
3454  else
3455  {
3456  /*
3457  * Read-only transactions: clear the list of transactions that might
3458  * make us unsafe. Note that we use 'inLink' for the iteration as
3459  * opposed to 'outLink' for the r/w xacts.
3460  */
3461  possibleUnsafeConflict = (RWConflict)
3464  offsetof(RWConflictData, inLink));
3465  while (possibleUnsafeConflict)
3466  {
3467  nextConflict = (RWConflict)
3469  &possibleUnsafeConflict->inLink,
3470  offsetof(RWConflictData, inLink));
3471 
3472  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3473  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3474 
3475  ReleaseRWConflict(possibleUnsafeConflict);
3476 
3477  possibleUnsafeConflict = nextConflict;
3478  }
3479  }
3480 
3481  /* Check for conflict out to old committed transactions. */
3482  if (isCommit
3485  {
3486  /*
3487  * we don't know which old committed transaction we conflicted with,
3488  * so be conservative and use FirstNormalSerCommitSeqNo here
3489  */
3493  }
3494 
3495  /*
3496  * Release all outConflicts to committed transactions. If we're rolling
3497  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3498  * previously committed transactions.
3499  */
3500  conflict = (RWConflict)
3503  offsetof(RWConflictData, outLink));
3504  while (conflict)
3505  {
3506  nextConflict = (RWConflict)
3508  &conflict->outLink,
3509  offsetof(RWConflictData, outLink));
3510 
3511  if (isCommit
3513  && SxactIsCommitted(conflict->sxactIn))
3514  {
3519  }
3520 
3521  if (!isCommit
3522  || SxactIsCommitted(conflict->sxactIn)
3524  ReleaseRWConflict(conflict);
3525 
3526  conflict = nextConflict;
3527  }
3528 
3529  /*
3530  * Release all inConflicts from committed and read-only transactions. If
3531  * we're rolling back, clear them all.
3532  */
3533  conflict = (RWConflict)
3536  offsetof(RWConflictData, inLink));
3537  while (conflict)
3538  {
3539  nextConflict = (RWConflict)
3541  &conflict->inLink,
3542  offsetof(RWConflictData, inLink));
3543 
3544  if (!isCommit
3545  || SxactIsCommitted(conflict->sxactOut)
3546  || SxactIsReadOnly(conflict->sxactOut))
3547  ReleaseRWConflict(conflict);
3548 
3549  conflict = nextConflict;
3550  }
3551 
3552  if (!topLevelIsDeclaredReadOnly)
3553  {
3554  /*
3555  * Remove ourselves from the list of possible conflicts for concurrent
3556  * READ ONLY transactions, flagging them as unsafe if we have a
3557  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3558  * up if they are known safe or known unsafe.
3559  */
3560  possibleUnsafeConflict = (RWConflict)
3563  offsetof(RWConflictData, outLink));
3564  while (possibleUnsafeConflict)
3565  {
3566  nextConflict = (RWConflict)
3568  &possibleUnsafeConflict->outLink,
3569  offsetof(RWConflictData, outLink));
3570 
3571  roXact = possibleUnsafeConflict->sxactIn;
3572  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3573  Assert(SxactIsReadOnly(roXact));
3574 
3575  /* Mark conflicted if necessary. */
3576  if (isCommit
3577  && MyXactDidWrite
3580  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3581  {
3582  /*
3583  * This releases possibleUnsafeConflict (as well as all other
3584  * possible conflicts for roXact)
3585  */
3586  FlagSxactUnsafe(roXact);
3587  }
3588  else
3589  {
3590  ReleaseRWConflict(possibleUnsafeConflict);
3591 
3592  /*
3593  * If we were the last possible conflict, flag it safe. The
3594  * transaction can now safely release its predicate locks (but
3595  * that transaction's backend has to do that itself).
3596  */
3597  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3598  roXact->flags |= SXACT_FLAG_RO_SAFE;
3599  }
3600 
3601  /*
3602  * Wake up the process for a waiting DEFERRABLE transaction if we
3603  * now know it's either safe or conflicted.
3604  */
3605  if (SxactIsDeferrableWaiting(roXact) &&
3606  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3607  ProcSendSignal(roXact->pid);
3608 
3609  possibleUnsafeConflict = nextConflict;
3610  }
3611  }
3612 
3613  /*
3614  * Check whether it's time to clean up old transactions. This can only be
3615  * done when the last serializable transaction with the oldest xmin among
3616  * serializable transactions completes. We then find the "new oldest"
3617  * xmin and purge any transactions which finished before this transaction
3618  * was launched.
3619  */
3620  needToClear = false;
3622  {
3624  if (--(PredXact->SxactGlobalXminCount) == 0)
3625  {
3627  needToClear = true;
3628  }
3629  }
3630 
3631  LWLockRelease(SerializableXactHashLock);
3632 
3633  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3634 
3635  /* Add this to the list of transactions to check for later cleanup. */
3636  if (isCommit)
3639 
3640  /*
3641  * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3642  * partially release it. That's necessary because other backends may have
3643  * a reference to it. The leader will release the SERIALIZABLEXACT itself
3644  * at the end of the transaction after workers have stopped running.
3645  */
3646  if (!isCommit)
3648  isReadOnlySafe && IsInParallelMode(),
3649  false);
3650 
3651  LWLockRelease(SerializableFinishedListLock);
3652 
3653  if (needToClear)
3655 
3657 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:279
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
TransactionId finishedBefore
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static PredXactList PredXact
Definition: predicate.c:382
TransactionId SxactGlobalXmin
static void ReleasePredicateLocksLocal(void)
Definition: predicate.c:3660
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3678
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:745
FullTransactionId nextFullXid
Definition: transam.h:164
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:265
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:753
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1810
#define SxactIsDoomed(sxact)
Definition: predicate.c:278
bool IsInParallelMode(void)
Definition: xact.c:996
#define SxactIsRolledBack(sxact)
Definition: predicate.c:277
SHM_QUEUE possibleUnsafeConflicts
#define SXACT_FLAG_RO_SAFE
static SERIALIZABLEXACT * SavedSerializableXact
Definition: predicate.c:429
union SERIALIZABLEXACT::@109 SeqNo
#define InvalidSerializableXact
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_PREPARED
SerCommitSeqNo lastCommitBeforeSnapshot
#define SxactIsROSafe(sxact)
Definition: predicate.c:289
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:281
#define IsParallelWorker()
Definition: parallel.h:60
SerCommitSeqNo commitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
bool ParallelContextActive(void)
Definition: parallel.c:944
#define SXACT_FLAG_PARTIALLY_RELEASED
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:287
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3835
#define Assert(condition)
Definition: c.h:733
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:288
#define SXACT_FLAG_ROLLED_BACK
SerCommitSeqNo prepareSeqNo
static HTAB * LocalPredicateLockHash
Definition: predicate.c:412
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define SxactIsPartiallyReleased(sxact)
Definition: predicate.c:291
#define IsolationIsSerializable()
Definition: xact.h:52
#define SXACT_FLAG_READ_ONLY
static bool MyXactDidWrite
Definition: predicate.c:420
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:290
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:397
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3209
#define SxactIsCommitted(sxact)
Definition: predicate.c:275
#define offsetof(type, field)
Definition: c.h:656
SERIALIZABLEXACT * sxactOut

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1653 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1656 {
1658 
1659  /*
1660  * If this is called by parallel.c in a parallel worker, we don't want to
1661  * create a SERIALIZABLEXACT just yet because the leader's
1662  * SERIALIZABLEXACT will be installed with AttachSerializableXact(). We
1663  * also don't want to reject SERIALIZABLE READ ONLY DEFERRABLE in this
1664  * case, because the leader has already determined that the snapshot it
1665  * has passed us is safe. So there is nothing for us to do.
1666  */
1667  if (IsParallelWorker())
1668  return;
1669 
1670  /*
1671  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1672  * import snapshots, since there's no way to wait for a safe snapshot when
1673  * we're using the snap we're told to. (XXX instead of throwing an error,
1674  * we could just ignore the XactDeferrable flag?)
1675  */
1677  ereport(ERROR,
1678  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1679  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1680 
1681  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1682  sourcepid);
1683 }
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:608
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1695
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define IsParallelWorker()
Definition: parallel.h:60
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:733
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define IsolationIsSerializable()
Definition: xact.h:52

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5167 of file predicate.c.

References MySerializableXact.

Referenced by InitializeParallelDSM().

5168 {
5169  return MySerializableXact;
5170 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3081 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3082 {
3083  DropAllPredicateLocksFromTable(relation, true);
3084 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2885

Variable Documentation

◆ max_predicate_locks_per_page

int max_predicate_locks_per_page

Definition at line 371 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

int max_predicate_locks_per_relation

Definition at line 370 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

int max_predicate_locks_per_xact

Definition at line 369 of file predicate.c.

Referenced by CreateLocalPredicateLockHash(), and MaxPredicateChildLocks().