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

4855 {
4856  PREDICATELOCK *predlock;
4857  SERIALIZABLEXACT *sxact;
4858  TwoPhasePredicateRecord record;
4859  TwoPhasePredicateXactRecord *xactRecord;
4860  TwoPhasePredicateLockRecord *lockRecord;
4861 
4862  sxact = MySerializableXact;
4863  xactRecord = &(record.data.xactRecord);
4864  lockRecord = &(record.data.lockRecord);
4865 
4867  return;
4868 
4869  /* Generate an xact record for our SERIALIZABLEXACT */
4871  xactRecord->xmin = MySerializableXact->xmin;
4872  xactRecord->flags = MySerializableXact->flags;
4873 
4874  /*
4875  * Note that we don't include the list of conflicts in our out in the
4876  * statefile, because new conflicts can be added even after the
4877  * transaction prepares. We'll just make a conservative assumption during
4878  * recovery instead.
4879  */
4880 
4882  &record, sizeof(record));
4883 
4884  /*
4885  * Generate a lock record for each lock.
4886  *
4887  * To do this, we need to walk the predicate lock list in our sxact rather
4888  * than using the local predicate lock table because the latter is not
4889  * guaranteed to be accurate.
4890  */
4891  LWLockAcquire(SerializablePredicateListLock, LW_SHARED);
4892 
4893  /*
4894  * No need to take sxact->perXactPredicateListLock in parallel mode
4895  * because there cannot be any parallel workers running while we are
4896  * preparing a transaction.
4897  */
4899 
4900  predlock = (PREDICATELOCK *)
4901  SHMQueueNext(&(sxact->predicateLocks),
4902  &(sxact->predicateLocks),
4903  offsetof(PREDICATELOCK, xactLink));
4904 
4905  while (predlock != NULL)
4906  {
4908  lockRecord->target = predlock->tag.myTarget->tag;
4909 
4911  &record, sizeof(record));
4912 
4913  predlock = (PREDICATELOCK *)
4914  SHMQueueNext(&(sxact->predicateLocks),
4915  &(predlock->xactLink),
4916  offsetof(PREDICATELOCK, xactLink));
4917  }
4918 
4919  LWLockRelease(SerializablePredicateListLock);
4920 }
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:1181
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
#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:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:723
PREDICATELOCKTARGET * myTarget

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5124 of file predicate.c.

References Assert, CreateLocalPredicateLockHash(), and InvalidSerializableXact.

Referenced by ParallelWorkerMain().

5125 {
5126 
5128 
5129  MySerializableXact = (SERIALIZABLEXACT *) handle;
5132 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:800
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1850

◆ CheckForSerializableConflictIn()

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

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

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

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

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

Referenced by HeapCheckForSerializableConflictOut().

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

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1013 of file predicate.c.

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

Referenced by CheckPointGuts().

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

4459 {
4460  HASH_SEQ_STATUS seqstat;
4461  PREDICATELOCKTARGET *target;
4462  Oid dbId;
4463  Oid heapId;
4464  int i;
4465 
4466  /*
4467  * Bail out quickly if there are no serializable transactions running.
4468  * It's safe to check this without taking locks because the caller is
4469  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4470  * would matter here can be acquired while that is held.
4471  */
4473  return;
4474 
4475  if (!SerializationNeededForWrite(relation))
4476  return;
4477 
4478  /*
4479  * We're doing a write which might cause rw-conflicts now or later.
4480  * Memorize that fact.
4481  */
4482  MyXactDidWrite = true;
4483 
4484  Assert(relation->rd_index == NULL); /* not an index relation */
4485 
4486  dbId = relation->rd_node.dbNode;
4487  heapId = relation->rd_id;
4488 
4489  LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
4490  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4492  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4493 
4494  /* Scan through target list */
4496 
4497  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4498  {
4499  PREDICATELOCK *predlock;
4500 
4501  /*
4502  * Check whether this is a target which needs attention.
4503  */
4504  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4505  continue; /* wrong relation id */
4506  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4507  continue; /* wrong database id */
4508 
4509  /*
4510  * Loop through locks for this target and flag conflicts.
4511  */
4512  predlock = (PREDICATELOCK *)
4513  SHMQueueNext(&(target->predicateLocks),
4514  &(target->predicateLocks),
4515  offsetof(PREDICATELOCK, targetLink));
4516  while (predlock)
4517  {
4518  PREDICATELOCK *nextpredlock;
4519 
4520  nextpredlock = (PREDICATELOCK *)
4521  SHMQueueNext(&(target->predicateLocks),
4522  &(predlock->targetLink),
4523  offsetof(PREDICATELOCK, targetLink));
4524 
4525  if (predlock->tag.myXact != MySerializableXact
4527  {
4529  }
4530 
4531  predlock = nextpredlock;
4532  }
4533  }
4534 
4535  /* Release locks in reverse order */
4536  LWLockRelease(SerializableXactHashLock);
4537  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4539  LWLockRelease(SerializablePredicateListLock);
4540 }
#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:4550
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:1811
Form_pg_index rd_index
Definition: rel.h:175
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:112
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:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
#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:723
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:119

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1608 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

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

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

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

1079 {
1080  HASHCTL info;
1081  long max_table_size;
1082  Size requestSize;
1083  bool found;
1084 
1085 #ifndef EXEC_BACKEND
1087 #endif
1088 
1089  /*
1090  * Compute size of predicate lock target hashtable. Note these
1091  * calculations must agree with PredicateLockShmemSize!
1092  */
1093  max_table_size = NPREDICATELOCKTARGETENTS();
1094 
1095  /*
1096  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1097  * per-predicate-lock-target information.
1098  */
1099  MemSet(&info, 0, sizeof(info));
1100  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1101  info.entrysize = sizeof(PREDICATELOCKTARGET);
1103 
1104  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1105  max_table_size,
1106  max_table_size,
1107  &info,
1108  HASH_ELEM | HASH_BLOBS |
1110 
1111  /*
1112  * Reserve a dummy entry in the hash table; we use it to make sure there's
1113  * always one entry available when we need to split or combine a page,
1114  * because running out of space there could mean aborting a
1115  * non-serializable transaction.
1116  */
1117  if (!IsUnderPostmaster)
1118  {
1120  HASH_ENTER, &found);
1121  Assert(!found);
1122  }
1123 
1124  /* Pre-calculate the hash and partition lock of the scratch entry */
1127 
1128  /*
1129  * Allocate hash table for PREDICATELOCK structs. This stores per
1130  * xact-lock-of-a-target information.
1131  */
1132  MemSet(&info, 0, sizeof(info));
1133  info.keysize = sizeof(PREDICATELOCKTAG);
1134  info.entrysize = sizeof(PREDICATELOCK);
1135  info.hash = predicatelock_hash;
1137 
1138  /* Assume an average of 2 xacts per target */
1139  max_table_size *= 2;
1140 
1141  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1142  max_table_size,
1143  max_table_size,
1144  &info,
1147 
1148  /*
1149  * Compute size for serializable transaction hashtable. Note these
1150  * calculations must agree with PredicateLockShmemSize!
1151  */
1152  max_table_size = (MaxBackends + max_prepared_xacts);
1153 
1154  /*
1155  * Allocate a list to hold information on transactions participating in
1156  * predicate locking.
1157  *
1158  * Assume an average of 10 predicate locking transactions per backend.
1159  * This allows aggressive cleanup while detail is present before data must
1160  * be summarized for storage in SLRU and the "dummy" transaction.
1161  */
1162  max_table_size *= 10;
1163 
1164  PredXact = ShmemInitStruct("PredXactList",
1166  &found);
1167  Assert(found == IsUnderPostmaster);
1168  if (!found)
1169  {
1170  int i;
1171 
1180  requestSize = mul_size((Size) max_table_size,
1182  PredXact->element = ShmemAlloc(requestSize);
1183  /* Add all elements to available list, clean. */
1184  memset(PredXact->element, 0, requestSize);
1185  for (i = 0; i < max_table_size; i++)
1186  {
1190  &(PredXact->element[i].link));
1191  }
1207  }
1208  /* This never changes, so let's keep a local copy. */
1210 
1211  /*
1212  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1213  * information for serializable transactions which have accessed data.
1214  */
1215  MemSet(&info, 0, sizeof(info));
1216  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1217  info.entrysize = sizeof(SERIALIZABLEXID);
1218 
1219  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1220  max_table_size,
1221  max_table_size,
1222  &info,
1223  HASH_ELEM | HASH_BLOBS |
1224  HASH_FIXED_SIZE);
1225 
1226  /*
1227  * Allocate space for tracking rw-conflicts in lists attached to the
1228  * transactions.
1229  *
1230  * Assume an average of 5 conflicts per transaction. Calculations suggest
1231  * that this will prevent resource exhaustion in even the most pessimal
1232  * loads up to max_connections = 200 with all 200 connections pounding the
1233  * database with serializable transactions. Beyond that, there may be
1234  * occasional transactions canceled when trying to flag conflicts. That's
1235  * probably OK.
1236  */
1237  max_table_size *= 5;
1238 
1239  RWConflictPool = ShmemInitStruct("RWConflictPool",
1241  &found);
1242  Assert(found == IsUnderPostmaster);
1243  if (!found)
1244  {
1245  int i;
1246 
1248  requestSize = mul_size((Size) max_table_size,
1250  RWConflictPool->element = ShmemAlloc(requestSize);
1251  /* Add all elements to available list, clean. */
1252  memset(RWConflictPool->element, 0, requestSize);
1253  for (i = 0; i < max_table_size; i++)
1254  {
1256  &(RWConflictPool->element[i].outLink));
1257  }
1258  }
1259 
1260  /*
1261  * Create or attach to the header for the list of finished serializable
1262  * transactions.
1263  */
1265  ShmemInitStruct("FinishedSerializableTransactions",
1266  sizeof(SHM_QUEUE),
1267  &found);
1268  Assert(found == IsUnderPostmaster);
1269  if (!found)
1271 
1272  /*
1273  * Initialize the SLRU storage for old committed serializable
1274  * transactions.
1275  */
1276  SerialInit();
1277 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:392
#define HASH_ELEM
Definition: hsearch.h:85
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:72
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1345
static HTAB * SerializableXidHash
Definition: predicate.c:391
#define MemSet(start, val, len)
Definition: c.h:1004
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:919
#define HASH_PARTITION
Definition: hsearch.h:82
#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:136
#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:744
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:86
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:71
#define Assert(condition)
Definition: c.h:800
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:76
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:528
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:94
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:73
#define HASH_FUNCTION
Definition: hsearch.h:87
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:119

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

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

1920 {
1921  PREDICATELOCKTARGETTAG targettag;
1922  uint32 targettaghash;
1923  LWLock *partitionLock;
1924  PREDICATELOCKTARGET *target;
1925 
1927  relation->rd_node.dbNode,
1928  relation->rd_id,
1929  blkno);
1930 
1931  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1932  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1933  LWLockAcquire(partitionLock, LW_SHARED);
1934  target = (PREDICATELOCKTARGET *)
1936  &targettag, targettaghash,
1937  HASH_FIND, NULL);
1938  LWLockRelease(partitionLock);
1939 
1940  return (target != NULL);
1941 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
Definition: lwlock.h:31
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:1811
unsigned int uint32
Definition: c.h:429
Oid rd_id
Definition: rel.h:112
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
RelFileNode rd_node
Definition: rel.h:55
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4930 of file predicate.c.

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

Referenced by PrepareTransaction().

4931 {
4933  return;
4934 
4936 
4937  MySerializableXact->pid = 0;
4938 
4940  LocalPredicateLockHash = NULL;
4941 
4943  MyXactDidWrite = false;
4944 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:827
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:800
static HTAB * LocalPredicateLockHash
Definition: predicate.c:409
static bool MyXactDidWrite
Definition: predicate.c:417

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

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

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

◆ predicatelock_twophase_recover()

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

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

4981 {
4982  TwoPhasePredicateRecord *record;
4983 
4984  Assert(len == sizeof(TwoPhasePredicateRecord));
4985 
4986  record = (TwoPhasePredicateRecord *) recdata;
4987 
4988  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4989  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4990 
4991  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4992  {
4993  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4994  TwoPhasePredicateXactRecord *xactRecord;
4995  SERIALIZABLEXACT *sxact;
4996  SERIALIZABLEXID *sxid;
4997  SERIALIZABLEXIDTAG sxidtag;
4998  bool found;
4999 
5000  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
5001 
5002  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
5003  sxact = CreatePredXact();
5004  if (!sxact)
5005  ereport(ERROR,
5006  (errcode(ERRCODE_OUT_OF_MEMORY),
5007  errmsg("out of shared memory")));
5008 
5009  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
5010  sxact->vxid.backendId = InvalidBackendId;
5012  sxact->pid = 0;
5013 
5014  /* a prepared xact hasn't committed yet */
5018 
5020 
5021  /*
5022  * Don't need to track this; no transactions running at the time the
5023  * recovered xact started are still active, except possibly other
5024  * prepared xacts and we don't care whether those are RO_SAFE or not.
5025  */
5027 
5028  SHMQueueInit(&(sxact->predicateLocks));
5029  SHMQueueElemInit(&(sxact->finishedLink));
5030 
5031  sxact->topXid = xid;
5032  sxact->xmin = xactRecord->xmin;
5033  sxact->flags = xactRecord->flags;
5034  Assert(SxactIsPrepared(sxact));
5035  if (!SxactIsReadOnly(sxact))
5036  {
5040  }
5041 
5042  /*
5043  * We don't know whether the transaction had any conflicts or not, so
5044  * we'll conservatively assume that it had both a conflict in and a
5045  * conflict out, and represent that with the summary conflict flags.
5046  */
5047  SHMQueueInit(&(sxact->outConflicts));
5048  SHMQueueInit(&(sxact->inConflicts));
5051 
5052  /* Register the transaction's xid */
5053  sxidtag.xid = xid;
5055  &sxidtag,
5056  HASH_ENTER, &found);
5057  Assert(sxid != NULL);
5058  Assert(!found);
5059  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5060 
5061  /*
5062  * Update global xmin. Note that this is a special case compared to
5063  * registering a normal transaction, because the global xmin might go
5064  * backwards. That's OK, because until recovery is over we're not
5065  * going to complete any transactions or create any non-prepared
5066  * transactions, so there's no danger of throwing away.
5067  */
5070  {
5071  PredXact->SxactGlobalXmin = sxact->xmin;
5073  SerialSetActiveSerXmin(sxact->xmin);
5074  }
5075  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5076  {
5079  }
5080 
5081  LWLockRelease(SerializableXactHashLock);
5082  }
5083  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5084  {
5085  /* Lock record. Recreate the PREDICATELOCK */
5086  TwoPhasePredicateLockRecord *lockRecord;
5087  SERIALIZABLEXID *sxid;
5088  SERIALIZABLEXACT *sxact;
5089  SERIALIZABLEXIDTAG sxidtag;
5090  uint32 targettaghash;
5091 
5092  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5093  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5094 
5095  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5096  sxidtag.xid = xid;
5097  sxid = (SERIALIZABLEXID *)
5098  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5099  LWLockRelease(SerializableXactHashLock);
5100 
5101  Assert(sxid != NULL);
5102  sxact = sxid->myXact;
5103  Assert(sxact != InvalidSerializableXact);
5104 
5105  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5106  }
5107 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2374
#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:691
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:919
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:65
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
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:136
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:429
uint32 LocalTransactionId
Definition: c.h:577
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:155
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:800
BackendId backendId
Definition: lock.h:64
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:902
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
union SERIALIZABLEXACT::@107 SeqNo
static void SerialSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:962
#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 2521 of file predicate.c.

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

Referenced by _bt_endpoint(), _bt_first(), _bt_readnextpage(), _hash_first(), _hash_readnext(), collectMatchBitmap(), gistScanPage(), IndexOnlyNext(), moveRightIfItNeeded(), scanPendingInsert(), and startScanEntry().

2522 {
2524 
2525  if (!SerializationNeededForRead(relation, snapshot))
2526  return;
2527 
2529  relation->rd_node.dbNode,
2530  relation->rd_id,
2531  blkno);
2532  PredicateLockAcquire(&tag);
2533 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
Oid rd_id
Definition: rel.h:112
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 3181 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

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

◆ PredicateLockPageSplit()

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

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

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

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 2498 of file predicate.c.

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

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

2499 {
2501 
2502  if (!SerializationNeededForRead(relation, snapshot))
2503  return;
2504 
2506  relation->rd_node.dbNode,
2507  relation->rd_id);
2508  PredicateLockAcquire(&tag);
2509 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
Oid rd_id
Definition: rel.h:112
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 1283 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().

1284 {
1285  Size size = 0;
1286  long max_table_size;
1287 
1288  /* predicate lock target hash table */
1289  max_table_size = NPREDICATELOCKTARGETENTS();
1290  size = add_size(size, hash_estimate_size(max_table_size,
1291  sizeof(PREDICATELOCKTARGET)));
1292 
1293  /* predicate lock hash table */
1294  max_table_size *= 2;
1295  size = add_size(size, hash_estimate_size(max_table_size,
1296  sizeof(PREDICATELOCK)));
1297 
1298  /*
1299  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1300  * margin.
1301  */
1302  size = add_size(size, size / 10);
1303 
1304  /* transaction list */
1305  max_table_size = MaxBackends + max_prepared_xacts;
1306  max_table_size *= 10;
1307  size = add_size(size, PredXactListDataSize);
1308  size = add_size(size, mul_size((Size) max_table_size,
1310 
1311  /* transaction xid table */
1312  size = add_size(size, hash_estimate_size(max_table_size,
1313  sizeof(SERIALIZABLEXID)));
1314 
1315  /* rw-conflict pool */
1316  max_table_size *= 5;
1317  size = add_size(size, RWConflictPoolHeaderDataSize);
1318  size = add_size(size, mul_size((Size) max_table_size,
1320 
1321  /* Head for list of finished serializable transactions. */
1322  size = add_size(size, sizeof(SHM_QUEUE));
1323 
1324  /* Shared memory structures for SLRU tracking of old committed xids. */
1325  size = add_size(size, sizeof(SerialControlData));
1327 
1328  return size;
1329 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:259
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:155
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:136
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:745
#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:528
#define PredXactListElementDataSize

◆ PredicateLockTID()

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

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

2545 {
2547 
2548  if (!SerializationNeededForRead(relation, snapshot))
2549  return;
2550 
2551  /*
2552  * Return if this xact wrote it.
2553  */
2554  if (relation->rd_index == NULL)
2555  {
2556  /* If we wrote it; we already have a write lock. */
2557  if (TransactionIdIsCurrentTransactionId(tuple_xid))
2558  return;
2559  }
2560 
2561  /*
2562  * Do quick-but-not-definitive test for a relation lock first. This will
2563  * never cause a return when the relation is *not* locked, but will
2564  * occasionally let the check continue when there really *is* a relation
2565  * level lock.
2566  */
2568  relation->rd_node.dbNode,
2569  relation->rd_id);
2570  if (PredicateLockExists(&tag))
2571  return;
2572 
2574  relation->rd_node.dbNode,
2575  relation->rd_id,
2578  PredicateLockAcquire(&tag);
2579 }
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1956
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
Form_pg_index rd_index
Definition: rel.h:175
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
Oid rd_id
Definition: rel.h:112
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 4952 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

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

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

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

1871 {
1872  SERIALIZABLEXIDTAG sxidtag;
1873  SERIALIZABLEXID *sxid;
1874  bool found;
1875 
1876  /*
1877  * If we're not tracking predicate lock data for this transaction, we
1878  * should ignore the request and return quickly.
1879  */
1881  return;
1882 
1883  /* We should have a valid XID and be at the top level. */
1885 
1886  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1887 
1888  /* This should only be done once per transaction. */
1890 
1891  MySerializableXact->topXid = xid;
1892 
1893  sxidtag.xid = xid;
1895  &sxidtag,
1896  HASH_ENTER, &found);
1897  Assert(!found);
1898 
1899  /* Initialize the structure. */
1900  sxid->myXact = MySerializableXact;
1901  LWLockRelease(SerializableXactHashLock);
1902 }
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:919
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)

Definition at line 3261 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::nextXid, 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().

3262 {
3263  bool needToClear;
3264  RWConflict conflict,
3265  nextConflict,
3266  possibleUnsafeConflict;
3267  SERIALIZABLEXACT *roXact;
3268 
3269  /*
3270  * We can't trust XactReadOnly here, because a transaction which started
3271  * as READ WRITE can show as READ ONLY later, e.g., within
3272  * subtransactions. We want to flag a transaction as READ ONLY if it
3273  * commits without writing so that de facto READ ONLY transactions get the
3274  * benefit of some RO optimizations, so we will use this local variable to
3275  * get some cleanup logic right which is based on whether the transaction
3276  * was declared READ ONLY at the top level.
3277  */
3278  bool topLevelIsDeclaredReadOnly;
3279 
3280  /* We can't be both committing and releasing early due to RO_SAFE. */
3281  Assert(!(isCommit && isReadOnlySafe));
3282 
3283  /* Are we at the end of a transaction, that is, a commit or abort? */
3284  if (!isReadOnlySafe)
3285  {
3286  /*
3287  * Parallel workers mustn't release predicate locks at the end of
3288  * their transaction. The leader will do that at the end of its
3289  * transaction.
3290  */
3291  if (IsParallelWorker())
3292  {
3294  return;
3295  }
3296 
3297  /*
3298  * By the time the leader in a parallel query reaches end of
3299  * transaction, it has waited for all workers to exit.
3300  */
3302 
3303  /*
3304  * If the leader in a parallel query earlier stashed a partially
3305  * released SERIALIZABLEXACT for final clean-up at end of transaction
3306  * (because workers might still have been accessing it), then it's
3307  * time to restore it.
3308  */
3310  {
3315  }
3316  }
3317 
3319  {
3320  Assert(LocalPredicateLockHash == NULL);
3321  return;
3322  }
3323 
3324  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3325 
3326  /*
3327  * If the transaction is committing, but it has been partially released
3328  * already, then treat this as a roll back. It was marked as rolled back.
3329  */
3331  isCommit = false;
3332 
3333  /*
3334  * If we're called in the middle of a transaction because we discovered
3335  * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3336  * it (that is, release the predicate locks and conflicts, but not the
3337  * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3338  */
3339  if (isReadOnlySafe && IsInParallelMode())
3340  {
3341  /*
3342  * The leader needs to stash a pointer to it, so that it can
3343  * completely release it at end-of-transaction.
3344  */
3345  if (!IsParallelWorker())
3347 
3348  /*
3349  * The first backend to reach this condition will partially release
3350  * the SERIALIZABLEXACT. All others will just clear their
3351  * backend-local state so that they stop doing SSI checks for the rest
3352  * of the transaction.
3353  */
3355  {
3356  LWLockRelease(SerializableXactHashLock);
3358  return;
3359  }
3360  else
3361  {
3363  /* ... and proceed to perform the partial release below. */
3364  }
3365  }
3366  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3367  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3371 
3372  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3374 
3375  /* We'd better not already be on the cleanup list. */
3377 
3378  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3379 
3380  /*
3381  * We don't hold XidGenLock lock here, assuming that TransactionId is
3382  * atomic!
3383  *
3384  * If this value is changing, we don't care that much whether we get the
3385  * old or new value -- it is just used to determine how far
3386  * SxactGlobalXmin must advance before this transaction can be fully
3387  * cleaned up. The worst that could happen is we wait for one more
3388  * transaction to complete before freeing some RAM; correctness of visible
3389  * behavior is not affected.
3390  */
3392 
3393  /*
3394  * If it's not a commit it's either a rollback or a read-only transaction
3395  * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3396  */
3397  if (isCommit)
3398  {
3401  /* Recognize implicit read-only transaction (commit without write). */
3402  if (!MyXactDidWrite)
3404  }
3405  else
3406  {
3407  /*
3408  * The DOOMED flag indicates that we intend to roll back this
3409  * transaction and so it should not cause serialization failures for
3410  * other transactions that conflict with it. Note that this flag might
3411  * already be set, if another backend marked this transaction for
3412  * abort.
3413  *
3414  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3415  * has been called, and so the SerializableXact is eligible for
3416  * cleanup. This means it should not be considered when calculating
3417  * SxactGlobalXmin.
3418  */
3421 
3422  /*
3423  * If the transaction was previously prepared, but is now failing due
3424  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3425  * prepare, clear the prepared flag. This simplifies conflict
3426  * checking.
3427  */
3429  }
3430 
3431  if (!topLevelIsDeclaredReadOnly)
3432  {
3434  if (--(PredXact->WritableSxactCount) == 0)
3435  {
3436  /*
3437  * Release predicate locks and rw-conflicts in for all committed
3438  * transactions. There are no longer any transactions which might
3439  * conflict with the locks and no chance for new transactions to
3440  * overlap. Similarly, existing conflicts in can't cause pivots,
3441  * and any conflicts in which could have completed a dangerous
3442  * structure would already have caused a rollback, so any
3443  * remaining ones must be benign.
3444  */
3446  }
3447  }
3448  else
3449  {
3450  /*
3451  * Read-only transactions: clear the list of transactions that might
3452  * make us unsafe. Note that we use 'inLink' for the iteration as
3453  * opposed to 'outLink' for the r/w xacts.
3454  */
3455  possibleUnsafeConflict = (RWConflict)
3458  offsetof(RWConflictData, inLink));
3459  while (possibleUnsafeConflict)
3460  {
3461  nextConflict = (RWConflict)
3463  &possibleUnsafeConflict->inLink,
3464  offsetof(RWConflictData, inLink));
3465 
3466  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3467  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3468 
3469  ReleaseRWConflict(possibleUnsafeConflict);
3470 
3471  possibleUnsafeConflict = nextConflict;
3472  }
3473  }
3474 
3475  /* Check for conflict out to old committed transactions. */
3476  if (isCommit
3479  {
3480  /*
3481  * we don't know which old committed transaction we conflicted with,
3482  * so be conservative and use FirstNormalSerCommitSeqNo here
3483  */
3487  }
3488 
3489  /*
3490  * Release all outConflicts to committed transactions. If we're rolling
3491  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3492  * previously committed transactions.
3493  */
3494  conflict = (RWConflict)
3497  offsetof(RWConflictData, outLink));
3498  while (conflict)
3499  {
3500  nextConflict = (RWConflict)
3502  &conflict->outLink,
3503  offsetof(RWConflictData, outLink));
3504 
3505  if (isCommit
3507  && SxactIsCommitted(conflict->sxactIn))
3508  {
3513  }
3514 
3515  if (!isCommit
3516  || SxactIsCommitted(conflict->sxactIn)
3518  ReleaseRWConflict(conflict);
3519 
3520  conflict = nextConflict;
3521  }
3522 
3523  /*
3524  * Release all inConflicts from committed and read-only transactions. If
3525  * we're rolling back, clear them all.
3526  */
3527  conflict = (RWConflict)
3530  offsetof(RWConflictData, inLink));
3531  while (conflict)
3532  {
3533  nextConflict = (RWConflict)
3535  &conflict->inLink,
3536  offsetof(RWConflictData, inLink));
3537 
3538  if (!isCommit
3539  || SxactIsCommitted(conflict->sxactOut)
3540  || SxactIsReadOnly(conflict->sxactOut))
3541  ReleaseRWConflict(conflict);
3542 
3543  conflict = nextConflict;
3544  }
3545 
3546  if (!topLevelIsDeclaredReadOnly)
3547  {
3548  /*
3549  * Remove ourselves from the list of possible conflicts for concurrent
3550  * READ ONLY transactions, flagging them as unsafe if we have a
3551  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3552  * up if they are known safe or known unsafe.
3553  */
3554  possibleUnsafeConflict = (RWConflict)
3557  offsetof(RWConflictData, outLink));
3558  while (possibleUnsafeConflict)
3559  {
3560  nextConflict = (RWConflict)
3562  &possibleUnsafeConflict->outLink,
3563  offsetof(RWConflictData, outLink));
3564 
3565  roXact = possibleUnsafeConflict->sxactIn;
3566  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3567  Assert(SxactIsReadOnly(roXact));
3568 
3569  /* Mark conflicted if necessary. */
3570  if (isCommit
3571  && MyXactDidWrite
3574  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3575  {
3576  /*
3577  * This releases possibleUnsafeConflict (as well as all other
3578  * possible conflicts for roXact)
3579  */
3580  FlagSxactUnsafe(roXact);
3581  }
3582  else
3583  {
3584  ReleaseRWConflict(possibleUnsafeConflict);
3585 
3586  /*
3587  * If we were the last possible conflict, flag it safe. The
3588  * transaction can now safely release its predicate locks (but
3589  * that transaction's backend has to do that itself).
3590  */
3591  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3592  roXact->flags |= SXACT_FLAG_RO_SAFE;
3593  }
3594 
3595  /*
3596  * Wake up the process for a waiting DEFERRABLE transaction if we
3597  * now know it's either safe or conflicted.
3598  */
3599  if (SxactIsDeferrableWaiting(roXact) &&
3600  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3601  ProcSendSignal(roXact->pid);
3602 
3603  possibleUnsafeConflict = nextConflict;
3604  }
3605  }
3606 
3607  /*
3608  * Check whether it's time to clean up old transactions. This can only be
3609  * done when the last serializable transaction with the oldest xmin among
3610  * serializable transactions completes. We then find the "new oldest"
3611  * xmin and purge any transactions which finished before this transaction
3612  * was launched.
3613  */
3614  needToClear = false;
3616  {
3618  if (--(PredXact->SxactGlobalXminCount) == 0)
3619  {
3621  needToClear = true;
3622  }
3623  }
3624 
3625  LWLockRelease(SerializableXactHashLock);
3626 
3627  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3628 
3629  /* Add this to the list of transactions to check for later cleanup. */
3630  if (isCommit)
3633 
3634  /*
3635  * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3636  * partially release it. That's necessary because other backends may have
3637  * a reference to it. The leader will release the SERIALIZABLEXACT itself
3638  * at the end of the transaction after workers have stopped running.
3639  */
3640  if (!isCommit)
3642  isReadOnlySafe && IsInParallelMode(),
3643  false);
3644 
3645  LWLockRelease(SerializableFinishedListLock);
3646 
3647  if (needToClear)
3649 
3651 }
#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:3654
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3672
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:742
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
FullTransactionId nextXid
Definition: transam.h:213
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:750
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1821
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
bool IsInParallelMode(void)
Definition: xact.c:1012
#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:3829
#define Assert(condition)
Definition: c.h:800
#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:1207
#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:3203
#define SxactIsCommitted(sxact)
Definition: predicate.c:272
#define offsetof(type, field)
Definition: c.h:723
SERIALIZABLEXACT * sxactOut

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1648 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

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

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5115 of file predicate.c.

References MySerializableXact.

Referenced by InitializeParallelDSM().

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

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3075 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3076 {
3077  DropAllPredicateLocksFromTable(relation, true);
3078 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2879

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