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_SERIAL_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 PredicateLockTID (Relation relation, ItemPointer tid, Snapshot snapshot, TransactionId insert_xid)
 
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)
 
bool CheckForSerializableConflictOutNeeded (Relation relation, Snapshot snapshot)
 
void CheckForSerializableConflictOut (Relation relation, TransactionId xid, Snapshot snapshot)
 
void CheckForSerializableConflictIn (Relation relation, ItemPointer tid, BlockNumber blkno)
 
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_SERIAL_BUFFERS

#define NUM_SERIAL_BUFFERS   16

Definition at line 31 of file predicate.h.

Referenced by PredicateLockShmemSize(), and SerialInit().

Typedef Documentation

◆ SerializableXactHandle

typedef void* SerializableXactHandle

Definition at line 37 of file predicate.h.

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

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

4854 {
4855  PREDICATELOCK *predlock;
4856  SERIALIZABLEXACT *sxact;
4857  TwoPhasePredicateRecord record;
4858  TwoPhasePredicateXactRecord *xactRecord;
4859  TwoPhasePredicateLockRecord *lockRecord;
4860 
4861  sxact = MySerializableXact;
4862  xactRecord = &(record.data.xactRecord);
4863  lockRecord = &(record.data.lockRecord);
4864 
4866  return;
4867 
4868  /* Generate an xact record for our SERIALIZABLEXACT */
4870  xactRecord->xmin = MySerializableXact->xmin;
4871  xactRecord->flags = MySerializableXact->flags;
4872 
4873  /*
4874  * Note that we don't include the list of conflicts in our out in the
4875  * statefile, because new conflicts can be added even after the
4876  * transaction prepares. We'll just make a conservative assumption during
4877  * recovery instead.
4878  */
4879 
4881  &record, sizeof(record));
4882 
4883  /*
4884  * Generate a lock record for each lock.
4885  *
4886  * To do this, we need to walk the predicate lock list in our sxact rather
4887  * than using the local predicate lock table because the latter is not
4888  * guaranteed to be accurate.
4889  */
4890  LWLockAcquire(SerializablePredicateListLock, LW_SHARED);
4891 
4892  /*
4893  * No need to take sxact->perXactPredicateListLock in parallel mode
4894  * because there cannot be any parallel workers running while we are
4895  * preparing a transaction.
4896  */
4898 
4899  predlock = (PREDICATELOCK *)
4900  SHMQueueNext(&(sxact->predicateLocks),
4901  &(sxact->predicateLocks),
4902  offsetof(PREDICATELOCK, xactLink));
4903 
4904  while (predlock != NULL)
4905  {
4907  lockRecord->target = predlock->tag.myTarget->tag;
4908 
4910  &record, sizeof(record));
4911 
4912  predlock = (PREDICATELOCK *)
4913  SHMQueueNext(&(sxact->predicateLocks),
4914  &(predlock->xactLink),
4915  offsetof(PREDICATELOCK, xactLink));
4916  }
4917 
4918  LWLockRelease(SerializablePredicateListLock);
4919 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
union TwoPhasePredicateRecord::@108 data
TwoPhasePredicateRecordType type
PREDICATELOCKTARGETTAG target
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1187
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
#define IsParallelWorker()
Definition: parallel.h:61
bool ParallelContextActive(void)
Definition: parallel.c:978
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:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:661
PREDICATELOCKTARGET * myTarget

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5123 of file predicate.c.

References Assert, CreateLocalPredicateLockHash(), and InvalidSerializableXact.

Referenced by ParallelWorkerMain().

5124 {
5125 
5127 
5128  MySerializableXact = (SERIALIZABLEXACT *) handle;
5131 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:738
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1852

◆ CheckForSerializableConflictIn()

void CheckForSerializableConflictIn ( Relation  relation,
ItemPointer  tid,
BlockNumber  blkno 
)

Definition at line 4374 of file predicate.c.

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

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

4375 {
4376  PREDICATELOCKTARGETTAG targettag;
4377 
4378  if (!SerializationNeededForWrite(relation))
4379  return;
4380 
4381  /* Check if someone else has already decided that we need to die */
4383  ereport(ERROR,
4384  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4385  errmsg("could not serialize access due to read/write dependencies among transactions"),
4386  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4387  errhint("The transaction might succeed if retried.")));
4388 
4389  /*
4390  * We're doing a write which might cause rw-conflicts now or later.
4391  * Memorize that fact.
4392  */
4393  MyXactDidWrite = true;
4394 
4395  /*
4396  * It is important that we check for locks from the finest granularity to
4397  * the coarsest granularity, so that granularity promotion doesn't cause
4398  * us to miss a lock. The new (coarser) lock will be acquired before the
4399  * old (finer) locks are released.
4400  *
4401  * It is not possible to take and hold a lock across the checks for all
4402  * granularities because each target could be in a separate partition.
4403  */
4404  if (tid != NULL)
4405  {
4407  relation->rd_node.dbNode,
4408  relation->rd_id,
4411  CheckTargetForConflictsIn(&targettag);
4412  }
4413 
4414  if (blkno != InvalidBlockNumber)
4415  {
4417  relation->rd_node.dbNode,
4418  relation->rd_id,
4419  blkno);
4420  CheckTargetForConflictsIn(&targettag);
4421  }
4422 
4424  relation->rd_node.dbNode,
4425  relation->rd_id);
4426  CheckTargetForConflictsIn(&targettag);
4427 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1071
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4192
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:610
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:558
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:43
Oid rd_id
Definition: rel.h:111
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode rd_node
Definition: rel.h:55
#define InvalidBlockNumber
Definition: block.h:33
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
int errmsg(const char *fmt,...)
Definition: elog.c:824
static bool MyXactDidWrite
Definition: predicate.c:417
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ CheckForSerializableConflictOut()

void CheckForSerializableConflictOut ( Relation  relation,
TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 4049 of file predicate.c.

References Assert, SERIALIZABLEXACT::earliestOutConflictCommit, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerialGetMinConflictCommitSeqNo(), SerializationNeededForRead(), SHMQueueEmpty(), SXACT_FLAG_DOOMED, SXACT_FLAG_SUMMARY_CONFLICT_OUT, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdIsValid, SERIALIZABLEXIDTAG::xid, and XidIsConcurrent().

Referenced by HeapCheckForSerializableConflictOut().

4050 {
4051  SERIALIZABLEXIDTAG sxidtag;
4052  SERIALIZABLEXID *sxid;
4053  SERIALIZABLEXACT *sxact;
4054 
4055  if (!SerializationNeededForRead(relation, snapshot))
4056  return;
4057 
4058  /* Check if someone else has already decided that we need to die */
4060  {
4061  ereport(ERROR,
4062  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4063  errmsg("could not serialize access due to read/write dependencies among transactions"),
4064  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4065  errhint("The transaction might succeed if retried.")));
4066  }
4068 
4070  return;
4071 
4072  /*
4073  * Find sxact or summarized info for the top level xid.
4074  */
4075  sxidtag.xid = xid;
4076  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4077  sxid = (SERIALIZABLEXID *)
4078  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4079  if (!sxid)
4080  {
4081  /*
4082  * Transaction not found in "normal" SSI structures. Check whether it
4083  * got pushed out to SLRU storage for "old committed" transactions.
4084  */
4085  SerCommitSeqNo conflictCommitSeqNo;
4086 
4087  conflictCommitSeqNo = SerialGetMinConflictCommitSeqNo(xid);
4088  if (conflictCommitSeqNo != 0)
4089  {
4090  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4092  || conflictCommitSeqNo
4094  ereport(ERROR,
4095  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4096  errmsg("could not serialize access due to read/write dependencies among transactions"),
4097  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4098  errhint("The transaction might succeed if retried.")));
4099 
4102  ereport(ERROR,
4103  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4104  errmsg("could not serialize access due to read/write dependencies among transactions"),
4105  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4106  errhint("The transaction might succeed if retried.")));
4107 
4109  }
4110 
4111  /* It's not serializable or otherwise not important. */
4112  LWLockRelease(SerializableXactHashLock);
4113  return;
4114  }
4115  sxact = sxid->myXact;
4116  Assert(TransactionIdEquals(sxact->topXid, xid));
4117  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4118  {
4119  /* Can't conflict with ourself or a transaction that will roll back. */
4120  LWLockRelease(SerializableXactHashLock);
4121  return;
4122  }
4123 
4124  /*
4125  * We have a conflict out to a transaction which has a conflict out to a
4126  * summarized transaction. That summarized transaction must have
4127  * committed first, and we can't tell when it committed in relation to our
4128  * snapshot acquisition, so something needs to be canceled.
4129  */
4130  if (SxactHasSummaryConflictOut(sxact))
4131  {
4132  if (!SxactIsPrepared(sxact))
4133  {
4134  sxact->flags |= SXACT_FLAG_DOOMED;
4135  LWLockRelease(SerializableXactHashLock);
4136  return;
4137  }
4138  else
4139  {
4140  LWLockRelease(SerializableXactHashLock);
4141  ereport(ERROR,
4142  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4143  errmsg("could not serialize access due to read/write dependencies among transactions"),
4144  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4145  errhint("The transaction might succeed if retried.")));
4146  }
4147  }
4148 
4149  /*
4150  * If this is a read-only transaction and the writing transaction has
4151  * committed, and it doesn't have a rw-conflict to a transaction which
4152  * committed before it, no conflict.
4153  */
4155  && SxactIsCommitted(sxact)
4156  && !SxactHasSummaryConflictOut(sxact)
4157  && (!SxactHasConflictOut(sxact)
4159  {
4160  /* Read-only transaction will appear to run first. No conflict. */
4161  LWLockRelease(SerializableXactHashLock);
4162  return;
4163  }
4164 
4165  if (!XidIsConcurrent(xid))
4166  {
4167  /* This write was already in our snapshot; no conflict. */
4168  LWLockRelease(SerializableXactHashLock);
4169  return;
4170  }
4171 
4173  {
4174  /* We don't want duplicate conflict records in the list. */
4175  LWLockRelease(SerializableXactHashLock);
4176  return;
4177  }
4178 
4179  /*
4180  * Flag the conflict. But first, if this conflict creates a dangerous
4181  * structure, ereport an error.
4182  */
4184  LWLockRelease(SerializableXactHashLock);
4185 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:653
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4549
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:277
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3994
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
int errcode(int sqlerrcode)
Definition: elog.c:610
static HTAB * SerializableXidHash
Definition: predicate.c:391
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:923
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:43
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:410
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:278
#define InvalidSerCommitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo earliestOutConflictCommit
#define ereport(elevel,...)
Definition: elog.h:144
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:284
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514
int errmsg(const char *fmt,...)
Definition: elog.c:824
union SERIALIZABLEXACT::@107 SeqNo
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define SxactIsCommitted(sxact)
Definition: predicate.c:272

◆ CheckForSerializableConflictOutNeeded()

bool CheckForSerializableConflictOutNeeded ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 4020 of file predicate.c.

References ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, SerializationNeededForRead(), and SxactIsDoomed.

Referenced by HeapCheckForSerializableConflictOut().

4021 {
4022  if (!SerializationNeededForRead(relation, snapshot))
4023  return false;
4024 
4025  /* Check if someone else has already decided that we need to die */
4027  {
4028  ereport(ERROR,
4029  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4030  errmsg("could not serialize access due to read/write dependencies among transactions"),
4031  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4032  errhint("The transaction might succeed if retried.")));
4033  }
4034 
4035  return true;
4036 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1071
int errcode(int sqlerrcode)
Definition: elog.c:610
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1015 of file predicate.c.

References SerialControlData::headPage, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SerialPage, SerialSlruCtl, SimpleLruFlush(), SimpleLruTruncate(), SerialControlData::tailXid, and TransactionIdIsValid.

Referenced by CheckPointGuts().

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

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)

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

4458 {
4459  HASH_SEQ_STATUS seqstat;
4460  PREDICATELOCKTARGET *target;
4461  Oid dbId;
4462  Oid heapId;
4463  int i;
4464 
4465  /*
4466  * Bail out quickly if there are no serializable transactions running.
4467  * It's safe to check this without taking locks because the caller is
4468  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4469  * would matter here can be acquired while that is held.
4470  */
4472  return;
4473 
4474  if (!SerializationNeededForWrite(relation))
4475  return;
4476 
4477  /*
4478  * We're doing a write which might cause rw-conflicts now or later.
4479  * Memorize that fact.
4480  */
4481  MyXactDidWrite = true;
4482 
4483  Assert(relation->rd_index == NULL); /* not an index relation */
4484 
4485  dbId = relation->rd_node.dbNode;
4486  heapId = relation->rd_id;
4487 
4488  LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
4489  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4491  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4492 
4493  /* Scan through target list */
4495 
4496  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4497  {
4498  PREDICATELOCK *predlock;
4499 
4500  /*
4501  * Check whether this is a target which needs attention.
4502  */
4503  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4504  continue; /* wrong relation id */
4505  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4506  continue; /* wrong database id */
4507 
4508  /*
4509  * Loop through locks for this target and flag conflicts.
4510  */
4511  predlock = (PREDICATELOCK *)
4512  SHMQueueNext(&(target->predicateLocks),
4513  &(target->predicateLocks),
4514  offsetof(PREDICATELOCK, targetLink));
4515  while (predlock)
4516  {
4517  PREDICATELOCK *nextpredlock;
4518 
4519  nextpredlock = (PREDICATELOCK *)
4520  SHMQueueNext(&(target->predicateLocks),
4521  &(predlock->targetLink),
4522  offsetof(PREDICATELOCK, targetLink));
4523 
4524  if (predlock->tag.myXact != MySerializableXact
4526  {
4528  }
4529 
4530  predlock = nextpredlock;
4531  }
4532  }
4533 
4534  /* Release locks in reverse order */
4535  LWLockRelease(SerializableXactHashLock);
4536  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4538  LWLockRelease(SerializablePredicateListLock);
4539 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:653
static HTAB * PredicateLockTargetHash
Definition: predicate.c:392
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4549
static PredXactList PredXact
Definition: predicate.c:379
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:558
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
Form_pg_index rd_index
Definition: rel.h:174
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:111
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:55
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1391
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1381
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:256
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:417
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:661
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:120

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1610 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

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

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

Definition at line 1080 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_PER_XACT_PREDICATE_LIST, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, HASHCTL::num_partitions, NUM_PREDICATELOCK_PARTITIONS, PredXactListData::OldCommittedSxact, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::perXactPredicateListLock, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, predicatelock_hash(), PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXactListDataSize, PredXactListElementDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPoolHeaderDataSize, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SerialInit(), 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().

1081 {
1082  HASHCTL info;
1083  long max_table_size;
1084  Size requestSize;
1085  bool found;
1086 
1087 #ifndef EXEC_BACKEND
1089 #endif
1090 
1091  /*
1092  * Compute size of predicate lock target hashtable. Note these
1093  * calculations must agree with PredicateLockShmemSize!
1094  */
1095  max_table_size = NPREDICATELOCKTARGETENTS();
1096 
1097  /*
1098  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1099  * per-predicate-lock-target information.
1100  */
1101  MemSet(&info, 0, sizeof(info));
1102  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1103  info.entrysize = sizeof(PREDICATELOCKTARGET);
1105 
1106  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1107  max_table_size,
1108  max_table_size,
1109  &info,
1110  HASH_ELEM | HASH_BLOBS |
1112 
1113  /*
1114  * Reserve a dummy entry in the hash table; we use it to make sure there's
1115  * always one entry available when we need to split or combine a page,
1116  * because running out of space there could mean aborting a
1117  * non-serializable transaction.
1118  */
1119  if (!IsUnderPostmaster)
1120  {
1122  HASH_ENTER, &found);
1123  Assert(!found);
1124  }
1125 
1126  /* Pre-calculate the hash and partition lock of the scratch entry */
1129 
1130  /*
1131  * Allocate hash table for PREDICATELOCK structs. This stores per
1132  * xact-lock-of-a-target information.
1133  */
1134  MemSet(&info, 0, sizeof(info));
1135  info.keysize = sizeof(PREDICATELOCKTAG);
1136  info.entrysize = sizeof(PREDICATELOCK);
1137  info.hash = predicatelock_hash;
1139 
1140  /* Assume an average of 2 xacts per target */
1141  max_table_size *= 2;
1142 
1143  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1144  max_table_size,
1145  max_table_size,
1146  &info,
1149 
1150  /*
1151  * Compute size for serializable transaction hashtable. Note these
1152  * calculations must agree with PredicateLockShmemSize!
1153  */
1154  max_table_size = (MaxBackends + max_prepared_xacts);
1155 
1156  /*
1157  * Allocate a list to hold information on transactions participating in
1158  * predicate locking.
1159  *
1160  * Assume an average of 10 predicate locking transactions per backend.
1161  * This allows aggressive cleanup while detail is present before data must
1162  * be summarized for storage in SLRU and the "dummy" transaction.
1163  */
1164  max_table_size *= 10;
1165 
1166  PredXact = ShmemInitStruct("PredXactList",
1168  &found);
1169  Assert(found == IsUnderPostmaster);
1170  if (!found)
1171  {
1172  int i;
1173 
1182  requestSize = mul_size((Size) max_table_size,
1184  PredXact->element = ShmemAlloc(requestSize);
1185  /* Add all elements to available list, clean. */
1186  memset(PredXact->element, 0, requestSize);
1187  for (i = 0; i < max_table_size; i++)
1188  {
1192  &(PredXact->element[i].link));
1193  }
1209  }
1210  /* This never changes, so let's keep a local copy. */
1212 
1213  /*
1214  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1215  * information for serializable transactions which have accessed data.
1216  */
1217  MemSet(&info, 0, sizeof(info));
1218  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1219  info.entrysize = sizeof(SERIALIZABLEXID);
1220 
1221  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1222  max_table_size,
1223  max_table_size,
1224  &info,
1225  HASH_ELEM | HASH_BLOBS |
1226  HASH_FIXED_SIZE);
1227 
1228  /*
1229  * Allocate space for tracking rw-conflicts in lists attached to the
1230  * transactions.
1231  *
1232  * Assume an average of 5 conflicts per transaction. Calculations suggest
1233  * that this will prevent resource exhaustion in even the most pessimal
1234  * loads up to max_connections = 200 with all 200 connections pounding the
1235  * database with serializable transactions. Beyond that, there may be
1236  * occasional transactions canceled when trying to flag conflicts. That's
1237  * probably OK.
1238  */
1239  max_table_size *= 5;
1240 
1241  RWConflictPool = ShmemInitStruct("RWConflictPool",
1243  &found);
1244  Assert(found == IsUnderPostmaster);
1245  if (!found)
1246  {
1247  int i;
1248 
1250  requestSize = mul_size((Size) max_table_size,
1252  RWConflictPool->element = ShmemAlloc(requestSize);
1253  /* Add all elements to available list, clean. */
1254  memset(RWConflictPool->element, 0, requestSize);
1255  for (i = 0; i < max_table_size; i++)
1256  {
1258  &(RWConflictPool->element[i].outLink));
1259  }
1260  }
1261 
1262  /*
1263  * Create or attach to the header for the list of finished serializable
1264  * transactions.
1265  */
1267  ShmemInitStruct("FinishedSerializableTransactions",
1268  sizeof(SHM_QUEUE),
1269  &found);
1270  Assert(found == IsUnderPostmaster);
1271  if (!found)
1273 
1274  /*
1275  * Initialize the SLRU storage for old committed serializable
1276  * transactions.
1277  */
1278  SerialInit();
1279 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:392
#define HASH_ELEM
Definition: hsearch.h:87
static void SerialInit(void)
Definition: predicate.c:814
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:259
static PredXactList PredXact
Definition: predicate.c:379
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:1347
static HTAB * SerializableXidHash
Definition: predicate.c:391
#define MemSet(start, val, len)
Definition: c.h:971
void * ShmemAlloc(Size size)
Definition: shmem.c:161
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:908
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:253
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:393
int max_prepared_xacts
Definition: twophase.c:117
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:385
struct PREDICATELOCK PREDICATELOCK
long num_partitions
Definition: hsearch.h:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
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:745
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:88
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:738
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:76
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:357
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
union SERIALIZABLEXACT::@107 SeqNo
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:401
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:337
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:394
static uint32 ScratchTargetTagHash
Definition: predicate.c:402
static LWLock * ScratchPartitionLock
Definition: predicate.c:403
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:580
PredXactListElement element
#define PredXactListElementDataSize
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:120

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

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

1922 {
1923  PREDICATELOCKTARGETTAG targettag;
1924  uint32 targettaghash;
1925  LWLock *partitionLock;
1926  PREDICATELOCKTARGET *target;
1927 
1929  relation->rd_node.dbNode,
1930  relation->rd_id,
1931  blkno);
1932 
1933  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1934  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1935  LWLockAcquire(partitionLock, LW_SHARED);
1936  target = (PREDICATELOCKTARGET *)
1938  &targettag, targettaghash,
1939  HASH_FIND, NULL);
1940  LWLockRelease(partitionLock);
1941 
1942  return (target != NULL);
1943 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:921
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:392
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:253
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
unsigned int uint32
Definition: c.h:367
Oid rd_id
Definition: rel.h:111
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
RelFileNode rd_node
Definition: rel.h:55
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4929 of file predicate.c.

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

Referenced by PrepareTransaction().

4930 {
4932  return;
4933 
4935 
4936  MySerializableXact->pid = 0;
4937 
4939  LocalPredicateLockHash = NULL;
4940 
4942  MyXactDidWrite = false;
4943 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:816
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:738
static HTAB * LocalPredicateLockHash
Definition: predicate.c:409
static bool MyXactDidWrite
Definition: predicate.c:417

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

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

4760 {
4761  RWConflict nearConflict;
4762 
4764  return;
4765 
4767 
4768  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4769 
4770  /* Check if someone else has already decided that we need to die */
4772  {
4774  LWLockRelease(SerializableXactHashLock);
4775  ereport(ERROR,
4776  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4777  errmsg("could not serialize access due to read/write dependencies among transactions"),
4778  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4779  errhint("The transaction might succeed if retried.")));
4780  }
4781 
4782  nearConflict = (RWConflict)
4785  offsetof(RWConflictData, inLink));
4786  while (nearConflict)
4787  {
4788  if (!SxactIsCommitted(nearConflict->sxactOut)
4789  && !SxactIsDoomed(nearConflict->sxactOut))
4790  {
4791  RWConflict farConflict;
4792 
4793  farConflict = (RWConflict)
4794  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4795  &nearConflict->sxactOut->inConflicts,
4796  offsetof(RWConflictData, inLink));
4797  while (farConflict)
4798  {
4799  if (farConflict->sxactOut == MySerializableXact
4800  || (!SxactIsCommitted(farConflict->sxactOut)
4801  && !SxactIsReadOnly(farConflict->sxactOut)
4802  && !SxactIsDoomed(farConflict->sxactOut)))
4803  {
4804  /*
4805  * Normally, we kill the pivot transaction to make sure we
4806  * make progress if the failing transaction is retried.
4807  * However, we can't kill it if it's already prepared, so
4808  * in that case we commit suicide instead.
4809  */
4810  if (SxactIsPrepared(nearConflict->sxactOut))
4811  {
4812  LWLockRelease(SerializableXactHashLock);
4813  ereport(ERROR,
4814  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4815  errmsg("could not serialize access due to read/write dependencies among transactions"),
4816  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4817  errhint("The transaction might succeed if retried.")));
4818  }
4819  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4820  break;
4821  }
4822  farConflict = (RWConflict)
4823  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4824  &farConflict->inLink,
4825  offsetof(RWConflictData, inLink));
4826  }
4827  }
4828 
4829  nearConflict = (RWConflict)
4831  &nearConflict->inLink,
4832  offsetof(RWConflictData, inLink));
4833  }
4834 
4837 
4838  LWLockRelease(SerializableXactHashLock);
4839 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1071
static PredXactList PredXact
Definition: predicate.c:379
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:610
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:43
#define InvalidSerializableXact
#define SXACT_FLAG_PREPARED
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define ereport(elevel,...)
Definition: elog.h:144
#define SXACT_FLAG_DOOMED
#define Assert(condition)
Definition: c.h:738
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define SxactIsPartiallyReleased(sxact)
Definition: predicate.c:288
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define IsolationIsSerializable()
Definition: xact.h:52
#define SxactIsCommitted(sxact)
Definition: predicate.c:272
#define offsetof(type, field)
Definition: c.h:661
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

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

Definition at line 4978 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, SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, SERIALIZABLEXACT::prepareSeqNo, RecoverySerCommitSeqNo, SERIALIZABLEXACT::SeqNo, SerialSetActiveSerXmin(), 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.

4980 {
4981  TwoPhasePredicateRecord *record;
4982 
4983  Assert(len == sizeof(TwoPhasePredicateRecord));
4984 
4985  record = (TwoPhasePredicateRecord *) recdata;
4986 
4987  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4988  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4989 
4990  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4991  {
4992  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4993  TwoPhasePredicateXactRecord *xactRecord;
4994  SERIALIZABLEXACT *sxact;
4995  SERIALIZABLEXID *sxid;
4996  SERIALIZABLEXIDTAG sxidtag;
4997  bool found;
4998 
4999  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
5000 
5001  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
5002  sxact = CreatePredXact();
5003  if (!sxact)
5004  ereport(ERROR,
5005  (errcode(ERRCODE_OUT_OF_MEMORY),
5006  errmsg("out of shared memory")));
5007 
5008  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
5009  sxact->vxid.backendId = InvalidBackendId;
5011  sxact->pid = 0;
5012 
5013  /* a prepared xact hasn't committed yet */
5017 
5019 
5020  /*
5021  * Don't need to track this; no transactions running at the time the
5022  * recovered xact started are still active, except possibly other
5023  * prepared xacts and we don't care whether those are RO_SAFE or not.
5024  */
5026 
5027  SHMQueueInit(&(sxact->predicateLocks));
5028  SHMQueueElemInit(&(sxact->finishedLink));
5029 
5030  sxact->topXid = xid;
5031  sxact->xmin = xactRecord->xmin;
5032  sxact->flags = xactRecord->flags;
5033  Assert(SxactIsPrepared(sxact));
5034  if (!SxactIsReadOnly(sxact))
5035  {
5039  }
5040 
5041  /*
5042  * We don't know whether the transaction had any conflicts or not, so
5043  * we'll conservatively assume that it had both a conflict in and a
5044  * conflict out, and represent that with the summary conflict flags.
5045  */
5046  SHMQueueInit(&(sxact->outConflicts));
5047  SHMQueueInit(&(sxact->inConflicts));
5050 
5051  /* Register the transaction's xid */
5052  sxidtag.xid = xid;
5054  &sxidtag,
5055  HASH_ENTER, &found);
5056  Assert(sxid != NULL);
5057  Assert(!found);
5058  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5059 
5060  /*
5061  * Update global xmin. Note that this is a special case compared to
5062  * registering a normal transaction, because the global xmin might go
5063  * backwards. That's OK, because until recovery is over we're not
5064  * going to complete any transactions or create any non-prepared
5065  * transactions, so there's no danger of throwing away.
5066  */
5069  {
5070  PredXact->SxactGlobalXmin = sxact->xmin;
5072  SerialSetActiveSerXmin(sxact->xmin);
5073  }
5074  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5075  {
5078  }
5079 
5080  LWLockRelease(SerializableXactHashLock);
5081  }
5082  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5083  {
5084  /* Lock record. Recreate the PREDICATELOCK */
5085  TwoPhasePredicateLockRecord *lockRecord;
5086  SERIALIZABLEXID *sxid;
5087  SERIALIZABLEXACT *sxact;
5088  SERIALIZABLEXIDTAG sxidtag;
5089  uint32 targettaghash;
5090 
5091  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5092  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5093 
5094  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5095  sxidtag.xid = xid;
5096  sxid = (SERIALIZABLEXID *)
5097  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5098  LWLockRelease(SerializableXactHashLock);
5099 
5100  Assert(sxid != NULL);
5101  sxact = sxid->myXact;
5102  Assert(sxact != InvalidSerializableXact);
5103 
5104  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5105  }
5106 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2376
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:379
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:610
static HTAB * SerializableXidHash
Definition: predicate.c:391
union TwoPhasePredicateRecord::@108 data
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:65
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:135
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:367
uint32 LocalTransactionId
Definition: c.h:515
SerCommitSeqNo lastCommitBeforeSnapshot
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
#define InvalidBackendId
Definition: backendid.h:23
#define ereport(elevel,...)
Definition: elog.h:144
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:738
BackendId backendId
Definition: lock.h:64
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:824
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
union SERIALIZABLEXACT::@107 SeqNo
static void SerialSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:964
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TwoPhasePredicateLockRecord lockRecord
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:580

◆ PredicateLockPage()

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

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

2524 {
2526 
2527  if (!SerializationNeededForRead(relation, snapshot))
2528  return;
2529 
2531  relation->rd_node.dbNode,
2532  relation->rd_id,
2533  blkno);
2534  PredicateLockAcquire(&tag);
2535 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2441
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:55
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514

◆ PredicateLockPageCombine()

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

Definition at line 3183 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

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

◆ PredicateLockPageSplit()

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

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

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

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

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

2501 {
2503 
2504  if (!SerializationNeededForRead(relation, snapshot))
2505  return;
2506 
2508  relation->rd_node.dbNode,
2509  relation->rd_id);
2510  PredicateLockAcquire(&tag);
2511 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2441
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:55
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514

◆ PredicateLockShmemSize()

Size PredicateLockShmemSize ( void  )

Definition at line 1285 of file predicate.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

1286 {
1287  Size size = 0;
1288  long max_table_size;
1289 
1290  /* predicate lock target hash table */
1291  max_table_size = NPREDICATELOCKTARGETENTS();
1292  size = add_size(size, hash_estimate_size(max_table_size,
1293  sizeof(PREDICATELOCKTARGET)));
1294 
1295  /* predicate lock hash table */
1296  max_table_size *= 2;
1297  size = add_size(size, hash_estimate_size(max_table_size,
1298  sizeof(PREDICATELOCK)));
1299 
1300  /*
1301  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1302  * margin.
1303  */
1304  size = add_size(size, size / 10);
1305 
1306  /* transaction list */
1307  max_table_size = MaxBackends + max_prepared_xacts;
1308  max_table_size *= 10;
1309  size = add_size(size, PredXactListDataSize);
1310  size = add_size(size, mul_size((Size) max_table_size,
1312 
1313  /* transaction xid table */
1314  size = add_size(size, hash_estimate_size(max_table_size,
1315  sizeof(SERIALIZABLEXID)));
1316 
1317  /* rw-conflict pool */
1318  max_table_size *= 5;
1319  size = add_size(size, RWConflictPoolHeaderDataSize);
1320  size = add_size(size, mul_size((Size) max_table_size,
1322 
1323  /* Head for list of finished serializable transactions. */
1324  size = add_size(size, sizeof(SHM_QUEUE));
1325 
1326  /* Shared memory structures for SLRU tracking of old committed xids. */
1327  size = add_size(size, sizeof(SerialControlData));
1329 
1330  return size;
1331 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:259
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:144
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:135
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:734
#define RWConflictPoolHeaderDataSize
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define NUM_SERIAL_BUFFERS
Definition: predicate.h:31
size_t Size
Definition: c.h:466
#define PredXactListElementDataSize

◆ PredicateLockTID()

void PredicateLockTID ( Relation  relation,
ItemPointer  tid,
Snapshot  snapshot,
TransactionId  insert_xid 
)

Definition at line 2545 of file predicate.c.

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

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

2547 {
2549 
2550  if (!SerializationNeededForRead(relation, snapshot))
2551  return;
2552 
2553  /*
2554  * Return if this xact wrote it.
2555  */
2556  if (relation->rd_index == NULL)
2557  {
2558  /* If we wrote it; we already have a write lock. */
2559  if (TransactionIdIsCurrentTransactionId(tuple_xid))
2560  return;
2561  }
2562 
2563  /*
2564  * Do quick-but-not-definitive test for a relation lock first. This will
2565  * never cause a return when the relation is *not* locked, but will
2566  * occasionally let the check continue when there really *is* a relation
2567  * level lock.
2568  */
2570  relation->rd_node.dbNode,
2571  relation->rd_id);
2572  if (PredicateLockExists(&tag))
2573  return;
2574 
2576  relation->rd_node.dbNode,
2577  relation->rd_id,
2580  PredicateLockAcquire(&tag);
2581 }
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:854
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1958
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
Form_pg_index rd_index
Definition: rel.h:174
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2441
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:55
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4951 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

4952 {
4953  SERIALIZABLEXID *sxid;
4954  SERIALIZABLEXIDTAG sxidtag;
4955 
4956  sxidtag.xid = xid;
4957 
4958  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4959  sxid = (SERIALIZABLEXID *)
4960  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4961  LWLockRelease(SerializableXactHashLock);
4962 
4963  /* xid will not be found if it wasn't a serializable transaction */
4964  if (sxid == NULL)
4965  return;
4966 
4967  /* Release its locks */
4968  MySerializableXact = sxid->myXact;
4969  MyXactDidWrite = true; /* conservatively assume that we wrote
4970  * something */
4971  ReleasePredicateLocks(isCommit, false);
4972 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
static HTAB * SerializableXidHash
Definition: predicate.c:391
SERIALIZABLEXACT * myXact
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
Definition: predicate.c:3263
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static bool MyXactDidWrite
Definition: predicate.c:417

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

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

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

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)

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

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

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1650 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

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

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5114 of file predicate.c.

References MySerializableXact.

Referenced by InitializeParallelDSM().

5115 {
5116  return MySerializableXact;
5117 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3077 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3078 {
3079  DropAllPredicateLocksFromTable(relation, true);
3080 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2881

Variable Documentation

◆ max_predicate_locks_per_page

int max_predicate_locks_per_page

Definition at line 368 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

int max_predicate_locks_per_relation

Definition at line 367 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

int max_predicate_locks_per_xact

Definition at line 366 of file predicate.c.

Referenced by CreateLocalPredicateLockHash(), and MaxPredicateChildLocks().