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

Definition at line 37 of file predicate.h.

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

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

4923 {
4924  PREDICATELOCK *predlock;
4925  SERIALIZABLEXACT *sxact;
4926  TwoPhasePredicateRecord record;
4927  TwoPhasePredicateXactRecord *xactRecord;
4928  TwoPhasePredicateLockRecord *lockRecord;
4929 
4930  sxact = MySerializableXact;
4931  xactRecord = &(record.data.xactRecord);
4932  lockRecord = &(record.data.lockRecord);
4933 
4935  return;
4936 
4937  /* Generate an xact record for our SERIALIZABLEXACT */
4939  xactRecord->xmin = MySerializableXact->xmin;
4940  xactRecord->flags = MySerializableXact->flags;
4941 
4942  /*
4943  * Note that we don't include the list of conflicts in our out in the
4944  * statefile, because new conflicts can be added even after the
4945  * transaction prepares. We'll just make a conservative assumption during
4946  * recovery instead.
4947  */
4948 
4950  &record, sizeof(record));
4951 
4952  /*
4953  * Generate a lock record for each lock.
4954  *
4955  * To do this, we need to walk the predicate lock list in our sxact rather
4956  * than using the local predicate lock table because the latter is not
4957  * guaranteed to be accurate.
4958  */
4959  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4960 
4961  /*
4962  * No need to take sxact->predicateLockListLock in parallel mode because
4963  * there cannot be any parallel workers running while we are preparing a
4964  * transaction.
4965  */
4967 
4968  predlock = (PREDICATELOCK *)
4969  SHMQueueNext(&(sxact->predicateLocks),
4970  &(sxact->predicateLocks),
4971  offsetof(PREDICATELOCK, xactLink));
4972 
4973  while (predlock != NULL)
4974  {
4976  lockRecord->target = predlock->tag.myTarget->tag;
4977 
4979  &record, sizeof(record));
4980 
4981  predlock = (PREDICATELOCK *)
4982  SHMQueueNext(&(sxact->predicateLocks),
4983  &(predlock->xactLink),
4984  offsetof(PREDICATELOCK, xactLink));
4985  }
4986 
4987  LWLockRelease(SerializablePredicateLockListLock);
4988 }
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:1204
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:945
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:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:655
PREDICATELOCKTARGET * myTarget

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5192 of file predicate.c.

References Assert, CreateLocalPredicateLockHash(), and InvalidSerializableXact.

Referenced by ParallelWorkerMain().

5193 {
5194 
5196 
5197  MySerializableXact = (SERIALIZABLEXACT *) handle;
5200 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:732
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1855

◆ CheckForSerializableConflictIn()

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

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

4444 {
4445  PREDICATELOCKTARGETTAG targettag;
4446 
4447  if (!SerializationNeededForWrite(relation))
4448  return;
4449 
4450  /* Check if someone else has already decided that we need to die */
4452  ereport(ERROR,
4453  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4454  errmsg("could not serialize access due to read/write dependencies among transactions"),
4455  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4456  errhint("The transaction might succeed if retried.")));
4457 
4458  /*
4459  * We're doing a write which might cause rw-conflicts now or later.
4460  * Memorize that fact.
4461  */
4462  MyXactDidWrite = true;
4463 
4464  /*
4465  * It is important that we check for locks from the finest granularity to
4466  * the coarsest granularity, so that granularity promotion doesn't cause
4467  * us to miss a lock. The new (coarser) lock will be acquired before the
4468  * old (finer) locks are released.
4469  *
4470  * It is not possible to take and hold a lock across the checks for all
4471  * granularities because each target could be in a separate partition.
4472  */
4473  if (tuple != NULL)
4474  {
4476  relation->rd_node.dbNode,
4477  relation->rd_id,
4478  ItemPointerGetBlockNumber(&(tuple->t_self)),
4479  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4480  CheckTargetForConflictsIn(&targettag);
4481  }
4482 
4483  if (BufferIsValid(buffer))
4484  {
4486  relation->rd_node.dbNode,
4487  relation->rd_id,
4488  BufferGetBlockNumber(buffer));
4489  CheckTargetForConflictsIn(&targettag);
4490  }
4491 
4493  relation->rd_node.dbNode,
4494  relation->rd_id);
4495  CheckTargetForConflictsIn(&targettag);
4496 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
int errhint(const char *fmt,...)
Definition: elog.c:974
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4260
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:570
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:887
#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:784
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 4057 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().

4060 {
4061  TransactionId xid;
4062  SERIALIZABLEXIDTAG sxidtag;
4063  SERIALIZABLEXID *sxid;
4064  SERIALIZABLEXACT *sxact;
4065  HTSV_Result htsvResult;
4066 
4067  if (!SerializationNeededForRead(relation, snapshot))
4068  return;
4069 
4070  /* Check if someone else has already decided that we need to die */
4072  {
4073  ereport(ERROR,
4074  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4075  errmsg("could not serialize access due to read/write dependencies among transactions"),
4076  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4077  errhint("The transaction might succeed if retried.")));
4078  }
4079 
4080  /*
4081  * Check to see whether the tuple has been written to by a concurrent
4082  * transaction, either to create it not visible to us, or to delete it
4083  * while it is visible to us. The "visible" bool indicates whether the
4084  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
4085  * is going on with it.
4086  */
4087  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
4088  switch (htsvResult)
4089  {
4090  case HEAPTUPLE_LIVE:
4091  if (visible)
4092  return;
4093  xid = HeapTupleHeaderGetXmin(tuple->t_data);
4094  break;
4096  if (!visible)
4097  return;
4098  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
4099  break;
4101  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
4102  break;
4104  xid = HeapTupleHeaderGetXmin(tuple->t_data);
4105  break;
4106  case HEAPTUPLE_DEAD:
4107  return;
4108  default:
4109 
4110  /*
4111  * The only way to get to this default clause is if a new value is
4112  * added to the enum type without adding it to this switch
4113  * statement. That's a bug, so elog.
4114  */
4115  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
4116 
4117  /*
4118  * In spite of having all enum values covered and calling elog on
4119  * this default, some compilers think this is a code path which
4120  * allows xid to be used below without initialization. Silence
4121  * that warning.
4122  */
4123  xid = InvalidTransactionId;
4124  }
4127 
4128  /*
4129  * Find top level xid. Bail out if xid is too early to be a conflict, or
4130  * if it's our own xid.
4131  */
4133  return;
4134  xid = SubTransGetTopmostTransaction(xid);
4136  return;
4138  return;
4139 
4140  /*
4141  * Find sxact or summarized info for the top level xid.
4142  */
4143  sxidtag.xid = xid;
4144  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4145  sxid = (SERIALIZABLEXID *)
4146  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4147  if (!sxid)
4148  {
4149  /*
4150  * Transaction not found in "normal" SSI structures. Check whether it
4151  * got pushed out to SLRU storage for "old committed" transactions.
4152  */
4153  SerCommitSeqNo conflictCommitSeqNo;
4154 
4155  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
4156  if (conflictCommitSeqNo != 0)
4157  {
4158  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4160  || conflictCommitSeqNo
4162  ereport(ERROR,
4163  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4164  errmsg("could not serialize access due to read/write dependencies among transactions"),
4165  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4166  errhint("The transaction might succeed if retried.")));
4167 
4170  ereport(ERROR,
4171  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4172  errmsg("could not serialize access due to read/write dependencies among transactions"),
4173  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4174  errhint("The transaction might succeed if retried.")));
4175 
4177  }
4178 
4179  /* It's not serializable or otherwise not important. */
4180  LWLockRelease(SerializableXactHashLock);
4181  return;
4182  }
4183  sxact = sxid->myXact;
4184  Assert(TransactionIdEquals(sxact->topXid, xid));
4185  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4186  {
4187  /* Can't conflict with ourself or a transaction that will roll back. */
4188  LWLockRelease(SerializableXactHashLock);
4189  return;
4190  }
4191 
4192  /*
4193  * We have a conflict out to a transaction which has a conflict out to a
4194  * summarized transaction. That summarized transaction must have
4195  * committed first, and we can't tell when it committed in relation to our
4196  * snapshot acquisition, so something needs to be canceled.
4197  */
4198  if (SxactHasSummaryConflictOut(sxact))
4199  {
4200  if (!SxactIsPrepared(sxact))
4201  {
4202  sxact->flags |= SXACT_FLAG_DOOMED;
4203  LWLockRelease(SerializableXactHashLock);
4204  return;
4205  }
4206  else
4207  {
4208  LWLockRelease(SerializableXactHashLock);
4209  ereport(ERROR,
4210  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4211  errmsg("could not serialize access due to read/write dependencies among transactions"),
4212  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4213  errhint("The transaction might succeed if retried.")));
4214  }
4215  }
4216 
4217  /*
4218  * If this is a read-only transaction and the writing transaction has
4219  * committed, and it doesn't have a rw-conflict to a transaction which
4220  * committed before it, no conflict.
4221  */
4223  && SxactIsCommitted(sxact)
4224  && !SxactHasSummaryConflictOut(sxact)
4225  && (!SxactHasConflictOut(sxact)
4227  {
4228  /* Read-only transaction will appear to run first. No conflict. */
4229  LWLockRelease(SerializableXactHashLock);
4230  return;
4231  }
4232 
4233  if (!XidIsConcurrent(xid))
4234  {
4235  /* This write was already in our snapshot; no conflict. */
4236  LWLockRelease(SerializableXactHashLock);
4237  return;
4238  }
4239 
4241  {
4242  /* We don't want duplicate conflict records in the list. */
4243  LWLockRelease(SerializableXactHashLock);
4244  return;
4245  }
4246 
4247  /*
4248  * Flag the conflict. But first, if this conflict creates a dangerous
4249  * structure, ereport an error.
4250  */
4252  LWLockRelease(SerializableXactHashLock);
4253 }
#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:974
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4618
uint32 TransactionId
Definition: c.h:507
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:280
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:4014
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
int errcode(int sqlerrcode)
Definition: elog.c:570
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:887
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:410
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:732
#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:784
#define elog(elevel,...)
Definition: elog.h:226
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:1185
#define OldSerXidPage(xid)
Definition: predicate.c:341
#define OldSerXidSlruCtl
Definition: predicate.c:324
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1120
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 4526 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().

4527 {
4528  HASH_SEQ_STATUS seqstat;
4529  PREDICATELOCKTARGET *target;
4530  Oid dbId;
4531  Oid heapId;
4532  int i;
4533 
4534  /*
4535  * Bail out quickly if there are no serializable transactions running.
4536  * It's safe to check this without taking locks because the caller is
4537  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4538  * would matter here can be acquired while that is held.
4539  */
4541  return;
4542 
4543  if (!SerializationNeededForWrite(relation))
4544  return;
4545 
4546  /*
4547  * We're doing a write which might cause rw-conflicts now or later.
4548  * Memorize that fact.
4549  */
4550  MyXactDidWrite = true;
4551 
4552  Assert(relation->rd_index == NULL); /* not an index relation */
4553 
4554  dbId = relation->rd_node.dbNode;
4555  heapId = relation->rd_id;
4556 
4557  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4558  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4560  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4561 
4562  /* Scan through target list */
4564 
4565  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4566  {
4567  PREDICATELOCK *predlock;
4568 
4569  /*
4570  * Check whether this is a target which needs attention.
4571  */
4572  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4573  continue; /* wrong relation id */
4574  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4575  continue; /* wrong database id */
4576 
4577  /*
4578  * Loop through locks for this target and flag conflicts.
4579  */
4580  predlock = (PREDICATELOCK *)
4581  SHMQueueNext(&(target->predicateLocks),
4582  &(target->predicateLocks),
4583  offsetof(PREDICATELOCK, targetLink));
4584  while (predlock)
4585  {
4586  PREDICATELOCK *nextpredlock;
4587 
4588  nextpredlock = (PREDICATELOCK *)
4589  SHMQueueNext(&(target->predicateLocks),
4590  &(predlock->targetLink),
4591  offsetof(PREDICATELOCK, targetLink));
4592 
4593  if (predlock->tag.myXact != MySerializableXact
4595  {
4597  }
4598 
4599  predlock = nextpredlock;
4600  }
4601  }
4602 
4603  /* Release locks in reverse order */
4604  LWLockRelease(SerializableXactHashLock);
4605  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4607  LWLockRelease(SerializablePredicateLockListLock);
4608 }
#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:4618
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:732
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:655
#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:81
int errhint(const char *fmt,...)
Definition: elog.c:974
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1491
int errcode(int sqlerrcode)
Definition: elog.c:570
bool RecoveryInProgress(void)
Definition: xlog.c:7898
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:860
#define ereport(elevel, rest)
Definition: elog.h:141
bool XactReadOnly
Definition: xact.c:78
#define Assert(condition)
Definition: c.h:732
int errmsg(const char *fmt,...)
Definition: elog.c:784
#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:955
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:118
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:732
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:466
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:358
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 4998 of file predicate.c.

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

Referenced by PrepareTransaction().

4999 {
5001  return;
5002 
5004 
5005  MySerializableXact->pid = 0;
5006 
5008  LocalPredicateLockHash = NULL;
5009 
5011  MyXactDidWrite = false;
5012 }
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:732
static HTAB * LocalPredicateLockHash
Definition: predicate.c:412
static bool MyXactDidWrite
Definition: predicate.c:420

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

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

4829 {
4830  RWConflict nearConflict;
4831 
4833  return;
4834 
4836 
4837  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4838 
4839  /* Check if someone else has already decided that we need to die */
4841  {
4843  LWLockRelease(SerializableXactHashLock);
4844  ereport(ERROR,
4845  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4846  errmsg("could not serialize access due to read/write dependencies among transactions"),
4847  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4848  errhint("The transaction might succeed if retried.")));
4849  }
4850 
4851  nearConflict = (RWConflict)
4854  offsetof(RWConflictData, inLink));
4855  while (nearConflict)
4856  {
4857  if (!SxactIsCommitted(nearConflict->sxactOut)
4858  && !SxactIsDoomed(nearConflict->sxactOut))
4859  {
4860  RWConflict farConflict;
4861 
4862  farConflict = (RWConflict)
4863  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4864  &nearConflict->sxactOut->inConflicts,
4865  offsetof(RWConflictData, inLink));
4866  while (farConflict)
4867  {
4868  if (farConflict->sxactOut == MySerializableXact
4869  || (!SxactIsCommitted(farConflict->sxactOut)
4870  && !SxactIsReadOnly(farConflict->sxactOut)
4871  && !SxactIsDoomed(farConflict->sxactOut)))
4872  {
4873  /*
4874  * Normally, we kill the pivot transaction to make sure we
4875  * make progress if the failing transaction is retried.
4876  * However, we can't kill it if it's already prepared, so
4877  * in that case we commit suicide instead.
4878  */
4879  if (SxactIsPrepared(nearConflict->sxactOut))
4880  {
4881  LWLockRelease(SerializableXactHashLock);
4882  ereport(ERROR,
4883  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4884  errmsg("could not serialize access due to read/write dependencies among transactions"),
4885  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4886  errhint("The transaction might succeed if retried.")));
4887  }
4888  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4889  break;
4890  }
4891  farConflict = (RWConflict)
4892  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4893  &farConflict->inLink,
4894  offsetof(RWConflictData, inLink));
4895  }
4896  }
4897 
4898  nearConflict = (RWConflict)
4900  &nearConflict->inLink,
4901  offsetof(RWConflictData, inLink));
4902  }
4903 
4906 
4907  LWLockRelease(SerializableXactHashLock);
4908 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:279
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419
int errhint(const char *fmt,...)
Definition: elog.c:974
static PredXactList PredXact
Definition: predicate.c:382
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:570
#define SxactIsPrepared(sxact)
Definition: predicate.c:276
int errdetail_internal(const char *fmt,...)
Definition: elog.c:887
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:732
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:784
#define IsolationIsSerializable()
Definition: xact.h:52
#define SxactIsCommitted(sxact)
Definition: predicate.c:275
#define offsetof(type, field)
Definition: c.h:655
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

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

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

5049 {
5050  TwoPhasePredicateRecord *record;
5051 
5052  Assert(len == sizeof(TwoPhasePredicateRecord));
5053 
5054  record = (TwoPhasePredicateRecord *) recdata;
5055 
5056  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
5057  (record->type == TWOPHASEPREDICATERECORD_LOCK));
5058 
5059  if (record->type == TWOPHASEPREDICATERECORD_XACT)
5060  {
5061  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
5062  TwoPhasePredicateXactRecord *xactRecord;
5063  SERIALIZABLEXACT *sxact;
5064  SERIALIZABLEXID *sxid;
5065  SERIALIZABLEXIDTAG sxidtag;
5066  bool found;
5067 
5068  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
5069 
5070  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
5071  sxact = CreatePredXact();
5072  if (!sxact)
5073  ereport(ERROR,
5074  (errcode(ERRCODE_OUT_OF_MEMORY),
5075  errmsg("out of shared memory")));
5076 
5077  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
5078  sxact->vxid.backendId = InvalidBackendId;
5080  sxact->pid = 0;
5081 
5082  /* a prepared xact hasn't committed yet */
5086 
5088 
5089  /*
5090  * Don't need to track this; no transactions running at the time the
5091  * recovered xact started are still active, except possibly other
5092  * prepared xacts and we don't care whether those are RO_SAFE or not.
5093  */
5095 
5096  SHMQueueInit(&(sxact->predicateLocks));
5097  SHMQueueElemInit(&(sxact->finishedLink));
5098 
5099  sxact->topXid = xid;
5100  sxact->xmin = xactRecord->xmin;
5101  sxact->flags = xactRecord->flags;
5102  Assert(SxactIsPrepared(sxact));
5103  if (!SxactIsReadOnly(sxact))
5104  {
5108  }
5109 
5110  /*
5111  * We don't know whether the transaction had any conflicts or not, so
5112  * we'll conservatively assume that it had both a conflict in and a
5113  * conflict out, and represent that with the summary conflict flags.
5114  */
5115  SHMQueueInit(&(sxact->outConflicts));
5116  SHMQueueInit(&(sxact->inConflicts));
5119 
5120  /* Register the transaction's xid */
5121  sxidtag.xid = xid;
5123  &sxidtag,
5124  HASH_ENTER, &found);
5125  Assert(sxid != NULL);
5126  Assert(!found);
5127  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5128 
5129  /*
5130  * Update global xmin. Note that this is a special case compared to
5131  * registering a normal transaction, because the global xmin might go
5132  * backwards. That's OK, because until recovery is over we're not
5133  * going to complete any transactions or create any non-prepared
5134  * transactions, so there's no danger of throwing away.
5135  */
5138  {
5139  PredXact->SxactGlobalXmin = sxact->xmin;
5142  }
5143  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5144  {
5147  }
5148 
5149  LWLockRelease(SerializableXactHashLock);
5150  }
5151  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5152  {
5153  /* Lock record. Recreate the PREDICATELOCK */
5154  TwoPhasePredicateLockRecord *lockRecord;
5155  SERIALIZABLEXID *sxid;
5156  SERIALIZABLEXACT *sxact;
5157  SERIALIZABLEXIDTAG sxidtag;
5158  uint32 targettaghash;
5159 
5160  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5161  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5162 
5163  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5164  sxidtag.xid = xid;
5165  sxid = (SERIALIZABLEXID *)
5166  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5167  LWLockRelease(SerializableXactHashLock);
5168 
5169  Assert(sxid != NULL);
5170  sxact = sxid->myXact;
5171  Assert(sxact != InvalidSerializableXact);
5172 
5173  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5174  }
5175 }
#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:570
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:118
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:358
uint32 LocalTransactionId
Definition: c.h:509
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:732
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:784
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 3203 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

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

◆ PredicateLockPageSplit()

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

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

3120 {
3121  PREDICATELOCKTARGETTAG oldtargettag;
3122  PREDICATELOCKTARGETTAG newtargettag;
3123  bool success;
3124 
3125  /*
3126  * Bail out quickly if there are no serializable transactions running.
3127  *
3128  * It's safe to do this check without taking any additional locks. Even if
3129  * a serializable transaction starts concurrently, we know it can't take
3130  * any SIREAD locks on the page being split because the caller is holding
3131  * the associated buffer page lock. Memory reordering isn't an issue; the
3132  * memory barrier in the LWLock acquisition guarantees that this read
3133  * occurs while the buffer page lock is held.
3134  */
3136  return;
3137 
3138  if (!PredicateLockingNeededForRelation(relation))
3139  return;
3140 
3141  Assert(oldblkno != newblkno);
3142  Assert(BlockNumberIsValid(oldblkno));
3143  Assert(BlockNumberIsValid(newblkno));
3144 
3145  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3146  relation->rd_node.dbNode,
3147  relation->rd_id,
3148  oldblkno);
3149  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3150  relation->rd_node.dbNode,
3151  relation->rd_id,
3152  newblkno);
3153 
3154  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3155 
3156  /*
3157  * Try copying the locks over to the new page's tag, creating it if
3158  * necessary.
3159  */
3160  success = TransferPredicateLocksToNewTarget(oldtargettag,
3161  newtargettag,
3162  false);
3163 
3164  if (!success)
3165  {
3166  /*
3167  * No more predicate lock entries are available. Failure isn't an
3168  * option here, so promote the page lock to a relation lock.
3169  */
3170 
3171  /* Get the parent relation lock's lock tag */
3172  success = GetParentPredicateLockTag(&oldtargettag,
3173  &newtargettag);
3174  Assert(success);
3175 
3176  /*
3177  * Move the locks to the parent. This shouldn't fail.
3178  *
3179  * Note that here we are removing locks held by other backends,
3180  * leading to a possible inconsistency in their local lock hash table.
3181  * This is OK because we're replacing it with a lock that covers the
3182  * old one.
3183  */
3184  success = TransferPredicateLocksToNewTarget(oldtargettag,
3185  newtargettag,
3186  true);
3187  Assert(success);
3188  }
3189 
3190  LWLockRelease(SerializablePredicateLockListLock);
3191 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:498
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2684
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:732
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:145
int max_prepared_xacts
Definition: twophase.c:118
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:466
#define PredXactListElementDataSize

◆ PredicateLockTuple()

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

Definition at line 2548 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 heap_fetch(), heap_hot_search_buffer(), and heapam_scan_bitmap_next_block().

2549 {
2551  ItemPointer tid;
2552  TransactionId targetxmin;
2553 
2554  if (!SerializationNeededForRead(relation, snapshot))
2555  return;
2556 
2557  /*
2558  * If it's a heap tuple, return if this xact wrote it.
2559  */
2560  if (relation->rd_index == NULL)
2561  {
2562  TransactionId myxid;
2563 
2564  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2565 
2566  myxid = GetTopTransactionIdIfAny();
2567  if (TransactionIdIsValid(myxid))
2568  {
2570  {
2571  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2572 
2573  if (TransactionIdEquals(xid, myxid))
2574  {
2575  /* We wrote it; we already have a write lock. */
2576  return;
2577  }
2578  }
2579  }
2580  }
2581 
2582  /*
2583  * Do quick-but-not-definitive test for a relation lock first. This will
2584  * never cause a return when the relation is *not* locked, but will
2585  * occasionally let the check continue when there really *is* a relation
2586  * level lock.
2587  */
2589  relation->rd_node.dbNode,
2590  relation->rd_id);
2591  if (PredicateLockExists(&tag))
2592  return;
2593 
2594  tid = &(tuple->t_self);
2596  relation->rd_node.dbNode,
2597  relation->rd_id,
2600  PredicateLockAcquire(&tag);
2601 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1961
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:166
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
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:410
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
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 5020 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

5021 {
5022  SERIALIZABLEXID *sxid;
5023  SERIALIZABLEXIDTAG sxidtag;
5024 
5025  sxidtag.xid = xid;
5026 
5027  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5028  sxid = (SERIALIZABLEXID *)
5029  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5030  LWLockRelease(SerializableXactHashLock);
5031 
5032  /* xid will not be found if it wasn't a serializable transaction */
5033  if (sxid == NULL)
5034  return;
5035 
5036  /* Release its locks */
5037  MySerializableXact = sxid->myXact;
5038  MyXactDidWrite = true; /* conservatively assume that we wrote
5039  * something */
5040  ReleasePredicateLocks(isCommit, false);
5041 }
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:3283
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:732
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 3283 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().

3284 {
3285  bool needToClear;
3286  RWConflict conflict,
3287  nextConflict,
3288  possibleUnsafeConflict;
3289  SERIALIZABLEXACT *roXact;
3290 
3291  /*
3292  * We can't trust XactReadOnly here, because a transaction which started
3293  * as READ WRITE can show as READ ONLY later, e.g., within
3294  * subtransactions. We want to flag a transaction as READ ONLY if it
3295  * commits without writing so that de facto READ ONLY transactions get the
3296  * benefit of some RO optimizations, so we will use this local variable to
3297  * get some cleanup logic right which is based on whether the transaction
3298  * was declared READ ONLY at the top level.
3299  */
3300  bool topLevelIsDeclaredReadOnly;
3301 
3302  /* We can't be both committing and releasing early due to RO_SAFE. */
3303  Assert(!(isCommit && isReadOnlySafe));
3304 
3305  /* Are we at the end of a transaction, that is, a commit or abort? */
3306  if (!isReadOnlySafe)
3307  {
3308  /*
3309  * Parallel workers mustn't release predicate locks at the end of
3310  * their transaction. The leader will do that at the end of its
3311  * transaction.
3312  */
3313  if (IsParallelWorker())
3314  {
3316  return;
3317  }
3318 
3319  /*
3320  * By the time the leader in a parallel query reaches end of
3321  * transaction, it has waited for all workers to exit.
3322  */
3324 
3325  /*
3326  * If the leader in a parallel query earlier stashed a partially
3327  * released SERIALIZABLEXACT for final clean-up at end of transaction
3328  * (because workers might still have been accessing it), then it's
3329  * time to restore it.
3330  */
3332  {
3337  }
3338  }
3339 
3341  {
3342  Assert(LocalPredicateLockHash == NULL);
3343  return;
3344  }
3345 
3346  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3347 
3348  /*
3349  * If the transaction is committing, but it has been partially released
3350  * already, then treat this as a roll back. It was marked as rolled back.
3351  */
3353  isCommit = false;
3354 
3355  /*
3356  * If we're called in the middle of a transaction because we discovered
3357  * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3358  * it (that is, release the predicate locks and conflicts, but not the
3359  * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3360  */
3361  if (isReadOnlySafe && IsInParallelMode())
3362  {
3363  /*
3364  * The leader needs to stash a pointer to it, so that it can
3365  * completely release it at end-of-transaction.
3366  */
3367  if (!IsParallelWorker())
3369 
3370  /*
3371  * The first backend to reach this condition will partially release
3372  * the SERIALIZABLEXACT. All others will just clear their
3373  * backend-local state so that they stop doing SSI checks for the rest
3374  * of the transaction.
3375  */
3377  {
3378  LWLockRelease(SerializableXactHashLock);
3380  return;
3381  }
3382  else
3383  {
3385  /* ... and proceed to perform the partial release below. */
3386  }
3387  }
3388  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3389  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3393 
3394  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3396 
3397  /* We'd better not already be on the cleanup list. */
3399 
3400  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3401 
3402  /*
3403  * We don't hold XidGenLock lock here, assuming that TransactionId is
3404  * atomic!
3405  *
3406  * If this value is changing, we don't care that much whether we get the
3407  * old or new value -- it is just used to determine how far
3408  * SxactGlobalXmin must advance before this transaction can be fully
3409  * cleaned up. The worst that could happen is we wait for one more
3410  * transaction to complete before freeing some RAM; correctness of visible
3411  * behavior is not affected.
3412  */
3414 
3415  /*
3416  * If it's not a commit it's either a rollback or a read-only transaction
3417  * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3418  */
3419  if (isCommit)
3420  {
3423  /* Recognize implicit read-only transaction (commit without write). */
3424  if (!MyXactDidWrite)
3426  }
3427  else
3428  {
3429  /*
3430  * The DOOMED flag indicates that we intend to roll back this
3431  * transaction and so it should not cause serialization failures for
3432  * other transactions that conflict with it. Note that this flag might
3433  * already be set, if another backend marked this transaction for
3434  * abort.
3435  *
3436  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3437  * has been called, and so the SerializableXact is eligible for
3438  * cleanup. This means it should not be considered when calculating
3439  * SxactGlobalXmin.
3440  */
3443 
3444  /*
3445  * If the transaction was previously prepared, but is now failing due
3446  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3447  * prepare, clear the prepared flag. This simplifies conflict
3448  * checking.
3449  */
3451  }
3452 
3453  if (!topLevelIsDeclaredReadOnly)
3454  {
3456  if (--(PredXact->WritableSxactCount) == 0)
3457  {
3458  /*
3459  * Release predicate locks and rw-conflicts in for all committed
3460  * transactions. There are no longer any transactions which might
3461  * conflict with the locks and no chance for new transactions to
3462  * overlap. Similarly, existing conflicts in can't cause pivots,
3463  * and any conflicts in which could have completed a dangerous
3464  * structure would already have caused a rollback, so any
3465  * remaining ones must be benign.
3466  */
3468  }
3469  }
3470  else
3471  {
3472  /*
3473  * Read-only transactions: clear the list of transactions that might
3474  * make us unsafe. Note that we use 'inLink' for the iteration as
3475  * opposed to 'outLink' for the r/w xacts.
3476  */
3477  possibleUnsafeConflict = (RWConflict)
3480  offsetof(RWConflictData, inLink));
3481  while (possibleUnsafeConflict)
3482  {
3483  nextConflict = (RWConflict)
3485  &possibleUnsafeConflict->inLink,
3486  offsetof(RWConflictData, inLink));
3487 
3488  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3489  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3490 
3491  ReleaseRWConflict(possibleUnsafeConflict);
3492 
3493  possibleUnsafeConflict = nextConflict;
3494  }
3495  }
3496 
3497  /* Check for conflict out to old committed transactions. */
3498  if (isCommit
3501  {
3502  /*
3503  * we don't know which old committed transaction we conflicted with,
3504  * so be conservative and use FirstNormalSerCommitSeqNo here
3505  */
3509  }
3510 
3511  /*
3512  * Release all outConflicts to committed transactions. If we're rolling
3513  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3514  * previously committed transactions.
3515  */
3516  conflict = (RWConflict)
3519  offsetof(RWConflictData, outLink));
3520  while (conflict)
3521  {
3522  nextConflict = (RWConflict)
3524  &conflict->outLink,
3525  offsetof(RWConflictData, outLink));
3526 
3527  if (isCommit
3529  && SxactIsCommitted(conflict->sxactIn))
3530  {
3535  }
3536 
3537  if (!isCommit
3538  || SxactIsCommitted(conflict->sxactIn)
3540  ReleaseRWConflict(conflict);
3541 
3542  conflict = nextConflict;
3543  }
3544 
3545  /*
3546  * Release all inConflicts from committed and read-only transactions. If
3547  * we're rolling back, clear them all.
3548  */
3549  conflict = (RWConflict)
3552  offsetof(RWConflictData, inLink));
3553  while (conflict)
3554  {
3555  nextConflict = (RWConflict)
3557  &conflict->inLink,
3558  offsetof(RWConflictData, inLink));
3559 
3560  if (!isCommit
3561  || SxactIsCommitted(conflict->sxactOut)
3562  || SxactIsReadOnly(conflict->sxactOut))
3563  ReleaseRWConflict(conflict);
3564 
3565  conflict = nextConflict;
3566  }
3567 
3568  if (!topLevelIsDeclaredReadOnly)
3569  {
3570  /*
3571  * Remove ourselves from the list of possible conflicts for concurrent
3572  * READ ONLY transactions, flagging them as unsafe if we have a
3573  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3574  * up if they are known safe or known unsafe.
3575  */
3576  possibleUnsafeConflict = (RWConflict)
3579  offsetof(RWConflictData, outLink));
3580  while (possibleUnsafeConflict)
3581  {
3582  nextConflict = (RWConflict)
3584  &possibleUnsafeConflict->outLink,
3585  offsetof(RWConflictData, outLink));
3586 
3587  roXact = possibleUnsafeConflict->sxactIn;
3588  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3589  Assert(SxactIsReadOnly(roXact));
3590 
3591  /* Mark conflicted if necessary. */
3592  if (isCommit
3593  && MyXactDidWrite
3596  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3597  {
3598  /*
3599  * This releases possibleUnsafeConflict (as well as all other
3600  * possible conflicts for roXact)
3601  */
3602  FlagSxactUnsafe(roXact);
3603  }
3604  else
3605  {
3606  ReleaseRWConflict(possibleUnsafeConflict);
3607 
3608  /*
3609  * If we were the last possible conflict, flag it safe. The
3610  * transaction can now safely release its predicate locks (but
3611  * that transaction's backend has to do that itself).
3612  */
3613  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3614  roXact->flags |= SXACT_FLAG_RO_SAFE;
3615  }
3616 
3617  /*
3618  * Wake up the process for a waiting DEFERRABLE transaction if we
3619  * now know it's either safe or conflicted.
3620  */
3621  if (SxactIsDeferrableWaiting(roXact) &&
3622  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3623  ProcSendSignal(roXact->pid);
3624 
3625  possibleUnsafeConflict = nextConflict;
3626  }
3627  }
3628 
3629  /*
3630  * Check whether it's time to clean up old transactions. This can only be
3631  * done when the last serializable transaction with the oldest xmin among
3632  * serializable transactions completes. We then find the "new oldest"
3633  * xmin and purge any transactions which finished before this transaction
3634  * was launched.
3635  */
3636  needToClear = false;
3638  {
3640  if (--(PredXact->SxactGlobalXminCount) == 0)
3641  {
3643  needToClear = true;
3644  }
3645  }
3646 
3647  LWLockRelease(SerializableXactHashLock);
3648 
3649  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3650 
3651  /* Add this to the list of transactions to check for later cleanup. */
3652  if (isCommit)
3655 
3656  /*
3657  * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3658  * partially release it. That's necessary because other backends may have
3659  * a reference to it. The leader will release the SERIALIZABLEXACT itself
3660  * at the end of the transaction after workers have stopped running.
3661  */
3662  if (!isCommit)
3664  isReadOnlySafe && IsInParallelMode(),
3665  false);
3666 
3667  LWLockRelease(SerializableFinishedListLock);
3668 
3669  if (needToClear)
3671 
3673 }
#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:3676
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3694
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:1811
#define SxactIsDoomed(sxact)
Definition: predicate.c:278
bool IsInParallelMode(void)
Definition: xact.c:994
#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:945
#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:3851
#define Assert(condition)
Definition: c.h:732
#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:3225
#define SxactIsCommitted(sxact)
Definition: predicate.c:275
#define offsetof(type, field)
Definition: c.h:655
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:81
int errcode(int sqlerrcode)
Definition: elog.c:570
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:78
#define Assert(condition)
Definition: c.h:732
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define IsolationIsSerializable()
Definition: xact.h:52

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5183 of file predicate.c.

References MySerializableXact.

Referenced by InitializeParallelDSM().

5184 {
5185  return MySerializableXact;
5186 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:419

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3097 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3098 {
3099  DropAllPredicateLocksFromTable(relation, true);
3100 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2901

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