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

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

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5195 of file predicate.c.

References Assert, CreateLocalPredicateLockHash(), and InvalidSerializableXact.

Referenced by ParallelWorkerMain().

5196 {
5197 
5199 
5200  MySerializableXact = (SERIALIZABLEXACT *) handle;
5203 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:804
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1922

◆ CheckForSerializableConflictIn()

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

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

4447 {
4448  PREDICATELOCKTARGETTAG targettag;
4449 
4450  if (!SerializationNeededForWrite(relation))
4451  return;
4452 
4453  /* Check if someone else has already decided that we need to die */
4455  ereport(ERROR,
4456  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4457  errmsg("could not serialize access due to read/write dependencies among transactions"),
4458  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4459  errhint("The transaction might succeed if retried.")));
4460 
4461  /*
4462  * We're doing a write which might cause rw-conflicts now or later.
4463  * Memorize that fact.
4464  */
4465  MyXactDidWrite = true;
4466 
4467  /*
4468  * It is important that we check for locks from the finest granularity to
4469  * the coarsest granularity, so that granularity promotion doesn't cause
4470  * us to miss a lock. The new (coarser) lock will be acquired before the
4471  * old (finer) locks are released.
4472  *
4473  * It is not possible to take and hold a lock across the checks for all
4474  * granularities because each target could be in a separate partition.
4475  */
4476  if (tid != NULL)
4477  {
4479  relation->rd_node.dbNode,
4480  relation->rd_id,
4483  CheckTargetForConflictsIn(&targettag);
4484  }
4485 
4486  if (blkno != InvalidBlockNumber)
4487  {
4489  relation->rd_node.dbNode,
4490  relation->rd_id,
4491  blkno);
4492  CheckTargetForConflictsIn(&targettag);
4493  }
4494 
4496  relation->rd_node.dbNode,
4497  relation->rd_id);
4498  CheckTargetForConflictsIn(&targettag);
4499 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1156
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4264
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:698
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:1069
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:46
Oid rd_id
Definition: rel.h:111
#define ereport(elevel,...)
Definition: elog.h:157
RelFileNode rd_node
Definition: rel.h:56
#define InvalidBlockNumber
Definition: block.h:33
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
int errmsg(const char *fmt,...)
Definition: elog.c:909
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 4121 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().

4122 {
4123  SERIALIZABLEXIDTAG sxidtag;
4124  SERIALIZABLEXID *sxid;
4125  SERIALIZABLEXACT *sxact;
4126 
4127  if (!SerializationNeededForRead(relation, snapshot))
4128  return;
4129 
4130  /* Check if someone else has already decided that we need to die */
4132  {
4133  ereport(ERROR,
4134  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4135  errmsg("could not serialize access due to read/write dependencies among transactions"),
4136  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4137  errhint("The transaction might succeed if retried.")));
4138  }
4140 
4142  return;
4143 
4144  /*
4145  * Find sxact or summarized info for the top level xid.
4146  */
4147  sxidtag.xid = xid;
4148  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4149  sxid = (SERIALIZABLEXID *)
4150  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4151  if (!sxid)
4152  {
4153  /*
4154  * Transaction not found in "normal" SSI structures. Check whether it
4155  * got pushed out to SLRU storage for "old committed" transactions.
4156  */
4157  SerCommitSeqNo conflictCommitSeqNo;
4158 
4159  conflictCommitSeqNo = SerialGetMinConflictCommitSeqNo(xid);
4160  if (conflictCommitSeqNo != 0)
4161  {
4162  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4164  || conflictCommitSeqNo
4166  ereport(ERROR,
4167  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4168  errmsg("could not serialize access due to read/write dependencies among transactions"),
4169  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4170  errhint("The transaction might succeed if retried.")));
4171 
4174  ereport(ERROR,
4175  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4176  errmsg("could not serialize access due to read/write dependencies among transactions"),
4177  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4178  errhint("The transaction might succeed if retried.")));
4179 
4181  }
4182 
4183  /* It's not serializable or otherwise not important. */
4184  LWLockRelease(SerializableXactHashLock);
4185  return;
4186  }
4187  sxact = sxid->myXact;
4188  Assert(TransactionIdEquals(sxact->topXid, xid));
4189  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4190  {
4191  /* Can't conflict with ourself or a transaction that will roll back. */
4192  LWLockRelease(SerializableXactHashLock);
4193  return;
4194  }
4195 
4196  /*
4197  * We have a conflict out to a transaction which has a conflict out to a
4198  * summarized transaction. That summarized transaction must have
4199  * committed first, and we can't tell when it committed in relation to our
4200  * snapshot acquisition, so something needs to be canceled.
4201  */
4202  if (SxactHasSummaryConflictOut(sxact))
4203  {
4204  if (!SxactIsPrepared(sxact))
4205  {
4206  sxact->flags |= SXACT_FLAG_DOOMED;
4207  LWLockRelease(SerializableXactHashLock);
4208  return;
4209  }
4210  else
4211  {
4212  LWLockRelease(SerializableXactHashLock);
4213  ereport(ERROR,
4214  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4215  errmsg("could not serialize access due to read/write dependencies among transactions"),
4216  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4217  errhint("The transaction might succeed if retried.")));
4218  }
4219  }
4220 
4221  /*
4222  * If this is a read-only transaction and the writing transaction has
4223  * committed, and it doesn't have a rw-conflict to a transaction which
4224  * committed before it, no conflict.
4225  */
4227  && SxactIsCommitted(sxact)
4228  && !SxactHasSummaryConflictOut(sxact)
4229  && (!SxactHasConflictOut(sxact)
4231  {
4232  /* Read-only transaction will appear to run first. No conflict. */
4233  LWLockRelease(SerializableXactHashLock);
4234  return;
4235  }
4236 
4237  if (!XidIsConcurrent(xid))
4238  {
4239  /* This write was already in our snapshot; no conflict. */
4240  LWLockRelease(SerializableXactHashLock);
4241  return;
4242  }
4243 
4245  {
4246  /* We don't want duplicate conflict records in the list. */
4247  LWLockRelease(SerializableXactHashLock);
4248  return;
4249  }
4250 
4251  /*
4252  * Flag the conflict. But first, if this conflict creates a dangerous
4253  * structure, ereport an error.
4254  */
4256  LWLockRelease(SerializableXactHashLock);
4257 }
#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:1156
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4621
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:277
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:4063
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
int errcode(int sqlerrcode)
Definition: elog.c:698
static HTAB * SerializableXidHash
Definition: predicate.c:391
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:977
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:46
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:426
#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:157
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:284
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514
int errmsg(const char *fmt,...)
Definition: elog.c:909
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 4089 of file predicate.c.

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

Referenced by HeapCheckForSerializableConflictOut().

4090 {
4091  if (!SerializationNeededForRead(relation, snapshot))
4092  return false;
4093 
4094  /* Check if someone else has already decided that we need to die */
4096  {
4097  ereport(ERROR,
4098  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4099  errmsg("could not serialize access due to read/write dependencies among transactions"),
4100  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4101  errhint("The transaction might succeed if retried.")));
4102  }
4103 
4104  return true;
4105 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1156
int errcode(int sqlerrcode)
Definition: elog.c:698
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1069 of file predicate.c.

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

Referenced by CheckPointGuts().

1070 {
1071  int tailPage;
1072 
1073  LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE);
1074 
1075  /* Exit quickly if the SLRU is currently not in use. */
1076  if (serialControl->headPage < 0)
1077  {
1078  LWLockRelease(SerialSLRULock);
1079  return;
1080  }
1081 
1083  {
1084  /* We can truncate the SLRU up to the page containing tailXid */
1085  tailPage = SerialPage(serialControl->tailXid);
1086  }
1087  else
1088  {
1089  /*----------
1090  * The SLRU is no longer needed. Truncate to head before we set head
1091  * invalid.
1092  *
1093  * XXX: It's possible that the SLRU is not needed again until XID
1094  * wrap-around has happened, so that the segment containing headPage
1095  * that we leave behind will appear to be new again. In that case it
1096  * won't be removed until XID horizon advances enough to make it
1097  * current again.
1098  *
1099  * XXX: This should happen in vac_truncate_clog(), not in checkpoints.
1100  * Consider this scenario, starting from a system with no in-progress
1101  * transactions and VACUUM FREEZE having maximized oldestXact:
1102  * - Start a SERIALIZABLE transaction.
1103  * - Start, finish, and summarize a SERIALIZABLE transaction, creating
1104  * one SLRU page.
1105  * - Consume XIDs to reach xidStopLimit.
1106  * - Finish all transactions. Due to the long-running SERIALIZABLE
1107  * transaction, earlier checkpoints did not touch headPage. The
1108  * next checkpoint will change it, but that checkpoint happens after
1109  * the end of the scenario.
1110  * - VACUUM to advance XID limits.
1111  * - Consume ~2M XIDs, crossing the former xidWrapLimit.
1112  * - Start, finish, and summarize a SERIALIZABLE transaction.
1113  * SerialAdd() declines to create the targetPage, because headPage
1114  * is not regarded as in the past relative to that targetPage. The
1115  * transaction instigating the summarize fails in
1116  * SimpleLruReadPage().
1117  */
1118  tailPage = serialControl->headPage;
1119  serialControl->headPage = -1;
1120  }
1121 
1122  LWLockRelease(SerialSLRULock);
1123 
1124  /* Truncate away pages that are no longer required */
1125  SimpleLruTruncate(SerialSlruCtl, tailPage);
1126 
1127  /*
1128  * Write dirty SLRU pages to disk
1129  *
1130  * This is not actually necessary from a correctness point of view. We do
1131  * it merely as a debugging aid.
1132  *
1133  * We're doing this after the truncation to avoid writing pages right
1134  * before deleting the file in which they sit, which would be completely
1135  * pointless.
1136  */
1138 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1226
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define SerialSlruCtl
Definition: predicate.c:321
#define SerialPage(xid)
Definition: predicate.c:338
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1156
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
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 4529 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().

4530 {
4531  HASH_SEQ_STATUS seqstat;
4532  PREDICATELOCKTARGET *target;
4533  Oid dbId;
4534  Oid heapId;
4535  int i;
4536 
4537  /*
4538  * Bail out quickly if there are no serializable transactions running.
4539  * It's safe to check this without taking locks because the caller is
4540  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4541  * would matter here can be acquired while that is held.
4542  */
4544  return;
4545 
4546  if (!SerializationNeededForWrite(relation))
4547  return;
4548 
4549  /*
4550  * We're doing a write which might cause rw-conflicts now or later.
4551  * Memorize that fact.
4552  */
4553  MyXactDidWrite = true;
4554 
4555  Assert(relation->rd_index == NULL); /* not an index relation */
4556 
4557  dbId = relation->rd_node.dbNode;
4558  heapId = relation->rd_id;
4559 
4560  LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
4561  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4563  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4564 
4565  /* Scan through target list */
4567 
4568  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4569  {
4570  PREDICATELOCK *predlock;
4571 
4572  /*
4573  * Check whether this is a target which needs attention.
4574  */
4575  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4576  continue; /* wrong relation id */
4577  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4578  continue; /* wrong database id */
4579 
4580  /*
4581  * Loop through locks for this target and flag conflicts.
4582  */
4583  predlock = (PREDICATELOCK *)
4584  SHMQueueNext(&(target->predicateLocks),
4585  &(target->predicateLocks),
4586  offsetof(PREDICATELOCK, targetLink));
4587  while (predlock)
4588  {
4589  PREDICATELOCK *nextpredlock;
4590 
4591  nextpredlock = (PREDICATELOCK *)
4592  SHMQueueNext(&(target->predicateLocks),
4593  &(predlock->targetLink),
4594  offsetof(PREDICATELOCK, targetLink));
4595 
4596  if (predlock->tag.myXact != MySerializableXact
4598  {
4600  }
4601 
4602  predlock = nextpredlock;
4603  }
4604  }
4605 
4606  /* Release locks in reverse order */
4607  LWLockRelease(SerializableXactHashLock);
4608  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4610  LWLockRelease(SerializablePredicateListLock);
4611 }
#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:4621
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:1803
Form_pg_index rd_index
Definition: rel.h:187
#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:56
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#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:727
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:91

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1680 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

1681 {
1683 
1684  /*
1685  * Can't use serializable mode while recovery is still active, as it is,
1686  * for example, on a hot standby. We could get here despite the check in
1687  * check_XactIsoLevel() if default_transaction_isolation is set to
1688  * serializable, so phrase the hint accordingly.
1689  */
1690  if (RecoveryInProgress())
1691  ereport(ERROR,
1692  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1693  errmsg("cannot use serializable mode in a hot standby"),
1694  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1695  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1696 
1697  /*
1698  * A special optimization is available for SERIALIZABLE READ ONLY
1699  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1700  * thereby avoid all SSI overhead once it's running.
1701  */
1703  return GetSafeSnapshot(snapshot);
1704 
1705  return GetSerializableTransactionSnapshotInt(snapshot,
1706  NULL, InvalidPid);
1707 }
bool XactDeferrable
Definition: xact.c:82
int errhint(const char *fmt,...)
Definition: elog.c:1156
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1558
int errcode(int sqlerrcode)
Definition: elog.c:698
bool RecoveryInProgress(void)
Definition: xlog.c:8328
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1762
#define ERROR
Definition: elog.h:46
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define ereport(elevel,...)
Definition: elog.h:157
bool XactReadOnly
Definition: xact.c:79
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define IsolationIsSerializable()
Definition: xact.h:52
#define InvalidPid
Definition: miscadmin.h:32

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

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

1154 {
1155  HASHCTL info;
1156  long max_table_size;
1157  Size requestSize;
1158  bool found;
1159 
1160 #ifndef EXEC_BACKEND
1162 #endif
1163 
1164  /*
1165  * Compute size of predicate lock target hashtable. Note these
1166  * calculations must agree with PredicateLockShmemSize!
1167  */
1168  max_table_size = NPREDICATELOCKTARGETENTS();
1169 
1170  /*
1171  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1172  * per-predicate-lock-target information.
1173  */
1174  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1175  info.entrysize = sizeof(PREDICATELOCKTARGET);
1177 
1178  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1179  max_table_size,
1180  max_table_size,
1181  &info,
1182  HASH_ELEM | HASH_BLOBS |
1184 
1185  /*
1186  * Reserve a dummy entry in the hash table; we use it to make sure there's
1187  * always one entry available when we need to split or combine a page,
1188  * because running out of space there could mean aborting a
1189  * non-serializable transaction.
1190  */
1191  if (!IsUnderPostmaster)
1192  {
1194  HASH_ENTER, &found);
1195  Assert(!found);
1196  }
1197 
1198  /* Pre-calculate the hash and partition lock of the scratch entry */
1201 
1202  /*
1203  * Allocate hash table for PREDICATELOCK structs. This stores per
1204  * xact-lock-of-a-target information.
1205  */
1206  info.keysize = sizeof(PREDICATELOCKTAG);
1207  info.entrysize = sizeof(PREDICATELOCK);
1208  info.hash = predicatelock_hash;
1210 
1211  /* Assume an average of 2 xacts per target */
1212  max_table_size *= 2;
1213 
1214  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1215  max_table_size,
1216  max_table_size,
1217  &info,
1220 
1221  /*
1222  * Compute size for serializable transaction hashtable. Note these
1223  * calculations must agree with PredicateLockShmemSize!
1224  */
1225  max_table_size = (MaxBackends + max_prepared_xacts);
1226 
1227  /*
1228  * Allocate a list to hold information on transactions participating in
1229  * predicate locking.
1230  *
1231  * Assume an average of 10 predicate locking transactions per backend.
1232  * This allows aggressive cleanup while detail is present before data must
1233  * be summarized for storage in SLRU and the "dummy" transaction.
1234  */
1235  max_table_size *= 10;
1236 
1237  PredXact = ShmemInitStruct("PredXactList",
1239  &found);
1240  Assert(found == IsUnderPostmaster);
1241  if (!found)
1242  {
1243  int i;
1244 
1253  requestSize = mul_size((Size) max_table_size,
1255  PredXact->element = ShmemAlloc(requestSize);
1256  /* Add all elements to available list, clean. */
1257  memset(PredXact->element, 0, requestSize);
1258  for (i = 0; i < max_table_size; i++)
1259  {
1263  &(PredXact->element[i].link));
1264  }
1280  }
1281  /* This never changes, so let's keep a local copy. */
1283 
1284  /*
1285  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1286  * information for serializable transactions which have accessed data.
1287  */
1288  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1289  info.entrysize = sizeof(SERIALIZABLEXID);
1290 
1291  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1292  max_table_size,
1293  max_table_size,
1294  &info,
1295  HASH_ELEM | HASH_BLOBS |
1296  HASH_FIXED_SIZE);
1297 
1298  /*
1299  * Allocate space for tracking rw-conflicts in lists attached to the
1300  * transactions.
1301  *
1302  * Assume an average of 5 conflicts per transaction. Calculations suggest
1303  * that this will prevent resource exhaustion in even the most pessimal
1304  * loads up to max_connections = 200 with all 200 connections pounding the
1305  * database with serializable transactions. Beyond that, there may be
1306  * occasional transactions canceled when trying to flag conflicts. That's
1307  * probably OK.
1308  */
1309  max_table_size *= 5;
1310 
1311  RWConflictPool = ShmemInitStruct("RWConflictPool",
1313  &found);
1314  Assert(found == IsUnderPostmaster);
1315  if (!found)
1316  {
1317  int i;
1318 
1320  requestSize = mul_size((Size) max_table_size,
1322  RWConflictPool->element = ShmemAlloc(requestSize);
1323  /* Add all elements to available list, clean. */
1324  memset(RWConflictPool->element, 0, requestSize);
1325  for (i = 0; i < max_table_size; i++)
1326  {
1328  &(RWConflictPool->element[i].outLink));
1329  }
1330  }
1331 
1332  /*
1333  * Create or attach to the header for the list of finished serializable
1334  * transactions.
1335  */
1337  ShmemInitStruct("FinishedSerializableTransactions",
1338  sizeof(SHM_QUEUE),
1339  &found);
1340  Assert(found == IsUnderPostmaster);
1341  if (!found)
1343 
1344  /*
1345  * Initialize the SLRU storage for old committed serializable
1346  * transactions.
1347  */
1348  SerialInit();
1349 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:392
#define HASH_ELEM
Definition: hsearch.h:95
static void SerialInit(void)
Definition: predicate.c:866
#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:76
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1417
static HTAB * SerializableXidHash
Definition: predicate.c:391
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:954
#define HASH_PARTITION
Definition: hsearch.h:92
#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:68
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
struct PREDICATELOCKTAG PREDICATELOCKTAG
int MaxBackends
Definition: globals.c:139
#define RWConflictDataSize
VirtualTransactionId vxid
bool IsUnderPostmaster
Definition: globals.c:112
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:736
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:97
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
Size keysize
Definition: hsearch.h:75
#define Assert(condition)
Definition: c.h:804
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:79
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:540
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:105
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:341
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:78
#define HASH_FUNCTION
Definition: hsearch.h:98
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:91

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

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

1991 {
1992  PREDICATELOCKTARGETTAG targettag;
1993  uint32 targettaghash;
1994  LWLock *partitionLock;
1995  PREDICATELOCKTARGET *target;
1996 
1998  relation->rd_node.dbNode,
1999  relation->rd_id,
2000  blkno);
2001 
2002  targettaghash = PredicateLockTargetTagHashCode(&targettag);
2003  partitionLock = PredicateLockHashPartitionLock(targettaghash);
2004  LWLockAcquire(partitionLock, LW_SHARED);
2005  target = (PREDICATELOCKTARGET *)
2007  &targettag, targettaghash,
2008  HASH_FIND, NULL);
2009  LWLockRelease(partitionLock);
2010 
2011  return (target != NULL);
2012 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:967
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:1803
unsigned int uint32
Definition: c.h:441
Oid rd_id
Definition: rel.h:111
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:298
RelFileNode rd_node
Definition: rel.h:56
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 5001 of file predicate.c.

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

Referenced by PrepareTransaction().

5002 {
5004  return;
5005 
5007 
5008  MySerializableXact->pid = 0;
5009 
5011  LocalPredicateLockHash = NULL;
5012 
5014  MyXactDidWrite = false;
5015 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:862
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:804
static HTAB * LocalPredicateLockHash
Definition: predicate.c:409
static bool MyXactDidWrite
Definition: predicate.c:417

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

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

4832 {
4833  RWConflict nearConflict;
4834 
4836  return;
4837 
4839 
4840  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4841 
4842  /* Check if someone else has already decided that we need to die */
4844  {
4846  LWLockRelease(SerializableXactHashLock);
4847  ereport(ERROR,
4848  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4849  errmsg("could not serialize access due to read/write dependencies among transactions"),
4850  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4851  errhint("The transaction might succeed if retried.")));
4852  }
4853 
4854  nearConflict = (RWConflict)
4857  offsetof(RWConflictData, inLink));
4858  while (nearConflict)
4859  {
4860  if (!SxactIsCommitted(nearConflict->sxactOut)
4861  && !SxactIsDoomed(nearConflict->sxactOut))
4862  {
4863  RWConflict farConflict;
4864 
4865  farConflict = (RWConflict)
4866  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4867  &nearConflict->sxactOut->inConflicts,
4868  offsetof(RWConflictData, inLink));
4869  while (farConflict)
4870  {
4871  if (farConflict->sxactOut == MySerializableXact
4872  || (!SxactIsCommitted(farConflict->sxactOut)
4873  && !SxactIsReadOnly(farConflict->sxactOut)
4874  && !SxactIsDoomed(farConflict->sxactOut)))
4875  {
4876  /*
4877  * Normally, we kill the pivot transaction to make sure we
4878  * make progress if the failing transaction is retried.
4879  * However, we can't kill it if it's already prepared, so
4880  * in that case we commit suicide instead.
4881  */
4882  if (SxactIsPrepared(nearConflict->sxactOut))
4883  {
4884  LWLockRelease(SerializableXactHashLock);
4885  ereport(ERROR,
4886  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4887  errmsg("could not serialize access due to read/write dependencies among transactions"),
4888  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4889  errhint("The transaction might succeed if retried.")));
4890  }
4891  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4892  break;
4893  }
4894  farConflict = (RWConflict)
4895  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4896  &farConflict->inLink,
4897  offsetof(RWConflictData, inLink));
4898  }
4899  }
4900 
4901  nearConflict = (RWConflict)
4903  &nearConflict->inLink,
4904  offsetof(RWConflictData, inLink));
4905  }
4906 
4909 
4910  LWLockRelease(SerializableXactHashLock);
4911 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416
int errhint(const char *fmt,...)
Definition: elog.c:1156
static PredXactList PredXact
Definition: predicate.c:379
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:698
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
#define ERROR
Definition: elog.h:46
#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:157
#define SXACT_FLAG_DOOMED
#define Assert(condition)
Definition: c.h:804
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define SxactIsPartiallyReleased(sxact)
Definition: predicate.c:288
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define IsolationIsSerializable()
Definition: xact.h:52
#define SxactIsCommitted(sxact)
Definition: predicate.c:272
#define offsetof(type, field)
Definition: c.h:727
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

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

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

5052 {
5053  TwoPhasePredicateRecord *record;
5054 
5055  Assert(len == sizeof(TwoPhasePredicateRecord));
5056 
5057  record = (TwoPhasePredicateRecord *) recdata;
5058 
5059  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
5060  (record->type == TWOPHASEPREDICATERECORD_LOCK));
5061 
5062  if (record->type == TWOPHASEPREDICATERECORD_XACT)
5063  {
5064  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
5065  TwoPhasePredicateXactRecord *xactRecord;
5066  SERIALIZABLEXACT *sxact;
5067  SERIALIZABLEXID *sxid;
5068  SERIALIZABLEXIDTAG sxidtag;
5069  bool found;
5070 
5071  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
5072 
5073  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
5074  sxact = CreatePredXact();
5075  if (!sxact)
5076  ereport(ERROR,
5077  (errcode(ERRCODE_OUT_OF_MEMORY),
5078  errmsg("out of shared memory")));
5079 
5080  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
5081  sxact->vxid.backendId = InvalidBackendId;
5083  sxact->pid = 0;
5084 
5085  /* a prepared xact hasn't committed yet */
5089 
5091 
5092  /*
5093  * Don't need to track this; no transactions running at the time the
5094  * recovered xact started are still active, except possibly other
5095  * prepared xacts and we don't care whether those are RO_SAFE or not.
5096  */
5098 
5099  SHMQueueInit(&(sxact->predicateLocks));
5100  SHMQueueElemInit(&(sxact->finishedLink));
5101 
5102  sxact->topXid = xid;
5103  sxact->xmin = xactRecord->xmin;
5104  sxact->flags = xactRecord->flags;
5105  Assert(SxactIsPrepared(sxact));
5106  if (!SxactIsReadOnly(sxact))
5107  {
5111  }
5112 
5113  /*
5114  * We don't know whether the transaction had any conflicts or not, so
5115  * we'll conservatively assume that it had both a conflict in and a
5116  * conflict out, and represent that with the summary conflict flags.
5117  */
5118  SHMQueueInit(&(sxact->outConflicts));
5119  SHMQueueInit(&(sxact->inConflicts));
5122 
5123  /* Register the transaction's xid */
5124  sxidtag.xid = xid;
5126  &sxidtag,
5127  HASH_ENTER, &found);
5128  Assert(sxid != NULL);
5129  Assert(!found);
5130  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5131 
5132  /*
5133  * Update global xmin. Note that this is a special case compared to
5134  * registering a normal transaction, because the global xmin might go
5135  * backwards. That's OK, because until recovery is over we're not
5136  * going to complete any transactions or create any non-prepared
5137  * transactions, so there's no danger of throwing away.
5138  */
5141  {
5142  PredXact->SxactGlobalXmin = sxact->xmin;
5144  SerialSetActiveSerXmin(sxact->xmin);
5145  }
5146  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5147  {
5150  }
5151 
5152  LWLockRelease(SerializableXactHashLock);
5153  }
5154  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5155  {
5156  /* Lock record. Recreate the PREDICATELOCK */
5157  TwoPhasePredicateLockRecord *lockRecord;
5158  SERIALIZABLEXID *sxid;
5159  SERIALIZABLEXACT *sxact;
5160  SERIALIZABLEXIDTAG sxidtag;
5161  uint32 targettaghash;
5162 
5163  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5164  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5165 
5166  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5167  sxidtag.xid = xid;
5168  sxid = (SERIALIZABLEXID *)
5169  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5170  LWLockRelease(SerializableXactHashLock);
5171 
5172  Assert(sxid != NULL);
5173  sxact = sxid->myXact;
5174  Assert(sxact != InvalidSerializableXact);
5175 
5176  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5177  }
5178 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:276
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2445
#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:698
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:954
#define SxactIsPrepared(sxact)
Definition: predicate.c:273
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:67
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:46
int max_prepared_xacts
Definition: twophase.c:117
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:139
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:441
uint32 LocalTransactionId
Definition: c.h:589
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:157
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:804
BackendId backendId
Definition: lock.h:66
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:909
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
union SERIALIZABLEXACT::@107 SeqNo
static void SerialSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:1018
#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 2592 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().

2593 {
2595 
2596  if (!SerializationNeededForRead(relation, snapshot))
2597  return;
2598 
2600  relation->rd_node.dbNode,
2601  relation->rd_id,
2602  blkno);
2603  PredicateLockAcquire(&tag);
2604 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2510
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:56
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514

◆ PredicateLockPageCombine()

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

Definition at line 3252 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

3254 {
3255  /*
3256  * Page combines differ from page splits in that we ought to be able to
3257  * remove the locks on the old page after transferring them to the new
3258  * page, instead of duplicating them. However, because we can't edit other
3259  * backends' local lock tables, removing the old lock would leave them
3260  * with an entry in their LocalPredicateLockHash for a lock they're not
3261  * holding, which isn't acceptable. So we wind up having to do the same
3262  * work as a page split, acquiring a lock on the new page and keeping the
3263  * old page locked too. That can lead to some false positives, but should
3264  * be rare in practice.
3265  */
3266  PredicateLockPageSplit(relation, oldblkno, newblkno);
3267 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3167

◆ PredicateLockPageSplit()

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

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

3169 {
3170  PREDICATELOCKTARGETTAG oldtargettag;
3171  PREDICATELOCKTARGETTAG newtargettag;
3172  bool success;
3173 
3174  /*
3175  * Bail out quickly if there are no serializable transactions running.
3176  *
3177  * It's safe to do this check without taking any additional locks. Even if
3178  * a serializable transaction starts concurrently, we know it can't take
3179  * any SIREAD locks on the page being split because the caller is holding
3180  * the associated buffer page lock. Memory reordering isn't an issue; the
3181  * memory barrier in the LWLock acquisition guarantees that this read
3182  * occurs while the buffer page lock is held.
3183  */
3185  return;
3186 
3187  if (!PredicateLockingNeededForRelation(relation))
3188  return;
3189 
3190  Assert(oldblkno != newblkno);
3191  Assert(BlockNumberIsValid(oldblkno));
3192  Assert(BlockNumberIsValid(newblkno));
3193 
3194  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3195  relation->rd_node.dbNode,
3196  relation->rd_id,
3197  oldblkno);
3198  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3199  relation->rd_node.dbNode,
3200  relation->rd_id,
3201  newblkno);
3202 
3203  LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
3204 
3205  /*
3206  * Try copying the locks over to the new page's tag, creating it if
3207  * necessary.
3208  */
3209  success = TransferPredicateLocksToNewTarget(oldtargettag,
3210  newtargettag,
3211  false);
3212 
3213  if (!success)
3214  {
3215  /*
3216  * No more predicate lock entries are available. Failure isn't an
3217  * option here, so promote the page lock to a relation lock.
3218  */
3219 
3220  /* Get the parent relation lock's lock tag */
3221  success = GetParentPredicateLockTag(&oldtargettag,
3222  &newtargettag);
3223  Assert(success);
3224 
3225  /*
3226  * Move the locks to the parent. This shouldn't fail.
3227  *
3228  * Note that here we are removing locks held by other backends,
3229  * leading to a possible inconsistency in their local lock hash table.
3230  * This is OK because we're replacing it with a lock that covers the
3231  * old one.
3232  */
3233  success = TransferPredicateLocksToNewTarget(oldtargettag,
3234  newtargettag,
3235  true);
3236  Assert(success);
3237  }
3238 
3239  LWLockRelease(SerializablePredicateListLock);
3240 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:495
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2733
static PredXactList PredXact
Definition: predicate.c:379
TransactionId SxactGlobalXmin
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
Oid rd_id
Definition: rel.h:111
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:2054
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:56
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static bool success
Definition: initdb.c:165

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

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

2570 {
2572 
2573  if (!SerializationNeededForRead(relation, snapshot))
2574  return;
2575 
2577  relation->rd_node.dbNode,
2578  relation->rd_id);
2579  PredicateLockAcquire(&tag);
2580 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2510
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:56
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:514

◆ PredicateLockShmemSize()

Size PredicateLockShmemSize ( void  )

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

1356 {
1357  Size size = 0;
1358  long max_table_size;
1359 
1360  /* predicate lock target hash table */
1361  max_table_size = NPREDICATELOCKTARGETENTS();
1362  size = add_size(size, hash_estimate_size(max_table_size,
1363  sizeof(PREDICATELOCKTARGET)));
1364 
1365  /* predicate lock hash table */
1366  max_table_size *= 2;
1367  size = add_size(size, hash_estimate_size(max_table_size,
1368  sizeof(PREDICATELOCK)));
1369 
1370  /*
1371  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1372  * margin.
1373  */
1374  size = add_size(size, size / 10);
1375 
1376  /* transaction list */
1377  max_table_size = MaxBackends + max_prepared_xacts;
1378  max_table_size *= 10;
1379  size = add_size(size, PredXactListDataSize);
1380  size = add_size(size, mul_size((Size) max_table_size,
1382 
1383  /* transaction xid table */
1384  size = add_size(size, hash_estimate_size(max_table_size,
1385  sizeof(SERIALIZABLEXID)));
1386 
1387  /* rw-conflict pool */
1388  max_table_size *= 5;
1389  size = add_size(size, RWConflictPoolHeaderDataSize);
1390  size = add_size(size, mul_size((Size) max_table_size,
1392 
1393  /* Head for list of finished serializable transactions. */
1394  size = add_size(size, sizeof(SHM_QUEUE));
1395 
1396  /* Shared memory structures for SLRU tracking of old committed xids. */
1397  size = add_size(size, sizeof(SerialControlData));
1399 
1400  return size;
1401 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:259
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:156
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:139
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:780
#define RWConflictPoolHeaderDataSize
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define NUM_SERIAL_BUFFERS
Definition: predicate.h:31
size_t Size
Definition: c.h:540
#define PredXactListElementDataSize

◆ PredicateLockTID()

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

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

2616 {
2618 
2619  if (!SerializationNeededForRead(relation, snapshot))
2620  return;
2621 
2622  /*
2623  * Return if this xact wrote it.
2624  */
2625  if (relation->rd_index == NULL)
2626  {
2627  /* If we wrote it; we already have a write lock. */
2628  if (TransactionIdIsCurrentTransactionId(tuple_xid))
2629  return;
2630  }
2631 
2632  /*
2633  * Do quick-but-not-definitive test for a relation lock first. This will
2634  * never cause a return when the relation is *not* locked, but will
2635  * occasionally let the check continue when there really *is* a relation
2636  * level lock.
2637  */
2639  relation->rd_node.dbNode,
2640  relation->rd_id);
2641  if (PredicateLockExists(&tag))
2642  return;
2643 
2645  relation->rd_node.dbNode,
2646  relation->rd_id,
2649  PredicateLockAcquire(&tag);
2650 }
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:870
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2027
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
Form_pg_index rd_index
Definition: rel.h:187
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2510
Oid rd_id
Definition: rel.h:111
RelFileNode rd_node
Definition: rel.h:56
#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 5023 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

5024 {
5025  SERIALIZABLEXID *sxid;
5026  SERIALIZABLEXIDTAG sxidtag;
5027 
5028  sxidtag.xid = xid;
5029 
5030  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5031  sxid = (SERIALIZABLEXID *)
5032  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5033  LWLockRelease(SerializableXactHashLock);
5034 
5035  /* xid will not be found if it wasn't a serializable transaction */
5036  if (sxid == NULL)
5037  return;
5038 
5039  /* Release its locks */
5040  MySerializableXact = sxid->myXact;
5041  MyXactDidWrite = true; /* conservatively assume that we wrote
5042  * something */
5043  ReleasePredicateLocks(isCommit, false);
5044 }
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:3332
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static bool MyXactDidWrite
Definition: predicate.c:417

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

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

1942 {
1943  SERIALIZABLEXIDTAG sxidtag;
1944  SERIALIZABLEXID *sxid;
1945  bool found;
1946 
1947  /*
1948  * If we're not tracking predicate lock data for this transaction, we
1949  * should ignore the request and return quickly.
1950  */
1952  return;
1953 
1954  /* We should have a valid XID and be at the top level. */
1956 
1957  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1958 
1959  /* This should only be done once per transaction. */
1961 
1962  MySerializableXact->topXid = xid;
1963 
1964  sxidtag.xid = xid;
1966  &sxidtag,
1967  HASH_ENTER, &found);
1968  Assert(!found);
1969 
1970  /* Initialize the structure. */
1971  sxid->myXact = MySerializableXact;
1972  LWLockRelease(SerializableXactHashLock);
1973 }
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:954
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)

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

3333 {
3334  bool needToClear;
3335  RWConflict conflict,
3336  nextConflict,
3337  possibleUnsafeConflict;
3338  SERIALIZABLEXACT *roXact;
3339 
3340  /*
3341  * We can't trust XactReadOnly here, because a transaction which started
3342  * as READ WRITE can show as READ ONLY later, e.g., within
3343  * subtransactions. We want to flag a transaction as READ ONLY if it
3344  * commits without writing so that de facto READ ONLY transactions get the
3345  * benefit of some RO optimizations, so we will use this local variable to
3346  * get some cleanup logic right which is based on whether the transaction
3347  * was declared READ ONLY at the top level.
3348  */
3349  bool topLevelIsDeclaredReadOnly;
3350 
3351  /* We can't be both committing and releasing early due to RO_SAFE. */
3352  Assert(!(isCommit && isReadOnlySafe));
3353 
3354  /* Are we at the end of a transaction, that is, a commit or abort? */
3355  if (!isReadOnlySafe)
3356  {
3357  /*
3358  * Parallel workers mustn't release predicate locks at the end of
3359  * their transaction. The leader will do that at the end of its
3360  * transaction.
3361  */
3362  if (IsParallelWorker())
3363  {
3365  return;
3366  }
3367 
3368  /*
3369  * By the time the leader in a parallel query reaches end of
3370  * transaction, it has waited for all workers to exit.
3371  */
3373 
3374  /*
3375  * If the leader in a parallel query earlier stashed a partially
3376  * released SERIALIZABLEXACT for final clean-up at end of transaction
3377  * (because workers might still have been accessing it), then it's
3378  * time to restore it.
3379  */
3381  {
3386  }
3387  }
3388 
3390  {
3391  Assert(LocalPredicateLockHash == NULL);
3392  return;
3393  }
3394 
3395  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3396 
3397  /*
3398  * If the transaction is committing, but it has been partially released
3399  * already, then treat this as a roll back. It was marked as rolled back.
3400  */
3402  isCommit = false;
3403 
3404  /*
3405  * If we're called in the middle of a transaction because we discovered
3406  * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3407  * it (that is, release the predicate locks and conflicts, but not the
3408  * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3409  */
3410  if (isReadOnlySafe && IsInParallelMode())
3411  {
3412  /*
3413  * The leader needs to stash a pointer to it, so that it can
3414  * completely release it at end-of-transaction.
3415  */
3416  if (!IsParallelWorker())
3418 
3419  /*
3420  * The first backend to reach this condition will partially release
3421  * the SERIALIZABLEXACT. All others will just clear their
3422  * backend-local state so that they stop doing SSI checks for the rest
3423  * of the transaction.
3424  */
3426  {
3427  LWLockRelease(SerializableXactHashLock);
3429  return;
3430  }
3431  else
3432  {
3434  /* ... and proceed to perform the partial release below. */
3435  }
3436  }
3437  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3438  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3442 
3443  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3445 
3446  /* We'd better not already be on the cleanup list. */
3448 
3449  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3450 
3451  /*
3452  * We don't hold XidGenLock lock here, assuming that TransactionId is
3453  * atomic!
3454  *
3455  * If this value is changing, we don't care that much whether we get the
3456  * old or new value -- it is just used to determine how far
3457  * SxactGlobalXmin must advance before this transaction can be fully
3458  * cleaned up. The worst that could happen is we wait for one more
3459  * transaction to complete before freeing some RAM; correctness of visible
3460  * behavior is not affected.
3461  */
3463 
3464  /*
3465  * If it's not a commit it's either a rollback or a read-only transaction
3466  * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3467  */
3468  if (isCommit)
3469  {
3472  /* Recognize implicit read-only transaction (commit without write). */
3473  if (!MyXactDidWrite)
3475  }
3476  else
3477  {
3478  /*
3479  * The DOOMED flag indicates that we intend to roll back this
3480  * transaction and so it should not cause serialization failures for
3481  * other transactions that conflict with it. Note that this flag might
3482  * already be set, if another backend marked this transaction for
3483  * abort.
3484  *
3485  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3486  * has been called, and so the SerializableXact is eligible for
3487  * cleanup. This means it should not be considered when calculating
3488  * SxactGlobalXmin.
3489  */
3492 
3493  /*
3494  * If the transaction was previously prepared, but is now failing due
3495  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3496  * prepare, clear the prepared flag. This simplifies conflict
3497  * checking.
3498  */
3500  }
3501 
3502  if (!topLevelIsDeclaredReadOnly)
3503  {
3505  if (--(PredXact->WritableSxactCount) == 0)
3506  {
3507  /*
3508  * Release predicate locks and rw-conflicts in for all committed
3509  * transactions. There are no longer any transactions which might
3510  * conflict with the locks and no chance for new transactions to
3511  * overlap. Similarly, existing conflicts in can't cause pivots,
3512  * and any conflicts in which could have completed a dangerous
3513  * structure would already have caused a rollback, so any
3514  * remaining ones must be benign.
3515  */
3517  }
3518  }
3519  else
3520  {
3521  /*
3522  * Read-only transactions: clear the list of transactions that might
3523  * make us unsafe. Note that we use 'inLink' for the iteration as
3524  * opposed to 'outLink' for the r/w xacts.
3525  */
3526  possibleUnsafeConflict = (RWConflict)
3529  offsetof(RWConflictData, inLink));
3530  while (possibleUnsafeConflict)
3531  {
3532  nextConflict = (RWConflict)
3534  &possibleUnsafeConflict->inLink,
3535  offsetof(RWConflictData, inLink));
3536 
3537  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3538  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3539 
3540  ReleaseRWConflict(possibleUnsafeConflict);
3541 
3542  possibleUnsafeConflict = nextConflict;
3543  }
3544  }
3545 
3546  /* Check for conflict out to old committed transactions. */
3547  if (isCommit
3550  {
3551  /*
3552  * we don't know which old committed transaction we conflicted with,
3553  * so be conservative and use FirstNormalSerCommitSeqNo here
3554  */
3558  }
3559 
3560  /*
3561  * Release all outConflicts to committed transactions. If we're rolling
3562  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3563  * previously committed transactions.
3564  */
3565  conflict = (RWConflict)
3568  offsetof(RWConflictData, outLink));
3569  while (conflict)
3570  {
3571  nextConflict = (RWConflict)
3573  &conflict->outLink,
3574  offsetof(RWConflictData, outLink));
3575 
3576  if (isCommit
3578  && SxactIsCommitted(conflict->sxactIn))
3579  {
3584  }
3585 
3586  if (!isCommit
3587  || SxactIsCommitted(conflict->sxactIn)
3589  ReleaseRWConflict(conflict);
3590 
3591  conflict = nextConflict;
3592  }
3593 
3594  /*
3595  * Release all inConflicts from committed and read-only transactions. If
3596  * we're rolling back, clear them all.
3597  */
3598  conflict = (RWConflict)
3601  offsetof(RWConflictData, inLink));
3602  while (conflict)
3603  {
3604  nextConflict = (RWConflict)
3606  &conflict->inLink,
3607  offsetof(RWConflictData, inLink));
3608 
3609  if (!isCommit
3610  || SxactIsCommitted(conflict->sxactOut)
3611  || SxactIsReadOnly(conflict->sxactOut))
3612  ReleaseRWConflict(conflict);
3613 
3614  conflict = nextConflict;
3615  }
3616 
3617  if (!topLevelIsDeclaredReadOnly)
3618  {
3619  /*
3620  * Remove ourselves from the list of possible conflicts for concurrent
3621  * READ ONLY transactions, flagging them as unsafe if we have a
3622  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3623  * up if they are known safe or known unsafe.
3624  */
3625  possibleUnsafeConflict = (RWConflict)
3628  offsetof(RWConflictData, outLink));
3629  while (possibleUnsafeConflict)
3630  {
3631  nextConflict = (RWConflict)
3633  &possibleUnsafeConflict->outLink,
3634  offsetof(RWConflictData, outLink));
3635 
3636  roXact = possibleUnsafeConflict->sxactIn;
3637  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3638  Assert(SxactIsReadOnly(roXact));
3639 
3640  /* Mark conflicted if necessary. */
3641  if (isCommit
3642  && MyXactDidWrite
3645  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3646  {
3647  /*
3648  * This releases possibleUnsafeConflict (as well as all other
3649  * possible conflicts for roXact)
3650  */
3651  FlagSxactUnsafe(roXact);
3652  }
3653  else
3654  {
3655  ReleaseRWConflict(possibleUnsafeConflict);
3656 
3657  /*
3658  * If we were the last possible conflict, flag it safe. The
3659  * transaction can now safely release its predicate locks (but
3660  * that transaction's backend has to do that itself).
3661  */
3662  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3663  roXact->flags |= SXACT_FLAG_RO_SAFE;
3664  }
3665 
3666  /*
3667  * Wake up the process for a waiting DEFERRABLE transaction if we
3668  * now know it's either safe or conflicted.
3669  */
3670  if (SxactIsDeferrableWaiting(roXact) &&
3671  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3672  ProcSendSignal(roXact->pid);
3673 
3674  possibleUnsafeConflict = nextConflict;
3675  }
3676  }
3677 
3678  /*
3679  * Check whether it's time to clean up old transactions. This can only be
3680  * done when the last serializable transaction with the oldest xmin among
3681  * serializable transactions completes. We then find the "new oldest"
3682  * xmin and purge any transactions which finished before this transaction
3683  * was launched.
3684  */
3685  needToClear = false;
3687  {
3689  if (--(PredXact->SxactGlobalXminCount) == 0)
3690  {
3692  needToClear = true;
3693  }
3694  }
3695 
3696  LWLockRelease(SerializableXactHashLock);
3697 
3698  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3699 
3700  /* Add this to the list of transactions to check for later cleanup. */
3701  if (isCommit)
3704 
3705  /*
3706  * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3707  * partially release it. That's necessary because other backends may have
3708  * a reference to it. The leader will release the SERIALIZABLEXACT itself
3709  * at the end of the transaction after workers have stopped running.
3710  */
3711  if (!isCommit)
3713  isReadOnlySafe && IsInParallelMode(),
3714  false);
3715 
3716  LWLockRelease(SerializableFinishedListLock);
3717 
3718  if (needToClear)
3720 
3722 }
#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:3725
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3743
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:220
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:750
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1909
#define SxactIsDoomed(sxact)
Definition: predicate.c:275
bool IsInParallelMode(void)
Definition: xact.c:1013
#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:990
#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:3900
#define Assert(condition)
Definition: c.h:804
#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:1199
#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:3274
#define SxactIsCommitted(sxact)
Definition: predicate.c:272
#define offsetof(type, field)
Definition: c.h:727
SERIALIZABLEXACT * sxactOut

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1720 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1723 {
1725 
1726  /*
1727  * If this is called by parallel.c in a parallel worker, we don't want to
1728  * create a SERIALIZABLEXACT just yet because the leader's
1729  * SERIALIZABLEXACT will be installed with AttachSerializableXact(). We
1730  * also don't want to reject SERIALIZABLE READ ONLY DEFERRABLE in this
1731  * case, because the leader has already determined that the snapshot it
1732  * has passed us is safe. So there is nothing for us to do.
1733  */
1734  if (IsParallelWorker())
1735  return;
1736 
1737  /*
1738  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1739  * import snapshots, since there's no way to wait for a safe snapshot when
1740  * we're using the snap we're told to. (XXX instead of throwing an error,
1741  * we could just ignore the XactDeferrable flag?)
1742  */
1744  ereport(ERROR,
1745  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1746  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1747 
1748  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1749  sourcepid);
1750 }
bool XactDeferrable
Definition: xact.c:82
int errcode(int sqlerrcode)
Definition: elog.c:698
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1762
#define ERROR
Definition: elog.h:46
#define IsParallelWorker()
Definition: parallel.h:61
#define ereport(elevel,...)
Definition: elog.h:157
bool XactReadOnly
Definition: xact.c:79
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define IsolationIsSerializable()
Definition: xact.h:52

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5186 of file predicate.c.

References MySerializableXact.

Referenced by InitializeParallelDSM().

5187 {
5188  return MySerializableXact;
5189 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:416

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3146 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3147 {
3148  DropAllPredicateLocksFromTable(relation, true);
3149 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2950

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