PostgreSQL Source Code  git master
predicate.h File Reference
#include "storage/lock.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for predicate.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NUM_OLDSERXID_BUFFERS   16
 

Functions

void InitPredicateLocks (void)
 
Size PredicateLockShmemSize (void)
 
void CheckPointPredicate (void)
 
bool PageIsPredicateLocked (Relation relation, BlockNumber blkno)
 
Snapshot GetSerializableTransactionSnapshot (Snapshot snapshot)
 
void SetSerializableTransactionSnapshot (Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
 
void RegisterPredicateLockingXid (TransactionId xid)
 
void PredicateLockRelation (Relation relation, Snapshot snapshot)
 
void PredicateLockPage (Relation relation, BlockNumber blkno, Snapshot snapshot)
 
void PredicateLockTuple (Relation relation, HeapTuple tuple, Snapshot snapshot)
 
void PredicateLockPageSplit (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void PredicateLockPageCombine (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void TransferPredicateLocksToHeapRelation (Relation relation)
 
void ReleasePredicateLocks (bool isCommit)
 
void CheckForSerializableConflictOut (bool valid, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
 
void CheckForSerializableConflictIn (Relation relation, HeapTuple tuple, Buffer buffer)
 
void CheckTableForSerializableConflictIn (Relation relation)
 
void PreCommit_CheckForSerializationFailure (void)
 
void AtPrepare_PredicateLocks (void)
 
void PostPrepare_PredicateLocks (TransactionId xid)
 
void PredicateLockTwoPhaseFinish (TransactionId xid, bool isCommit)
 
void predicatelock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 

Variables

int max_predicate_locks_per_xact
 
int max_predicate_locks_per_relation
 
int max_predicate_locks_per_page
 

Macro Definition Documentation

◆ NUM_OLDSERXID_BUFFERS

#define NUM_OLDSERXID_BUFFERS   16

Definition at line 31 of file predicate.h.

Referenced by OldSerXidInit(), and PredicateLockShmemSize().

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

Definition at line 4759 of file predicate.c.

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

4760 {
4761  PREDICATELOCK *predlock;
4762  SERIALIZABLEXACT *sxact;
4763  TwoPhasePredicateRecord record;
4764  TwoPhasePredicateXactRecord *xactRecord;
4765  TwoPhasePredicateLockRecord *lockRecord;
4766 
4767  sxact = MySerializableXact;
4768  xactRecord = &(record.data.xactRecord);
4769  lockRecord = &(record.data.lockRecord);
4770 
4772  return;
4773 
4774  /* Generate an xact record for our SERIALIZABLEXACT */
4776  xactRecord->xmin = MySerializableXact->xmin;
4777  xactRecord->flags = MySerializableXact->flags;
4778 
4779  /*
4780  * Note that we don't include the list of conflicts in our out in the
4781  * statefile, because new conflicts can be added even after the
4782  * transaction prepares. We'll just make a conservative assumption during
4783  * recovery instead.
4784  */
4785 
4787  &record, sizeof(record));
4788 
4789  /*
4790  * Generate a lock record for each lock.
4791  *
4792  * To do this, we need to walk the predicate lock list in our sxact rather
4793  * than using the local predicate lock table because the latter is not
4794  * guaranteed to be accurate.
4795  */
4796  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4797 
4798  predlock = (PREDICATELOCK *)
4799  SHMQueueNext(&(sxact->predicateLocks),
4800  &(sxact->predicateLocks),
4801  offsetof(PREDICATELOCK, xactLink));
4802 
4803  while (predlock != NULL)
4804  {
4806  lockRecord->target = predlock->tag.myTarget->tag;
4807 
4809  &record, sizeof(record));
4810 
4811  predlock = (PREDICATELOCK *)
4812  SHMQueueNext(&(sxact->predicateLocks),
4813  &(predlock->xactLink),
4814  offsetof(PREDICATELOCK, xactLink));
4815  }
4816 
4817  LWLockRelease(SerializablePredicateLockListLock);
4818 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
TwoPhasePredicateRecordType type
PREDICATELOCKTARGETTAG target
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1191
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
union TwoPhasePredicateRecord::@111 data
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:622
PREDICATELOCKTARGET * myTarget

◆ CheckForSerializableConflictIn()

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

Definition at line 4280 of file predicate.c.

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

Referenced by _bt_check_unique(), _bt_doinsert(), _hash_doinsert(), ginEntryInsert(), ginFindLeafPage(), ginHeapTupleFastInsert(), gistinserttuples(), heap_delete(), heap_insert(), heap_multi_insert(), heap_update(), and index_insert().

4282 {
4283  PREDICATELOCKTARGETTAG targettag;
4284 
4285  if (!SerializationNeededForWrite(relation))
4286  return;
4287 
4288  /* Check if someone else has already decided that we need to die */
4290  ereport(ERROR,
4291  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4292  errmsg("could not serialize access due to read/write dependencies among transactions"),
4293  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4294  errhint("The transaction might succeed if retried.")));
4295 
4296  /*
4297  * We're doing a write which might cause rw-conflicts now or later.
4298  * Memorize that fact.
4299  */
4300  MyXactDidWrite = true;
4301 
4302  /*
4303  * It is important that we check for locks from the finest granularity to
4304  * the coarsest granularity, so that granularity promotion doesn't cause
4305  * us to miss a lock. The new (coarser) lock will be acquired before the
4306  * old (finer) locks are released.
4307  *
4308  * It is not possible to take and hold a lock across the checks for all
4309  * granularities because each target could be in a separate partition.
4310  */
4311  if (tuple != NULL)
4312  {
4314  relation->rd_node.dbNode,
4315  relation->rd_id,
4316  ItemPointerGetBlockNumber(&(tuple->t_self)),
4317  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4318  CheckTargetForConflictsIn(&targettag);
4319  }
4320 
4321  if (BufferIsValid(buffer))
4322  {
4324  relation->rd_node.dbNode,
4325  relation->rd_id,
4327  CheckTargetForConflictsIn(&targettag);
4328  }
4329 
4331  relation->rd_node.dbNode,
4332  relation->rd_id);
4333  CheckTargetForConflictsIn(&targettag);
4334 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
int errhint(const char *fmt,...)
Definition: elog.c:987
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4102
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:540
#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:900
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
Oid rd_id
Definition: rel.h:86
RelFileNode rd_node
Definition: rel.h:55
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool MyXactDidWrite
Definition: predicate.c:410
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ CheckForSerializableConflictOut()

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

Definition at line 3899 of file predicate.c.

References Assert, SERIALIZABLEXACT::earliestOutConflictCommit, elog, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleSatisfiesVacuum(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, OldSerXidGetMinConflictCommitSeqNo(), RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerializationNeededForRead(), SHMQueueEmpty(), SubTransGetTopmostTransaction(), SXACT_FLAG_DOOMED, SXACT_FLAG_SUMMARY_CONFLICT_OUT, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, HeapTupleData::t_data, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionXmin, SERIALIZABLEXIDTAG::xid, and XidIsConcurrent().

Referenced by bitgetpage(), heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heapgetpage(), heapgettup(), and tablesample_getnext().

3902 {
3903  TransactionId xid;
3904  SERIALIZABLEXIDTAG sxidtag;
3905  SERIALIZABLEXID *sxid;
3906  SERIALIZABLEXACT *sxact;
3907  HTSV_Result htsvResult;
3908 
3909  if (!SerializationNeededForRead(relation, snapshot))
3910  return;
3911 
3912  /* Check if someone else has already decided that we need to die */
3914  {
3915  ereport(ERROR,
3916  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3917  errmsg("could not serialize access due to read/write dependencies among transactions"),
3918  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3919  errhint("The transaction might succeed if retried.")));
3920  }
3921 
3922  /*
3923  * Check to see whether the tuple has been written to by a concurrent
3924  * transaction, either to create it not visible to us, or to delete it
3925  * while it is visible to us. The "visible" bool indicates whether the
3926  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
3927  * is going on with it.
3928  */
3929  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
3930  switch (htsvResult)
3931  {
3932  case HEAPTUPLE_LIVE:
3933  if (visible)
3934  return;
3935  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3936  break;
3938  if (!visible)
3939  return;
3940  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3941  break;
3943  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3944  break;
3946  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3947  break;
3948  case HEAPTUPLE_DEAD:
3949  return;
3950  default:
3951 
3952  /*
3953  * The only way to get to this default clause is if a new value is
3954  * added to the enum type without adding it to this switch
3955  * statement. That's a bug, so elog.
3956  */
3957  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
3958 
3959  /*
3960  * In spite of having all enum values covered and calling elog on
3961  * this default, some compilers think this is a code path which
3962  * allows xid to be used below without initialization. Silence
3963  * that warning.
3964  */
3965  xid = InvalidTransactionId;
3966  }
3969 
3970  /*
3971  * Find top level xid. Bail out if xid is too early to be a conflict, or
3972  * if it's our own xid.
3973  */
3975  return;
3976  xid = SubTransGetTopmostTransaction(xid);
3978  return;
3980  return;
3981 
3982  /*
3983  * Find sxact or summarized info for the top level xid.
3984  */
3985  sxidtag.xid = xid;
3986  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3987  sxid = (SERIALIZABLEXID *)
3988  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
3989  if (!sxid)
3990  {
3991  /*
3992  * Transaction not found in "normal" SSI structures. Check whether it
3993  * got pushed out to SLRU storage for "old committed" transactions.
3994  */
3995  SerCommitSeqNo conflictCommitSeqNo;
3996 
3997  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
3998  if (conflictCommitSeqNo != 0)
3999  {
4000  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4002  || conflictCommitSeqNo
4004  ereport(ERROR,
4005  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4006  errmsg("could not serialize access due to read/write dependencies among transactions"),
4007  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4008  errhint("The transaction might succeed if retried.")));
4009 
4012  ereport(ERROR,
4013  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4014  errmsg("could not serialize access due to read/write dependencies among transactions"),
4015  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4016  errhint("The transaction might succeed if retried.")));
4017 
4019  }
4020 
4021  /* It's not serializable or otherwise not important. */
4022  LWLockRelease(SerializableXactHashLock);
4023  return;
4024  }
4025  sxact = sxid->myXact;
4026  Assert(TransactionIdEquals(sxact->topXid, xid));
4027  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4028  {
4029  /* Can't conflict with ourself or a transaction that will roll back. */
4030  LWLockRelease(SerializableXactHashLock);
4031  return;
4032  }
4033 
4034  /*
4035  * We have a conflict out to a transaction which has a conflict out to a
4036  * summarized transaction. That summarized transaction must have
4037  * committed first, and we can't tell when it committed in relation to our
4038  * snapshot acquisition, so something needs to be canceled.
4039  */
4040  if (SxactHasSummaryConflictOut(sxact))
4041  {
4042  if (!SxactIsPrepared(sxact))
4043  {
4044  sxact->flags |= SXACT_FLAG_DOOMED;
4045  LWLockRelease(SerializableXactHashLock);
4046  return;
4047  }
4048  else
4049  {
4050  LWLockRelease(SerializableXactHashLock);
4051  ereport(ERROR,
4052  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4053  errmsg("could not serialize access due to read/write dependencies among transactions"),
4054  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4055  errhint("The transaction might succeed if retried.")));
4056  }
4057  }
4058 
4059  /*
4060  * If this is a read-only transaction and the writing transaction has
4061  * committed, and it doesn't have a rw-conflict to a transaction which
4062  * committed before it, no conflict.
4063  */
4065  && SxactIsCommitted(sxact)
4066  && !SxactHasSummaryConflictOut(sxact)
4067  && (!SxactHasConflictOut(sxact)
4069  {
4070  /* Read-only transaction will appear to run first. No conflict. */
4071  LWLockRelease(SerializableXactHashLock);
4072  return;
4073  }
4074 
4075  if (!XidIsConcurrent(xid))
4076  {
4077  /* This write was already in our snapshot; no conflict. */
4078  LWLockRelease(SerializableXactHashLock);
4079  return;
4080  }
4081 
4083  {
4084  /* We don't want duplicate conflict records in the list. */
4085  LWLockRelease(SerializableXactHashLock);
4086  return;
4087  }
4088 
4089  /*
4090  * Flag the conflict. But first, if this conflict creates a dangerous
4091  * structure, ereport an error.
4092  */
4094  LWLockRelease(SerializableXactHashLock);
4095 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:635
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4456
uint32 TransactionId
Definition: c.h:474
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:271
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3856
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:384
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
HTSV_Result
Definition: tqual.h:49
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define ERROR
Definition: elog.h:43
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
#define ereport(elevel, rest)
Definition: elog.h:122
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:272
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define InvalidSerCommitSeqNo
union SERIALIZABLEXACT::@110 SeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo earliestOutConflictCommit
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:905
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:278
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:496
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define SxactIsCommitted(sxact)
Definition: predicate.c:266

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 997 of file predicate.c.

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

Referenced by CheckPointGuts().

998 {
999  int tailPage;
1000 
1001  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
1002 
1003  /* Exit quickly if the SLRU is currently not in use. */
1004  if (oldSerXidControl->headPage < 0)
1005  {
1006  LWLockRelease(OldSerXidLock);
1007  return;
1008  }
1009 
1011  {
1012  /* We can truncate the SLRU up to the page containing tailXid */
1013  tailPage = OldSerXidPage(oldSerXidControl->tailXid);
1014  }
1015  else
1016  {
1017  /*
1018  * The SLRU is no longer needed. Truncate to head before we set head
1019  * invalid.
1020  *
1021  * XXX: It's possible that the SLRU is not needed again until XID
1022  * wrap-around has happened, so that the segment containing headPage
1023  * that we leave behind will appear to be new again. In that case it
1024  * won't be removed until XID horizon advances enough to make it
1025  * current again.
1026  */
1027  tailPage = oldSerXidControl->headPage;
1028  oldSerXidControl->headPage = -1;
1029  }
1030 
1031  LWLockRelease(OldSerXidLock);
1032 
1033  /* Truncate away pages that are no longer required */
1035 
1036  /*
1037  * Flush dirty SLRU pages to disk
1038  *
1039  * This is not actually necessary from a correctness point of view. We do
1040  * it merely as a debugging aid.
1041  *
1042  * We're doing this after the truncation to avoid writing pages right
1043  * before deleting the file in which they sit, which would be completely
1044  * pointless.
1045  */
1047 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1168
#define OldSerXidPage(xid)
Definition: predicate.c:331
#define OldSerXidSlruCtl
Definition: predicate.c:314
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1103
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static OldSerXidControl oldSerXidControl
Definition: predicate.c:342
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId tailXid
Definition: predicate.c:337

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)

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

4365 {
4366  HASH_SEQ_STATUS seqstat;
4367  PREDICATELOCKTARGET *target;
4368  Oid dbId;
4369  Oid heapId;
4370  int i;
4371 
4372  /*
4373  * Bail out quickly if there are no serializable transactions running.
4374  * It's safe to check this without taking locks because the caller is
4375  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4376  * would matter here can be acquired while that is held.
4377  */
4379  return;
4380 
4381  if (!SerializationNeededForWrite(relation))
4382  return;
4383 
4384  /*
4385  * We're doing a write which might cause rw-conflicts now or later.
4386  * Memorize that fact.
4387  */
4388  MyXactDidWrite = true;
4389 
4390  Assert(relation->rd_index == NULL); /* not an index relation */
4391 
4392  dbId = relation->rd_node.dbNode;
4393  heapId = relation->rd_id;
4394 
4395  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4396  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4398  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4399 
4400  /* Scan through target list */
4402 
4403  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4404  {
4405  PREDICATELOCK *predlock;
4406 
4407  /*
4408  * Check whether this is a target which needs attention.
4409  */
4410  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4411  continue; /* wrong relation id */
4412  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4413  continue; /* wrong database id */
4414 
4415  /*
4416  * Loop through locks for this target and flag conflicts.
4417  */
4418  predlock = (PREDICATELOCK *)
4419  SHMQueueNext(&(target->predicateLocks),
4420  &(target->predicateLocks),
4421  offsetof(PREDICATELOCK, targetLink));
4422  while (predlock)
4423  {
4424  PREDICATELOCK *nextpredlock;
4425 
4426  nextpredlock = (PREDICATELOCK *)
4427  SHMQueueNext(&(target->predicateLocks),
4428  &(predlock->targetLink),
4429  offsetof(PREDICATELOCK, targetLink));
4430 
4431  if (predlock->tag.myXact != MySerializableXact
4433  {
4435  }
4436 
4437  predlock = nextpredlock;
4438  }
4439  }
4440 
4441  /* Release locks in reverse order */
4442  LWLockRelease(SerializableXactHashLock);
4443  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4445  LWLockRelease(SerializablePredicateLockListLock);
4446 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:635
static HTAB * PredicateLockTargetHash
Definition: predicate.c:385
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4456
static PredXactList PredXact
Definition: predicate.c:372
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:540
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
Form_pg_index rd_index
Definition: rel.h:131
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:86
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:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:250
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:410
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:622
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1590 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

1591 {
1593 
1594  /*
1595  * Can't use serializable mode while recovery is still active, as it is,
1596  * for example, on a hot standby. We could get here despite the check in
1597  * check_XactIsoLevel() if default_transaction_isolation is set to
1598  * serializable, so phrase the hint accordingly.
1599  */
1600  if (RecoveryInProgress())
1601  ereport(ERROR,
1602  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1603  errmsg("cannot use serializable mode in a hot standby"),
1604  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1605  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1606 
1607  /*
1608  * A special optimization is available for SERIALIZABLE READ ONLY
1609  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1610  * thereby avoid all SSI overhead once it's running.
1611  */
1613  return GetSafeSnapshot(snapshot);
1614 
1615  return GetSerializableTransactionSnapshotInt(snapshot,
1616  NULL, InvalidPid);
1617 }
bool XactDeferrable
Definition: xact.c:79
int errhint(const char *fmt,...)
Definition: elog.c:987
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1468
int errcode(int sqlerrcode)
Definition: elog.c:575
bool RecoveryInProgress(void)
Definition: xlog.c:7949
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1661
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:76
#define Assert(condition)
Definition: c.h:699
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:51
#define InvalidPid
Definition: miscadmin.h:31

◆ InitPredicateLocks()

void InitPredicateLocks ( void  )

Definition at line 1062 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, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, HASHCTL::num_partitions, NUM_PREDICATELOCK_PARTITIONS, PredXactListData::OldCommittedSxact, OldSerXidInit(), SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, predicatelock_hash(), PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXactListDataSize, PredXactListElementDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPoolHeaderDataSize, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SetInvalidVirtualTransactionId, ShmemAlloc(), ShmemInitHash(), ShmemInitStruct(), SHMQueueInit(), SHMQueueInsertBefore(), SXACT_FLAG_COMMITTED, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SERIALIZABLEXACT::topXid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by CreateSharedMemoryAndSemaphores().

1063 {
1064  HASHCTL info;
1065  long max_table_size;
1066  Size requestSize;
1067  bool found;
1068 
1069 #ifndef EXEC_BACKEND
1071 #endif
1072 
1073  /*
1074  * Compute size of predicate lock target hashtable. Note these
1075  * calculations must agree with PredicateLockShmemSize!
1076  */
1077  max_table_size = NPREDICATELOCKTARGETENTS();
1078 
1079  /*
1080  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1081  * per-predicate-lock-target information.
1082  */
1083  MemSet(&info, 0, sizeof(info));
1084  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1085  info.entrysize = sizeof(PREDICATELOCKTARGET);
1087 
1088  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1089  max_table_size,
1090  max_table_size,
1091  &info,
1092  HASH_ELEM | HASH_BLOBS |
1094 
1095  /*
1096  * Reserve a dummy entry in the hash table; we use it to make sure there's
1097  * always one entry available when we need to split or combine a page,
1098  * because running out of space there could mean aborting a
1099  * non-serializable transaction.
1100  */
1101  if (!IsUnderPostmaster)
1102  {
1104  HASH_ENTER, &found);
1105  Assert(!found);
1106  }
1107 
1108  /* Pre-calculate the hash and partition lock of the scratch entry */
1111 
1112  /*
1113  * Allocate hash table for PREDICATELOCK structs. This stores per
1114  * xact-lock-of-a-target information.
1115  */
1116  MemSet(&info, 0, sizeof(info));
1117  info.keysize = sizeof(PREDICATELOCKTAG);
1118  info.entrysize = sizeof(PREDICATELOCK);
1119  info.hash = predicatelock_hash;
1121 
1122  /* Assume an average of 2 xacts per target */
1123  max_table_size *= 2;
1124 
1125  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1126  max_table_size,
1127  max_table_size,
1128  &info,
1131 
1132  /*
1133  * Compute size for serializable transaction hashtable. Note these
1134  * calculations must agree with PredicateLockShmemSize!
1135  */
1136  max_table_size = (MaxBackends + max_prepared_xacts);
1137 
1138  /*
1139  * Allocate a list to hold information on transactions participating in
1140  * predicate locking.
1141  *
1142  * Assume an average of 10 predicate locking transactions per backend.
1143  * This allows aggressive cleanup while detail is present before data must
1144  * be summarized for storage in SLRU and the "dummy" transaction.
1145  */
1146  max_table_size *= 10;
1147 
1148  PredXact = ShmemInitStruct("PredXactList",
1150  &found);
1151  Assert(found == IsUnderPostmaster);
1152  if (!found)
1153  {
1154  int i;
1155 
1164  requestSize = mul_size((Size) max_table_size,
1166  PredXact->element = ShmemAlloc(requestSize);
1167  /* Add all elements to available list, clean. */
1168  memset(PredXact->element, 0, requestSize);
1169  for (i = 0; i < max_table_size; i++)
1170  {
1172  &(PredXact->element[i].link));
1173  }
1189  }
1190  /* This never changes, so let's keep a local copy. */
1192 
1193  /*
1194  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1195  * information for serializable transactions which have accessed data.
1196  */
1197  MemSet(&info, 0, sizeof(info));
1198  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1199  info.entrysize = sizeof(SERIALIZABLEXID);
1200 
1201  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1202  max_table_size,
1203  max_table_size,
1204  &info,
1205  HASH_ELEM | HASH_BLOBS |
1206  HASH_FIXED_SIZE);
1207 
1208  /*
1209  * Allocate space for tracking rw-conflicts in lists attached to the
1210  * transactions.
1211  *
1212  * Assume an average of 5 conflicts per transaction. Calculations suggest
1213  * that this will prevent resource exhaustion in even the most pessimal
1214  * loads up to max_connections = 200 with all 200 connections pounding the
1215  * database with serializable transactions. Beyond that, there may be
1216  * occasional transactions canceled when trying to flag conflicts. That's
1217  * probably OK.
1218  */
1219  max_table_size *= 5;
1220 
1221  RWConflictPool = ShmemInitStruct("RWConflictPool",
1223  &found);
1224  Assert(found == IsUnderPostmaster);
1225  if (!found)
1226  {
1227  int i;
1228 
1230  requestSize = mul_size((Size) max_table_size,
1232  RWConflictPool->element = ShmemAlloc(requestSize);
1233  /* Add all elements to available list, clean. */
1234  memset(RWConflictPool->element, 0, requestSize);
1235  for (i = 0; i < max_table_size; i++)
1236  {
1238  &(RWConflictPool->element[i].outLink));
1239  }
1240  }
1241 
1242  /*
1243  * Create or attach to the header for the list of finished serializable
1244  * transactions.
1245  */
1247  ShmemInitStruct("FinishedSerializableTransactions",
1248  sizeof(SHM_QUEUE),
1249  &found);
1250  Assert(found == IsUnderPostmaster);
1251  if (!found)
1253 
1254  /*
1255  * Initialize the SLRU storage for old committed serializable
1256  * transactions.
1257  */
1258  OldSerXidInit();
1259 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:385
#define HASH_ELEM
Definition: hsearch.h:87
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:253
static PredXactList PredXact
Definition: predicate.c:372
TransactionId SxactGlobalXmin
struct SERIALIZABLEXIDTAG SERIALIZABLEXIDTAG
struct PREDICATELOCKTARGET PREDICATELOCKTARGET
Size entrysize
Definition: hsearch.h:73
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1327
static HTAB * SerializableXidHash
Definition: predicate.c:384
#define MemSet(start, val, len)
Definition: c.h:908
static void OldSerXidInit(void)
Definition: predicate.c:796
void * ShmemAlloc(Size size)
Definition: shmem.c:157
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:386
int max_prepared_xacts
Definition: twophase.c:117
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:378
struct PREDICATELOCK PREDICATELOCK
long num_partitions
Definition: hsearch.h:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
struct PREDICATELOCKTAG PREDICATELOCKTAG
int MaxBackends
Definition: globals.c:134
#define RWConflictDataSize
VirtualTransactionId vxid
bool IsUnderPostmaster
Definition: globals.c:108
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
union SERIALIZABLEXACT::@110 SeqNo
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:88
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:699
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:433
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:96
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:350
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:394
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:317
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:387
static uint32 ScratchTargetTagHash
Definition: predicate.c:395
static LWLock * ScratchPartitionLock
Definition: predicate.c:396
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:562
PredXactListElement element
#define PredXactListElementDataSize
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

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

1884 {
1885  PREDICATELOCKTARGETTAG targettag;
1886  uint32 targettaghash;
1887  LWLock *partitionLock;
1888  PREDICATELOCKTARGET *target;
1889 
1891  relation->rd_node.dbNode,
1892  relation->rd_id,
1893  blkno);
1894 
1895  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1896  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1897  LWLockAcquire(partitionLock, LW_SHARED);
1898  target = (PREDICATELOCKTARGET *)
1900  &targettag, targettaghash,
1901  HASH_FIND, NULL);
1902  LWLockRelease(partitionLock);
1903 
1904  return (target != NULL);
1905 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:385
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
unsigned int uint32
Definition: c.h:325
Oid rd_id
Definition: rel.h:86
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
RelFileNode rd_node
Definition: rel.h:55
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ PostPrepare_PredicateLocks()

void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4828 of file predicate.c.

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

Referenced by PrepareTransaction().

4829 {
4831  return;
4832 
4834 
4835  MySerializableXact->pid = 0;
4836 
4838  LocalPredicateLockHash = NULL;
4839 
4841  MyXactDidWrite = false;
4842 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:814
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:699
static HTAB * LocalPredicateLockHash
Definition: predicate.c:402
static bool MyXactDidWrite
Definition: predicate.c:410

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

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

Referenced by CommitTransaction(), and PrepareTransaction().

4667 {
4668  RWConflict nearConflict;
4669 
4671  return;
4672 
4674 
4675  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4676 
4677  /* Check if someone else has already decided that we need to die */
4679  {
4680  LWLockRelease(SerializableXactHashLock);
4681  ereport(ERROR,
4682  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4683  errmsg("could not serialize access due to read/write dependencies among transactions"),
4684  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4685  errhint("The transaction might succeed if retried.")));
4686  }
4687 
4688  nearConflict = (RWConflict)
4691  offsetof(RWConflictData, inLink));
4692  while (nearConflict)
4693  {
4694  if (!SxactIsCommitted(nearConflict->sxactOut)
4695  && !SxactIsDoomed(nearConflict->sxactOut))
4696  {
4697  RWConflict farConflict;
4698 
4699  farConflict = (RWConflict)
4700  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4701  &nearConflict->sxactOut->inConflicts,
4702  offsetof(RWConflictData, inLink));
4703  while (farConflict)
4704  {
4705  if (farConflict->sxactOut == MySerializableXact
4706  || (!SxactIsCommitted(farConflict->sxactOut)
4707  && !SxactIsReadOnly(farConflict->sxactOut)
4708  && !SxactIsDoomed(farConflict->sxactOut)))
4709  {
4710  /*
4711  * Normally, we kill the pivot transaction to make sure we
4712  * make progress if the failing transaction is retried.
4713  * However, we can't kill it if it's already prepared, so
4714  * in that case we commit suicide instead.
4715  */
4716  if (SxactIsPrepared(nearConflict->sxactOut))
4717  {
4718  LWLockRelease(SerializableXactHashLock);
4719  ereport(ERROR,
4720  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4721  errmsg("could not serialize access due to read/write dependencies among transactions"),
4722  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4723  errhint("The transaction might succeed if retried.")));
4724  }
4725  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4726  break;
4727  }
4728  farConflict = (RWConflict)
4729  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4730  &farConflict->inLink,
4731  offsetof(RWConflictData, inLink));
4732  }
4733  }
4734 
4735  nearConflict = (RWConflict)
4737  &nearConflict->inLink,
4738  offsetof(RWConflictData, inLink));
4739  }
4740 
4743 
4744  LWLockRelease(SerializableXactHashLock);
4745 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
int errhint(const char *fmt,...)
Definition: elog.c:987
static PredXactList PredXact
Definition: predicate.c:372
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define ERROR
Definition: elog.h:43
#define InvalidSerializableXact
#define SXACT_FLAG_PREPARED
#define ereport(elevel, rest)
Definition: elog.h:122
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define SXACT_FLAG_DOOMED
#define Assert(condition)
Definition: c.h:699
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:51
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:622
SERIALIZABLEXACT * sxactOut

◆ predicatelock_twophase_recover()

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

Definition at line 4877 of file predicate.c.

References Assert, VirtualTransactionId::backendId, SERIALIZABLEXACT::commitSeqNo, CreatePredicateLock(), CreatePredXact(), TwoPhasePredicateRecord::data, ereport, errcode(), errmsg(), ERROR, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, HASH_ENTER, HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidBackendId, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, VirtualTransactionId::localTransactionId, TwoPhasePredicateRecord::lockRecord, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, SERIALIZABLEXID::myXact, OldSerXidSetActiveSerXmin(), SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, SERIALIZABLEXACT::prepareSeqNo, RecoverySerCommitSeqNo, SERIALIZABLEXACT::SeqNo, SHMQueueElemInit(), SHMQueueInit(), SXACT_FLAG_SUMMARY_CONFLICT_IN, SXACT_FLAG_SUMMARY_CONFLICT_OUT, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactIsPrepared, SxactIsReadOnly, TwoPhasePredicateLockRecord::target, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollows(), TransactionIdIsValid, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXIDTAG::xid, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

4879 {
4880  TwoPhasePredicateRecord *record;
4881 
4882  Assert(len == sizeof(TwoPhasePredicateRecord));
4883 
4884  record = (TwoPhasePredicateRecord *) recdata;
4885 
4886  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4887  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4888 
4889  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4890  {
4891  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4892  TwoPhasePredicateXactRecord *xactRecord;
4893  SERIALIZABLEXACT *sxact;
4894  SERIALIZABLEXID *sxid;
4895  SERIALIZABLEXIDTAG sxidtag;
4896  bool found;
4897 
4898  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4899 
4900  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4901  sxact = CreatePredXact();
4902  if (!sxact)
4903  ereport(ERROR,
4904  (errcode(ERRCODE_OUT_OF_MEMORY),
4905  errmsg("out of shared memory")));
4906 
4907  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
4908  sxact->vxid.backendId = InvalidBackendId;
4910  sxact->pid = 0;
4911 
4912  /* a prepared xact hasn't committed yet */
4916 
4918 
4919  /*
4920  * Don't need to track this; no transactions running at the time the
4921  * recovered xact started are still active, except possibly other
4922  * prepared xacts and we don't care whether those are RO_SAFE or not.
4923  */
4925 
4926  SHMQueueInit(&(sxact->predicateLocks));
4927  SHMQueueElemInit(&(sxact->finishedLink));
4928 
4929  sxact->topXid = xid;
4930  sxact->xmin = xactRecord->xmin;
4931  sxact->flags = xactRecord->flags;
4932  Assert(SxactIsPrepared(sxact));
4933  if (!SxactIsReadOnly(sxact))
4934  {
4938  }
4939 
4940  /*
4941  * We don't know whether the transaction had any conflicts or not, so
4942  * we'll conservatively assume that it had both a conflict in and a
4943  * conflict out, and represent that with the summary conflict flags.
4944  */
4945  SHMQueueInit(&(sxact->outConflicts));
4946  SHMQueueInit(&(sxact->inConflicts));
4949 
4950  /* Register the transaction's xid */
4951  sxidtag.xid = xid;
4953  &sxidtag,
4954  HASH_ENTER, &found);
4955  Assert(sxid != NULL);
4956  Assert(!found);
4957  sxid->myXact = (SERIALIZABLEXACT *) sxact;
4958 
4959  /*
4960  * Update global xmin. Note that this is a special case compared to
4961  * registering a normal transaction, because the global xmin might go
4962  * backwards. That's OK, because until recovery is over we're not
4963  * going to complete any transactions or create any non-prepared
4964  * transactions, so there's no danger of throwing away.
4965  */
4968  {
4969  PredXact->SxactGlobalXmin = sxact->xmin;
4972  }
4973  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
4974  {
4977  }
4978 
4979  LWLockRelease(SerializableXactHashLock);
4980  }
4981  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
4982  {
4983  /* Lock record. Recreate the PREDICATELOCK */
4984  TwoPhasePredicateLockRecord *lockRecord;
4985  SERIALIZABLEXID *sxid;
4986  SERIALIZABLEXACT *sxact;
4987  SERIALIZABLEXIDTAG sxidtag;
4988  uint32 targettaghash;
4989 
4990  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
4991  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
4992 
4993  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4994  sxidtag.xid = xid;
4995  sxid = (SERIALIZABLEXID *)
4996  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4997  LWLockRelease(SerializableXactHashLock);
4998 
4999  Assert(sxid != NULL);
5000  sxact = sxid->myXact;
5001  Assert(sxact != InvalidSerializableXact);
5002 
5003  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5004  }
5005 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2332
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:372
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:384
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:66
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:134
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:325
uint32 LocalTransactionId
Definition: c.h:476
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
union SERIALIZABLEXACT::@110 SeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
#define InvalidBackendId
Definition: backendid.h:23
#define RecoverySerCommitSeqNo
#define Assert(condition)
Definition: c.h:699
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:946
SerCommitSeqNo prepareSeqNo
union TwoPhasePredicateRecord::@111 data
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TwoPhasePredicateLockRecord lockRecord
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:562

◆ PredicateLockPage()

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

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

2476 {
2478 
2479  if (!SerializationNeededForRead(relation, snapshot))
2480  return;
2481 
2483  relation->rd_node.dbNode,
2484  relation->rd_id,
2485  blkno);
2486  PredicateLockAcquire(&tag);
2487 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2393
Oid rd_id
Definition: rel.h:86
RelFileNode rd_node
Definition: rel.h:55
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:496

◆ PredicateLockPageCombine()

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

Definition at line 3150 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

3152 {
3153  /*
3154  * Page combines differ from page splits in that we ought to be able to
3155  * remove the locks on the old page after transferring them to the new
3156  * page, instead of duplicating them. However, because we can't edit other
3157  * backends' local lock tables, removing the old lock would leave them
3158  * with an entry in their LocalPredicateLockHash for a lock they're not
3159  * holding, which isn't acceptable. So we wind up having to do the same
3160  * work as a page split, acquiring a lock on the new page and keeping the
3161  * old page locked too. That can lead to some false positives, but should
3162  * be rare in practice.
3163  */
3164  PredicateLockPageSplit(relation, oldblkno, newblkno);
3165 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3065

◆ PredicateLockPageSplit()

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

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

3067 {
3068  PREDICATELOCKTARGETTAG oldtargettag;
3069  PREDICATELOCKTARGETTAG newtargettag;
3070  bool success;
3071 
3072  /*
3073  * Bail out quickly if there are no serializable transactions running.
3074  *
3075  * It's safe to do this check without taking any additional locks. Even if
3076  * a serializable transaction starts concurrently, we know it can't take
3077  * any SIREAD locks on the page being split because the caller is holding
3078  * the associated buffer page lock. Memory reordering isn't an issue; the
3079  * memory barrier in the LWLock acquisition guarantees that this read
3080  * occurs while the buffer page lock is held.
3081  */
3083  return;
3084 
3085  if (!PredicateLockingNeededForRelation(relation))
3086  return;
3087 
3088  Assert(oldblkno != newblkno);
3089  Assert(BlockNumberIsValid(oldblkno));
3090  Assert(BlockNumberIsValid(newblkno));
3091 
3092  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3093  relation->rd_node.dbNode,
3094  relation->rd_id,
3095  oldblkno);
3096  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3097  relation->rd_node.dbNode,
3098  relation->rd_id,
3099  newblkno);
3100 
3101  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3102 
3103  /*
3104  * Try copying the locks over to the new page's tag, creating it if
3105  * necessary.
3106  */
3107  success = TransferPredicateLocksToNewTarget(oldtargettag,
3108  newtargettag,
3109  false);
3110 
3111  if (!success)
3112  {
3113  /*
3114  * No more predicate lock entries are available. Failure isn't an
3115  * option here, so promote the page lock to a relation lock.
3116  */
3117 
3118  /* Get the parent relation lock's lock tag */
3119  success = GetParentPredicateLockTag(&oldtargettag,
3120  &newtargettag);
3121  Assert(success);
3122 
3123  /*
3124  * Move the locks to the parent. This shouldn't fail.
3125  *
3126  * Note that here we are removing locks held by other backends,
3127  * leading to a possible inconsistency in their local lock hash table.
3128  * This is OK because we're replacing it with a lock that covers the
3129  * old one.
3130  */
3131  success = TransferPredicateLocksToNewTarget(oldtargettag,
3132  newtargettag,
3133  true);
3134  Assert(success);
3135  }
3136 
3137  LWLockRelease(SerializablePredicateLockListLock);
3138 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:477
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2632
static PredXactList PredXact
Definition: predicate.c:372
TransactionId SxactGlobalXmin
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static bool success
Oid rd_id
Definition: rel.h:86
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1947
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

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

2453 {
2455 
2456  if (!SerializationNeededForRead(relation, snapshot))
2457  return;
2458 
2460  relation->rd_node.dbNode,
2461  relation->rd_id);
2462  PredicateLockAcquire(&tag);
2463 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2393
Oid rd_id
Definition: rel.h:86
RelFileNode rd_node
Definition: rel.h:55
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:496

◆ PredicateLockShmemSize()

Size PredicateLockShmemSize ( void  )

Definition at line 1265 of file predicate.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

1266 {
1267  Size size = 0;
1268  long max_table_size;
1269 
1270  /* predicate lock target hash table */
1271  max_table_size = NPREDICATELOCKTARGETENTS();
1272  size = add_size(size, hash_estimate_size(max_table_size,
1273  sizeof(PREDICATELOCKTARGET)));
1274 
1275  /* predicate lock hash table */
1276  max_table_size *= 2;
1277  size = add_size(size, hash_estimate_size(max_table_size,
1278  sizeof(PREDICATELOCK)));
1279 
1280  /*
1281  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1282  * margin.
1283  */
1284  size = add_size(size, size / 10);
1285 
1286  /* transaction list */
1287  max_table_size = MaxBackends + max_prepared_xacts;
1288  max_table_size *= 10;
1289  size = add_size(size, PredXactListDataSize);
1290  size = add_size(size, mul_size((Size) max_table_size,
1292 
1293  /* transaction xid table */
1294  size = add_size(size, hash_estimate_size(max_table_size,
1295  sizeof(SERIALIZABLEXID)));
1296 
1297  /* rw-conflict pool */
1298  max_table_size *= 5;
1299  size = add_size(size, RWConflictPoolHeaderDataSize);
1300  size = add_size(size, mul_size((Size) max_table_size,
1302 
1303  /* Head for list of finished serializable transactions. */
1304  size = add_size(size, sizeof(SHM_QUEUE));
1305 
1306  /* Shared memory structures for SLRU tracking of old committed xids. */
1307  size = add_size(size, sizeof(OldSerXidControlData));
1309 
1310  return size;
1311 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:253
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:31
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:134
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:732
#define RWConflictPoolHeaderDataSize
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:433
#define PredXactListElementDataSize

◆ PredicateLockTuple()

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

Definition at line 2497 of file predicate.c.

References RelFileNode::dbNode, GetTopTransactionIdIfAny(), HeapTupleHeaderGetXmin, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, PredicateLockAcquire(), PredicateLockExists(), RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, SerializationNeededForRead(), SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, SubTransGetTopmostTransaction(), HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionXmin.

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

2498 {
2500  ItemPointer tid;
2501  TransactionId targetxmin;
2502 
2503  if (!SerializationNeededForRead(relation, snapshot))
2504  return;
2505 
2506  /*
2507  * If it's a heap tuple, return if this xact wrote it.
2508  */
2509  if (relation->rd_index == NULL)
2510  {
2511  TransactionId myxid;
2512 
2513  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2514 
2515  myxid = GetTopTransactionIdIfAny();
2516  if (TransactionIdIsValid(myxid))
2517  {
2519  {
2520  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2521 
2522  if (TransactionIdEquals(xid, myxid))
2523  {
2524  /* We wrote it; we already have a write lock. */
2525  return;
2526  }
2527  }
2528  }
2529  }
2530 
2531  /*
2532  * Do quick-but-not-definitive test for a relation lock first. This will
2533  * never cause a return when the relation is *not* locked, but will
2534  * occasionally let the check continue when there really *is* a relation
2535  * level lock.
2536  */
2538  relation->rd_node.dbNode,
2539  relation->rd_id);
2540  if (PredicateLockExists(&tag))
2541  return;
2542 
2543  tid = &(tuple->t_self);
2545  relation->rd_node.dbNode,
2546  relation->rd_id,
2549  PredicateLockAcquire(&tag);
2550 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:474
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1920
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:68
Form_pg_index rd_index
Definition: rel.h:131
ItemPointerData t_self
Definition: htup.h:65
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2393
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
Oid rd_id
Definition: rel.h:86
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:496
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4850 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

4851 {
4852  SERIALIZABLEXID *sxid;
4853  SERIALIZABLEXIDTAG sxidtag;
4854 
4855  sxidtag.xid = xid;
4856 
4857  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4858  sxid = (SERIALIZABLEXID *)
4859  hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4860  LWLockRelease(SerializableXactHashLock);
4861 
4862  /* xid will not be found if it wasn't a serializable transaction */
4863  if (sxid == NULL)
4864  return;
4865 
4866  /* Release its locks */
4867  MySerializableXact = sxid->myXact;
4868  MyXactDidWrite = true; /* conservatively assume that we wrote
4869  * something */
4870  ReleasePredicateLocks(isCommit);
4871 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
static HTAB * SerializableXidHash
Definition: predicate.c:384
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3222
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static bool MyXactDidWrite
Definition: predicate.c:410

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

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

1835 {
1836  SERIALIZABLEXIDTAG sxidtag;
1837  SERIALIZABLEXID *sxid;
1838  bool found;
1839 
1840  /*
1841  * If we're not tracking predicate lock data for this transaction, we
1842  * should ignore the request and return quickly.
1843  */
1845  return;
1846 
1847  /* We should have a valid XID and be at the top level. */
1849 
1850  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1851 
1852  /* This should only be done once per transaction. */
1854 
1855  MySerializableXact->topXid = xid;
1856 
1857  sxidtag.xid = xid;
1859  &sxidtag,
1860  HASH_ENTER, &found);
1861  Assert(!found);
1862 
1863  /* Initialize the structure. */
1864  sxid->myXact = MySerializableXact;
1865  LWLockRelease(SerializableXactHashLock);
1866 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
static HTAB * SerializableXidHash
Definition: predicate.c:384
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit)

Definition at line 3222 of file predicate.c.

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

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

3223 {
3224  bool needToClear;
3225  RWConflict conflict,
3226  nextConflict,
3227  possibleUnsafeConflict;
3228  SERIALIZABLEXACT *roXact;
3229 
3230  /*
3231  * We can't trust XactReadOnly here, because a transaction which started
3232  * as READ WRITE can show as READ ONLY later, e.g., within
3233  * subtransactions. We want to flag a transaction as READ ONLY if it
3234  * commits without writing so that de facto READ ONLY transactions get the
3235  * benefit of some RO optimizations, so we will use this local variable to
3236  * get some cleanup logic right which is based on whether the transaction
3237  * was declared READ ONLY at the top level.
3238  */
3239  bool topLevelIsDeclaredReadOnly;
3240 
3242  {
3243  Assert(LocalPredicateLockHash == NULL);
3244  return;
3245  }
3246 
3247  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3248 
3249  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3250  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3253 
3254  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3256 
3257  /* We'd better not already be on the cleanup list. */
3259 
3260  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3261 
3262  /*
3263  * We don't hold XidGenLock lock here, assuming that TransactionId is
3264  * atomic!
3265  *
3266  * If this value is changing, we don't care that much whether we get the
3267  * old or new value -- it is just used to determine how far
3268  * GlobalSerializableXmin must advance before this transaction can be
3269  * fully cleaned up. The worst that could happen is we wait for one more
3270  * transaction to complete before freeing some RAM; correctness of visible
3271  * behavior is not affected.
3272  */
3274 
3275  /*
3276  * If it's not a commit it's a rollback, and we can clear our locks
3277  * immediately.
3278  */
3279  if (isCommit)
3280  {
3283  /* Recognize implicit read-only transaction (commit without write). */
3284  if (!MyXactDidWrite)
3286  }
3287  else
3288  {
3289  /*
3290  * The DOOMED flag indicates that we intend to roll back this
3291  * transaction and so it should not cause serialization failures for
3292  * other transactions that conflict with it. Note that this flag might
3293  * already be set, if another backend marked this transaction for
3294  * abort.
3295  *
3296  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3297  * has been called, and so the SerializableXact is eligible for
3298  * cleanup. This means it should not be considered when calculating
3299  * SxactGlobalXmin.
3300  */
3303 
3304  /*
3305  * If the transaction was previously prepared, but is now failing due
3306  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3307  * prepare, clear the prepared flag. This simplifies conflict
3308  * checking.
3309  */
3311  }
3312 
3313  if (!topLevelIsDeclaredReadOnly)
3314  {
3316  if (--(PredXact->WritableSxactCount) == 0)
3317  {
3318  /*
3319  * Release predicate locks and rw-conflicts in for all committed
3320  * transactions. There are no longer any transactions which might
3321  * conflict with the locks and no chance for new transactions to
3322  * overlap. Similarly, existing conflicts in can't cause pivots,
3323  * and any conflicts in which could have completed a dangerous
3324  * structure would already have caused a rollback, so any
3325  * remaining ones must be benign.
3326  */
3328  }
3329  }
3330  else
3331  {
3332  /*
3333  * Read-only transactions: clear the list of transactions that might
3334  * make us unsafe. Note that we use 'inLink' for the iteration as
3335  * opposed to 'outLink' for the r/w xacts.
3336  */
3337  possibleUnsafeConflict = (RWConflict)
3340  offsetof(RWConflictData, inLink));
3341  while (possibleUnsafeConflict)
3342  {
3343  nextConflict = (RWConflict)
3345  &possibleUnsafeConflict->inLink,
3346  offsetof(RWConflictData, inLink));
3347 
3348  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3349  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3350 
3351  ReleaseRWConflict(possibleUnsafeConflict);
3352 
3353  possibleUnsafeConflict = nextConflict;
3354  }
3355  }
3356 
3357  /* Check for conflict out to old committed transactions. */
3358  if (isCommit
3361  {
3362  /*
3363  * we don't know which old committed transaction we conflicted with,
3364  * so be conservative and use FirstNormalSerCommitSeqNo here
3365  */
3369  }
3370 
3371  /*
3372  * Release all outConflicts to committed transactions. If we're rolling
3373  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3374  * previously committed transactions.
3375  */
3376  conflict = (RWConflict)
3379  offsetof(RWConflictData, outLink));
3380  while (conflict)
3381  {
3382  nextConflict = (RWConflict)
3384  &conflict->outLink,
3385  offsetof(RWConflictData, outLink));
3386 
3387  if (isCommit
3389  && SxactIsCommitted(conflict->sxactIn))
3390  {
3395  }
3396 
3397  if (!isCommit
3398  || SxactIsCommitted(conflict->sxactIn)
3400  ReleaseRWConflict(conflict);
3401 
3402  conflict = nextConflict;
3403  }
3404 
3405  /*
3406  * Release all inConflicts from committed and read-only transactions. If
3407  * we're rolling back, clear them all.
3408  */
3409  conflict = (RWConflict)
3412  offsetof(RWConflictData, inLink));
3413  while (conflict)
3414  {
3415  nextConflict = (RWConflict)
3417  &conflict->inLink,
3418  offsetof(RWConflictData, inLink));
3419 
3420  if (!isCommit
3421  || SxactIsCommitted(conflict->sxactOut)
3422  || SxactIsReadOnly(conflict->sxactOut))
3423  ReleaseRWConflict(conflict);
3424 
3425  conflict = nextConflict;
3426  }
3427 
3428  if (!topLevelIsDeclaredReadOnly)
3429  {
3430  /*
3431  * Remove ourselves from the list of possible conflicts for concurrent
3432  * READ ONLY transactions, flagging them as unsafe if we have a
3433  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3434  * up if they are known safe or known unsafe.
3435  */
3436  possibleUnsafeConflict = (RWConflict)
3439  offsetof(RWConflictData, outLink));
3440  while (possibleUnsafeConflict)
3441  {
3442  nextConflict = (RWConflict)
3444  &possibleUnsafeConflict->outLink,
3445  offsetof(RWConflictData, outLink));
3446 
3447  roXact = possibleUnsafeConflict->sxactIn;
3448  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3449  Assert(SxactIsReadOnly(roXact));
3450 
3451  /* Mark conflicted if necessary. */
3452  if (isCommit
3453  && MyXactDidWrite
3456  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3457  {
3458  /*
3459  * This releases possibleUnsafeConflict (as well as all other
3460  * possible conflicts for roXact)
3461  */
3462  FlagSxactUnsafe(roXact);
3463  }
3464  else
3465  {
3466  ReleaseRWConflict(possibleUnsafeConflict);
3467 
3468  /*
3469  * If we were the last possible conflict, flag it safe. The
3470  * transaction can now safely release its predicate locks (but
3471  * that transaction's backend has to do that itself).
3472  */
3473  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3474  roXact->flags |= SXACT_FLAG_RO_SAFE;
3475  }
3476 
3477  /*
3478  * Wake up the process for a waiting DEFERRABLE transaction if we
3479  * now know it's either safe or conflicted.
3480  */
3481  if (SxactIsDeferrableWaiting(roXact) &&
3482  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3483  ProcSendSignal(roXact->pid);
3484 
3485  possibleUnsafeConflict = nextConflict;
3486  }
3487  }
3488 
3489  /*
3490  * Check whether it's time to clean up old transactions. This can only be
3491  * done when the last serializable transaction with the oldest xmin among
3492  * serializable transactions completes. We then find the "new oldest"
3493  * xmin and purge any transactions which finished before this transaction
3494  * was launched.
3495  */
3496  needToClear = false;
3498  {
3500  if (--(PredXact->SxactGlobalXminCount) == 0)
3501  {
3503  needToClear = true;
3504  }
3505  }
3506 
3507  LWLockRelease(SerializableXactHashLock);
3508 
3509  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3510 
3511  /* Add this to the list of transactions to check for later cleanup. */
3512  if (isCommit)
3515 
3516  if (!isCommit)
3518 
3519  LWLockRelease(SerializableFinishedListLock);
3520 
3521  if (needToClear)
3523 
3525  MyXactDidWrite = false;
3526 
3527  /* Delete per-transaction lock table */
3528  if (LocalPredicateLockHash != NULL)
3529  {
3531  LocalPredicateLockHash = NULL;
3532  }
3533 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:409
TransactionId finishedBefore
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:814
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static PredXactList PredXact
Definition: predicate.c:372
TransactionId SxactGlobalXmin
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3540
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:724
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:256
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:732
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1786
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define SxactIsRolledBack(sxact)
Definition: predicate.c:268
SHM_QUEUE possibleUnsafeConflicts
#define SXACT_FLAG_RO_SAFE
#define InvalidSerializableXact
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_PREPARED
SerCommitSeqNo lastCommitBeforeSnapshot
#define SxactIsROSafe(sxact)
Definition: predicate.c:280
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:272
union SERIALIZABLEXACT::@110 SeqNo
SerCommitSeqNo commitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
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:278
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3697
#define Assert(condition)
Definition: c.h:699
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:279
#define SXACT_FLAG_ROLLED_BACK
SerCommitSeqNo prepareSeqNo
static HTAB * LocalPredicateLockHash
Definition: predicate.c:402
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define IsolationIsSerializable()
Definition: xact.h:51
#define SXACT_FLAG_READ_ONLY
static bool MyXactDidWrite
Definition: predicate.c:410
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:281
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:387
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3172
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:622
SERIALIZABLEXACT * sxactOut

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1630 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1633 {
1635 
1636  /*
1637  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1638  * import snapshots, since there's no way to wait for a safe snapshot when
1639  * we're using the snap we're told to. (XXX instead of throwing an error,
1640  * we could just ignore the XactDeferrable flag?)
1641  */
1643  ereport(ERROR,
1644  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1645  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1646 
1647  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1648  sourcepid);
1649 }
bool XactDeferrable
Definition: xact.c:79
int errcode(int sqlerrcode)
Definition: elog.c:575
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1661
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:76
#define Assert(condition)
Definition: c.h:699
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:51

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3044 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3045 {
3046  DropAllPredicateLocksFromTable(relation, true);
3047 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2848

Variable Documentation

◆ max_predicate_locks_per_page

int max_predicate_locks_per_page

Definition at line 361 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

int max_predicate_locks_per_relation

Definition at line 360 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

int max_predicate_locks_per_xact

Definition at line 359 of file predicate.c.

Referenced by GetSerializableTransactionSnapshotInt(), and MaxPredicateChildLocks().