PostgreSQL Source Code git master
predicate.h File Reference
#include "storage/itemptr.h"
#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.

Typedefs

typedef void * SerializableXactHandle
 

Functions

void PredicateLockShmemInit (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 tuple_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

PGDLLIMPORT int max_predicate_locks_per_xact
 
PGDLLIMPORT int max_predicate_locks_per_relation
 
PGDLLIMPORT int max_predicate_locks_per_page
 

Typedef Documentation

◆ SerializableXactHandle

typedef void* SerializableXactHandle

Definition at line 34 of file predicate.h.

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )

Definition at line 4780 of file predicate.c.

4781{
4782 SERIALIZABLEXACT *sxact;
4784 TwoPhasePredicateXactRecord *xactRecord;
4785 TwoPhasePredicateLockRecord *lockRecord;
4786 dlist_iter iter;
4787
4788 sxact = MySerializableXact;
4789 xactRecord = &(record.data.xactRecord);
4790 lockRecord = &(record.data.lockRecord);
4791
4793 return;
4794
4795 /* Generate an xact record for our SERIALIZABLEXACT */
4797 xactRecord->xmin = MySerializableXact->xmin;
4798 xactRecord->flags = MySerializableXact->flags;
4799
4800 /*
4801 * Note that we don't include the list of conflicts in our out in the
4802 * statefile, because new conflicts can be added even after the
4803 * transaction prepares. We'll just make a conservative assumption during
4804 * recovery instead.
4805 */
4806
4808 &record, sizeof(record));
4809
4810 /*
4811 * Generate a lock record for each lock.
4812 *
4813 * To do this, we need to walk the predicate lock list in our sxact rather
4814 * than using the local predicate lock table because the latter is not
4815 * guaranteed to be accurate.
4816 */
4817 LWLockAcquire(SerializablePredicateListLock, LW_SHARED);
4818
4819 /*
4820 * No need to take sxact->perXactPredicateListLock in parallel mode
4821 * because there cannot be any parallel workers running while we are
4822 * preparing a transaction.
4823 */
4825
4826 dlist_foreach(iter, &sxact->predicateLocks)
4827 {
4828 PREDICATELOCK *predlock =
4829 dlist_container(PREDICATELOCK, xactLink, iter.cur);
4830
4832 lockRecord->target = predlock->tag.myTarget->tag;
4833
4835 &record, sizeof(record));
4836 }
4837
4838 LWLockRelease(SerializablePredicateListLock);
4839}
bool ParallelContextActive(void)
Definition: parallel.c:1020
#define Assert(condition)
Definition: c.h:815
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
#define IsParallelWorker()
Definition: parallel.h:60
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:115
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:421
@ TWOPHASEPREDICATERECORD_XACT
@ TWOPHASEPREDICATERECORD_LOCK
#define InvalidSerializableXact
PREDICATELOCKTARGET * myTarget
PREDICATELOCKTARGETTAG tag
PREDICATELOCKTAG tag
PREDICATELOCKTARGETTAG target
TwoPhasePredicateRecordType type
TwoPhasePredicateLockRecord lockRecord
TwoPhasePredicateXactRecord xactRecord
union TwoPhasePredicateRecord::@123 data
dlist_node * cur
Definition: ilist.h:179
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1280
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28

References Assert, dlist_iter::cur, TwoPhasePredicateRecord::data, dlist_container, dlist_foreach, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, IsParallelWorker, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, ParallelContextActive(), SERIALIZABLEXACT::predicateLocks, RegisterTwoPhaseRecord(), PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, TwoPhasePredicateLockRecord::target, TWOPHASE_RM_PREDICATELOCK_ID, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

Referenced by PrepareTransaction().

◆ AttachSerializableXact()

void AttachSerializableXact ( SerializableXactHandle  handle)

Definition at line 5045 of file predicate.c.

5046{
5047
5049
5053}
static void CreateLocalPredicateLockHash(void)
Definition: predicate.c:1930

References Assert, CreateLocalPredicateLockHash(), InvalidSerializableXact, and MySerializableXact.

Referenced by ParallelWorkerMain().

◆ CheckForSerializableConflictIn()

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

Definition at line 4326 of file predicate.c.

4327{
4328 PREDICATELOCKTARGETTAG targettag;
4329
4330 if (!SerializationNeededForWrite(relation))
4331 return;
4332
4333 /* Check if someone else has already decided that we need to die */
4335 ereport(ERROR,
4337 errmsg("could not serialize access due to read/write dependencies among transactions"),
4338 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4339 errhint("The transaction might succeed if retried.")));
4340
4341 /*
4342 * We're doing a write which might cause rw-conflicts now or later.
4343 * Memorize that fact.
4344 */
4345 MyXactDidWrite = true;
4346
4347 /*
4348 * It is important that we check for locks from the finest granularity to
4349 * the coarsest granularity, so that granularity promotion doesn't cause
4350 * us to miss a lock. The new (coarser) lock will be acquired before the
4351 * old (finer) locks are released.
4352 *
4353 * It is not possible to take and hold a lock across the checks for all
4354 * granularities because each target could be in a separate partition.
4355 */
4356 if (tid != NULL)
4357 {
4359 relation->rd_locator.dbOid,
4360 relation->rd_id,
4363 CheckTargetForConflictsIn(&targettag);
4364 }
4365
4366 if (blkno != InvalidBlockNumber)
4367 {
4369 relation->rd_locator.dbOid,
4370 relation->rd_id,
4371 blkno);
4372 CheckTargetForConflictsIn(&targettag);
4373 }
4374
4376 relation->rd_locator.dbOid,
4377 relation->rd_id);
4378 CheckTargetForConflictsIn(&targettag);
4379}
#define InvalidBlockNumber
Definition: block.h:33
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:76
static bool MyXactDidWrite
Definition: predicate.c:422
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:560
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4156
#define SxactIsDoomed(sxact)
Definition: predicate.c:280
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
Oid rd_id
Definition: rel.h:113
RelFileLocator rd_locator
Definition: rel.h:57

References CheckTargetForConflictsIn(), RelFileLocator::dbOid, ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errdetail_internal(), errhint(), errmsg(), ERROR, InvalidBlockNumber, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), MySerializableXact, MyXactDidWrite, RelationData::rd_id, RelationData::rd_locator, 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().

◆ CheckForSerializableConflictOut()

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

Definition at line 4013 of file predicate.c.

4014{
4015 SERIALIZABLEXIDTAG sxidtag;
4016 SERIALIZABLEXID *sxid;
4017 SERIALIZABLEXACT *sxact;
4018
4019 if (!SerializationNeededForRead(relation, snapshot))
4020 return;
4021
4022 /* Check if someone else has already decided that we need to die */
4024 {
4025 ereport(ERROR,
4027 errmsg("could not serialize access due to read/write dependencies among transactions"),
4028 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4029 errhint("The transaction might succeed if retried.")));
4030 }
4032
4034 return;
4035
4036 /*
4037 * Find sxact or summarized info for the top level xid.
4038 */
4039 sxidtag.xid = xid;
4040 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4041 sxid = (SERIALIZABLEXID *)
4042 hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4043 if (!sxid)
4044 {
4045 /*
4046 * Transaction not found in "normal" SSI structures. Check whether it
4047 * got pushed out to SLRU storage for "old committed" transactions.
4048 */
4049 SerCommitSeqNo conflictCommitSeqNo;
4050
4051 conflictCommitSeqNo = SerialGetMinConflictCommitSeqNo(xid);
4052 if (conflictCommitSeqNo != 0)
4053 {
4054 if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4056 || conflictCommitSeqNo
4058 ereport(ERROR,
4060 errmsg("could not serialize access due to read/write dependencies among transactions"),
4061 errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4062 errhint("The transaction might succeed if retried.")));
4063
4066 ereport(ERROR,
4068 errmsg("could not serialize access due to read/write dependencies among transactions"),
4069 errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4070 errhint("The transaction might succeed if retried.")));
4071
4073 }
4074
4075 /* It's not serializable or otherwise not important. */
4076 LWLockRelease(SerializableXactHashLock);
4077 return;
4078 }
4079 sxact = sxid->myXact;
4080 Assert(TransactionIdEquals(sxact->topXid, xid));
4081 if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4082 {
4083 /* Can't conflict with ourself or a transaction that will roll back. */
4084 LWLockRelease(SerializableXactHashLock);
4085 return;
4086 }
4087
4088 /*
4089 * We have a conflict out to a transaction which has a conflict out to a
4090 * summarized transaction. That summarized transaction must have
4091 * committed first, and we can't tell when it committed in relation to our
4092 * snapshot acquisition, so something needs to be canceled.
4093 */
4094 if (SxactHasSummaryConflictOut(sxact))
4095 {
4096 if (!SxactIsPrepared(sxact))
4097 {
4098 sxact->flags |= SXACT_FLAG_DOOMED;
4099 LWLockRelease(SerializableXactHashLock);
4100 return;
4101 }
4102 else
4103 {
4104 LWLockRelease(SerializableXactHashLock);
4105 ereport(ERROR,
4107 errmsg("could not serialize access due to read/write dependencies among transactions"),
4108 errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4109 errhint("The transaction might succeed if retried.")));
4110 }
4111 }
4112
4113 /*
4114 * If this is a read-only transaction and the writing transaction has
4115 * committed, and it doesn't have a rw-conflict to a transaction which
4116 * committed before it, no conflict.
4117 */
4119 && SxactIsCommitted(sxact)
4121 && (!SxactHasConflictOut(sxact)
4123 {
4124 /* Read-only transaction will appear to run first. No conflict. */
4125 LWLockRelease(SerializableXactHashLock);
4126 return;
4127 }
4128
4129 if (!XidIsConcurrent(xid))
4130 {
4131 /* This write was already in our snapshot; no conflict. */
4132 LWLockRelease(SerializableXactHashLock);
4133 return;
4134 }
4135
4137 {
4138 /* We don't want duplicate conflict records in the list. */
4139 LWLockRelease(SerializableXactHashLock);
4140 return;
4141 }
4142
4143 /*
4144 * Flag the conflict. But first, if this conflict creates a dangerous
4145 * structure, ereport an error.
4146 */
4148 LWLockRelease(SerializableXactHashLock);
4149}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_FIND
Definition: hsearch.h:113
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
@ LW_EXCLUSIVE
Definition: lwlock.h:114
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:610
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:516
#define SxactIsCommitted(sxact)
Definition: predicate.c:277
#define SxactIsReadOnly(sxact)
Definition: predicate.c:281
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:282
#define SxactHasConflictOut(sxact)
Definition: predicate.c:289
#define SxactIsPrepared(sxact)
Definition: predicate.c:278
static HTAB * SerializableXidHash
Definition: predicate.c:396
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4491
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:949
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3962
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:283
#define InvalidSerCommitSeqNo
#define SXACT_FLAG_DOOMED
uint64 SerCommitSeqNo
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
SerCommitSeqNo lastCommitBeforeSnapshot
SerCommitSeqNo earliestOutConflictCommit
union SERIALIZABLEXACT::@122 SeqNo
SERIALIZABLEXACT * myXact
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:440

References Assert, dlist_is_empty(), SERIALIZABLEXACT::earliestOutConflictCommit, ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errdetail_internal(), errhint(), errmsg(), ERROR, FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, SERIALIZABLEXID::myXact, RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerialGetMinConflictCommitSeqNo(), SerializableXidHash, SerializationNeededForRead(), 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().

◆ CheckForSerializableConflictOutNeeded()

bool CheckForSerializableConflictOutNeeded ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 3981 of file predicate.c.

3982{
3983 if (!SerializationNeededForRead(relation, snapshot))
3984 return false;
3985
3986 /* Check if someone else has already decided that we need to die */
3988 {
3989 ereport(ERROR,
3991 errmsg("could not serialize access due to read/write dependencies among transactions"),
3992 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3993 errhint("The transaction might succeed if retried.")));
3994 }
3995
3996 return true;
3997}

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

Referenced by heap_prepare_pagescan(), and HeapCheckForSerializableConflictOut().

◆ CheckPointPredicate()

void CheckPointPredicate ( void  )

Definition at line 1041 of file predicate.c.

1042{
1043 int64 truncateCutoffPage;
1044
1045 LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
1046
1047 /* Exit quickly if the SLRU is currently not in use. */
1048 if (serialControl->headPage < 0)
1049 {
1050 LWLockRelease(SerialControlLock);
1051 return;
1052 }
1053
1055 {
1056 int64 tailPage;
1057
1058 tailPage = SerialPage(serialControl->tailXid);
1059
1060 /*
1061 * It is possible for the tailXid to be ahead of the headXid. This
1062 * occurs if we checkpoint while there are in-progress serializable
1063 * transaction(s) advancing the tail but we are yet to summarize the
1064 * transactions. In this case, we cutoff up to the headPage and the
1065 * next summary will advance the headXid.
1066 */
1068 {
1069 /* We can truncate the SLRU up to the page containing tailXid */
1070 truncateCutoffPage = tailPage;
1071 }
1072 else
1073 truncateCutoffPage = serialControl->headPage;
1074 }
1075 else
1076 {
1077 /*----------
1078 * The SLRU is no longer needed. Truncate to head before we set head
1079 * invalid.
1080 *
1081 * XXX: It's possible that the SLRU is not needed again until XID
1082 * wrap-around has happened, so that the segment containing headPage
1083 * that we leave behind will appear to be new again. In that case it
1084 * won't be removed until XID horizon advances enough to make it
1085 * current again.
1086 *
1087 * XXX: This should happen in vac_truncate_clog(), not in checkpoints.
1088 * Consider this scenario, starting from a system with no in-progress
1089 * transactions and VACUUM FREEZE having maximized oldestXact:
1090 * - Start a SERIALIZABLE transaction.
1091 * - Start, finish, and summarize a SERIALIZABLE transaction, creating
1092 * one SLRU page.
1093 * - Consume XIDs to reach xidStopLimit.
1094 * - Finish all transactions. Due to the long-running SERIALIZABLE
1095 * transaction, earlier checkpoints did not touch headPage. The
1096 * next checkpoint will change it, but that checkpoint happens after
1097 * the end of the scenario.
1098 * - VACUUM to advance XID limits.
1099 * - Consume ~2M XIDs, crossing the former xidWrapLimit.
1100 * - Start, finish, and summarize a SERIALIZABLE transaction.
1101 * SerialAdd() declines to create the targetPage, because headPage
1102 * is not regarded as in the past relative to that targetPage. The
1103 * transaction instigating the summarize fails in
1104 * SimpleLruReadPage().
1105 */
1106 truncateCutoffPage = serialControl->headPage;
1107 serialControl->headPage = -1;
1108 }
1109
1110 LWLockRelease(SerialControlLock);
1111
1112 /*
1113 * Truncate away pages that are no longer required. Note that no
1114 * additional locking is required, because this is only called as part of
1115 * a checkpoint, and the validity limits have already been determined.
1116 */
1117 SimpleLruTruncate(SerialSlruCtl, truncateCutoffPage);
1118
1119 /*
1120 * Write dirty SLRU pages to disk
1121 *
1122 * This is not actually necessary from a correctness point of view. We do
1123 * it merely as a debugging aid.
1124 *
1125 * We're doing this after the truncation to avoid writing pages right
1126 * before deleting the file in which they sit, which would be completely
1127 * pointless.
1128 */
1130}
int64_t int64
Definition: c.h:485
#define SerialPage(xid)
Definition: predicate.c:343
static SerialControl serialControl
Definition: predicate.c:354
static bool SerialPagePrecedesLogically(int64 page1, int64 page2)
Definition: predicate.c:731
#define SerialSlruCtl
Definition: predicate.c:326
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1322
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
Definition: slru.c:1408
TransactionId tailXid
Definition: predicate.c:349

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

Referenced by CheckPointGuts().

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)

Definition at line 4409 of file predicate.c.

4410{
4411 HASH_SEQ_STATUS seqstat;
4412 PREDICATELOCKTARGET *target;
4413 Oid dbId;
4414 Oid heapId;
4415 int i;
4416
4417 /*
4418 * Bail out quickly if there are no serializable transactions running.
4419 * It's safe to check this without taking locks because the caller is
4420 * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4421 * would matter here can be acquired while that is held.
4422 */
4424 return;
4425
4426 if (!SerializationNeededForWrite(relation))
4427 return;
4428
4429 /*
4430 * We're doing a write which might cause rw-conflicts now or later.
4431 * Memorize that fact.
4432 */
4433 MyXactDidWrite = true;
4434
4435 Assert(relation->rd_index == NULL); /* not an index relation */
4436
4437 dbId = relation->rd_locator.dbOid;
4438 heapId = relation->rd_id;
4439
4440 LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
4441 for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4443 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4444
4445 /* Scan through target list */
4447
4448 while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4449 {
4450 dlist_mutable_iter iter;
4451
4452 /*
4453 * Check whether this is a target which needs attention.
4454 */
4455 if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4456 continue; /* wrong relation id */
4457 if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4458 continue; /* wrong database id */
4459
4460 /*
4461 * Loop through locks for this target and flag conflicts.
4462 */
4463 dlist_foreach_modify(iter, &target->predicateLocks)
4464 {
4465 PREDICATELOCK *predlock =
4466 dlist_container(PREDICATELOCK, targetLink, iter.cur);
4467
4468 if (predlock->tag.myXact != MySerializableXact
4470 {
4472 }
4473 }
4474 }
4475
4476 /* Release locks in reverse order */
4477 LWLockRelease(SerializableXactHashLock);
4478 for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4480 LWLockRelease(SerializablePredicateListLock);
4481}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
int i
Definition: isn.c:72
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:101
unsigned int Oid
Definition: postgres_ext.h:32
static PredXactList PredXact
Definition: predicate.c:384
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:261
static HTAB * PredicateLockTargetHash
Definition: predicate.c:397
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
SERIALIZABLEXACT * myXact
TransactionId SxactGlobalXmin
Form_pg_index rd_index
Definition: rel.h:192
dlist_node * cur
Definition: ilist.h:200

References Assert, dlist_mutable_iter::cur, RelFileLocator::dbOid, dlist_container, dlist_foreach_modify, FlagRWConflict(), GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_RELATION, hash_seq_init(), hash_seq_search(), i, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myXact, MyXactDidWrite, NUM_PREDICATELOCK_PARTITIONS, PredicateLockHashPartitionLockByIndex, PREDICATELOCKTARGET::predicateLocks, PredicateLockTargetHash, PredXact, RelationData::rd_id, RelationData::rd_index, RelationData::rd_locator, RWConflictExists(), SerializationNeededForWrite(), PredXactListData::SxactGlobalXmin, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, and TransactionIdIsValid.

Referenced by ExecuteTruncateGuts(), and heap_drop_with_catalog().

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1672 of file predicate.c.

1673{
1675
1676 /*
1677 * Can't use serializable mode while recovery is still active, as it is,
1678 * for example, on a hot standby. We could get here despite the check in
1679 * check_transaction_isolation() if default_transaction_isolation is set
1680 * to serializable, so phrase the hint accordingly.
1681 */
1682 if (RecoveryInProgress())
1683 ereport(ERROR,
1684 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1685 errmsg("cannot use serializable mode in a hot standby"),
1686 errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1687 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1688
1689 /*
1690 * A special optimization is available for SERIALIZABLE READ ONLY
1691 * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1692 * thereby avoid all SSI overhead once it's running.
1693 */
1695 return GetSafeSnapshot(snapshot);
1696
1698 NULL, InvalidPid);
1699}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define InvalidPid
Definition: miscadmin.h:32
static Snapshot GetSafeSnapshot(Snapshot origSnapshot)
Definition: predicate.c:1548
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1754
bool XactDeferrable
Definition: xact.c:84
bool XactReadOnly
Definition: xact.c:81
#define IsolationIsSerializable()
Definition: xact.h:52
bool RecoveryInProgress(void)
Definition: xlog.c:6334

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

Referenced by GetTransactionSnapshot().

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

Definition at line 1998 of file predicate.c.

1999{
2000 PREDICATELOCKTARGETTAG targettag;
2001 uint32 targettaghash;
2002 LWLock *partitionLock;
2003 PREDICATELOCKTARGET *target;
2004
2006 relation->rd_locator.dbOid,
2007 relation->rd_id,
2008 blkno);
2009
2010 targettaghash = PredicateLockTargetTagHashCode(&targettag);
2011 partitionLock = PredicateLockHashPartitionLock(targettaghash);
2012 LWLockAcquire(partitionLock, LW_SHARED);
2013 target = (PREDICATELOCKTARGET *)
2015 &targettag, targettaghash,
2016 HASH_FIND, NULL);
2017 LWLockRelease(partitionLock);
2018
2019 return (target != NULL);
2020}
uint32_t uint32
Definition: c.h:488
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:968
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:303
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:258
Definition: lwlock.h:42

References RelFileLocator::dbOid, HASH_FIND, hash_search_with_hash_value(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PredicateLockHashPartitionLock, PredicateLockTargetHash, PredicateLockTargetTagHashCode, RelationData::rd_id, RelationData::rd_locator, and SET_PREDICATELOCKTARGETTAG_PAGE.

◆ PostPrepare_PredicateLocks()

◆ PreCommit_CheckForSerializationFailure()

void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4693 of file predicate.c.

4694{
4695 dlist_iter near_iter;
4696
4698 return;
4699
4701
4702 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4703
4704 /*
4705 * Check if someone else has already decided that we need to die. Since
4706 * we set our own DOOMED flag when partially releasing, ignore in that
4707 * case.
4708 */
4711 {
4712 LWLockRelease(SerializableXactHashLock);
4713 ereport(ERROR,
4715 errmsg("could not serialize access due to read/write dependencies among transactions"),
4716 errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4717 errhint("The transaction might succeed if retried.")));
4718 }
4719
4721 {
4722 RWConflict nearConflict =
4723 dlist_container(RWConflictData, inLink, near_iter.cur);
4724
4725 if (!SxactIsCommitted(nearConflict->sxactOut)
4726 && !SxactIsDoomed(nearConflict->sxactOut))
4727 {
4728 dlist_iter far_iter;
4729
4730 dlist_foreach(far_iter, &nearConflict->sxactOut->inConflicts)
4731 {
4732 RWConflict farConflict =
4733 dlist_container(RWConflictData, inLink, far_iter.cur);
4734
4735 if (farConflict->sxactOut == MySerializableXact
4736 || (!SxactIsCommitted(farConflict->sxactOut)
4737 && !SxactIsReadOnly(farConflict->sxactOut)
4738 && !SxactIsDoomed(farConflict->sxactOut)))
4739 {
4740 /*
4741 * Normally, we kill the pivot transaction to make sure we
4742 * make progress if the failing transaction is retried.
4743 * However, we can't kill it if it's already prepared, so
4744 * in that case we commit suicide instead.
4745 */
4746 if (SxactIsPrepared(nearConflict->sxactOut))
4747 {
4748 LWLockRelease(SerializableXactHashLock);
4749 ereport(ERROR,
4751 errmsg("could not serialize access due to read/write dependencies among transactions"),
4752 errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4753 errhint("The transaction might succeed if retried.")));
4754 }
4755 nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4756 break;
4757 }
4758 }
4759 }
4760 }
4761
4764
4765 LWLockRelease(SerializableXactHashLock);
4766}
#define SxactIsPartiallyReleased(sxact)
Definition: predicate.c:293
#define SXACT_FLAG_PREPARED
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * sxactOut
SerCommitSeqNo prepareSeqNo

References Assert, dlist_iter::cur, dlist_container, dlist_foreach, ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errdetail_internal(), errhint(), errmsg(), ERROR, SERIALIZABLEXACT::flags, SERIALIZABLEXACT::inConflicts, InvalidSerializableXact, IsolationIsSerializable, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, PredXact, SERIALIZABLEXACT::prepareSeqNo, SXACT_FLAG_DOOMED, SXACT_FLAG_PREPARED, SxactIsCommitted, SxactIsDoomed, SxactIsPartiallyReleased, SxactIsPrepared, SxactIsReadOnly, and RWConflictData::sxactOut.

Referenced by CommitTransaction(), and PrepareTransaction().

◆ predicatelock_twophase_recover()

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

Definition at line 4899 of file predicate.c.

4901{
4903
4905
4906 record = (TwoPhasePredicateRecord *) recdata;
4907
4909 (record->type == TWOPHASEPREDICATERECORD_LOCK));
4910
4911 if (record->type == TWOPHASEPREDICATERECORD_XACT)
4912 {
4913 /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4914 TwoPhasePredicateXactRecord *xactRecord;
4915 SERIALIZABLEXACT *sxact;
4916 SERIALIZABLEXID *sxid;
4917 SERIALIZABLEXIDTAG sxidtag;
4918 bool found;
4919
4920 xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4921
4922 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4923 sxact = CreatePredXact();
4924 if (!sxact)
4925 ereport(ERROR,
4926 (errcode(ERRCODE_OUT_OF_MEMORY),
4927 errmsg("out of shared memory")));
4928
4929 /* vxid for a prepared xact is INVALID_PROC_NUMBER/xid; no pid */
4932 sxact->pid = 0;
4934
4935 /* a prepared xact hasn't committed yet */
4939
4941
4942 /*
4943 * Don't need to track this; no transactions running at the time the
4944 * recovered xact started are still active, except possibly other
4945 * prepared xacts and we don't care whether those are RO_SAFE or not.
4946 */
4948
4949 dlist_init(&(sxact->predicateLocks));
4951
4952 sxact->topXid = xid;
4953 sxact->xmin = xactRecord->xmin;
4954 sxact->flags = xactRecord->flags;
4955 Assert(SxactIsPrepared(sxact));
4956 if (!SxactIsReadOnly(sxact))
4957 {
4961 }
4962
4963 /*
4964 * We don't know whether the transaction had any conflicts or not, so
4965 * we'll conservatively assume that it had both a conflict in and a
4966 * conflict out, and represent that with the summary conflict flags.
4967 */
4968 dlist_init(&(sxact->outConflicts));
4969 dlist_init(&(sxact->inConflicts));
4972
4973 /* Register the transaction's xid */
4974 sxidtag.xid = xid;
4976 &sxidtag,
4977 HASH_ENTER, &found);
4978 Assert(sxid != NULL);
4979 Assert(!found);
4980 sxid->myXact = (SERIALIZABLEXACT *) sxact;
4981
4982 /*
4983 * Update global xmin. Note that this is a special case compared to
4984 * registering a normal transaction, because the global xmin might go
4985 * backwards. That's OK, because until recovery is over we're not
4986 * going to complete any transactions or create any non-prepared
4987 * transactions, so there's no danger of throwing away.
4988 */
4991 {
4992 PredXact->SxactGlobalXmin = sxact->xmin;
4995 }
4997 {
5000 }
5001
5002 LWLockRelease(SerializableXactHashLock);
5003 }
5004 else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5005 {
5006 /* Lock record. Recreate the PREDICATELOCK */
5007 TwoPhasePredicateLockRecord *lockRecord;
5008 SERIALIZABLEXID *sxid;
5009 SERIALIZABLEXACT *sxact;
5010 SERIALIZABLEXIDTAG sxidtag;
5011 uint32 targettaghash;
5012
5013 lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5014 targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5015
5016 LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5017 sxidtag.xid = xid;
5018 sxid = (SERIALIZABLEXID *)
5019 hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
5020 LWLockRelease(SerializableXactHashLock);
5021
5022 Assert(sxid != NULL);
5023 sxact = sxid->myXact;
5025
5026 CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5027 }
5028}
uint32 LocalTransactionId
Definition: c.h:611
int MaxBackends
Definition: globals.c:145
@ HASH_ENTER
Definition: hsearch.h:114
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
static void dlist_node_init(dlist_node *node)
Definition: ilist.h:325
const void size_t len
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2443
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:582
static void SerialSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:990
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
#define RecoverySerCommitSeqNo
VirtualTransactionId vxid
dlist_head possibleUnsafeConflicts
SerCommitSeqNo commitSeqNo
TransactionId finishedBefore
LocalTransactionId localTransactionId
Definition: lock.h:62
ProcNumber procNumber
Definition: lock.h:61
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:314
#define InvalidTransactionId
Definition: transam.h:31
int max_prepared_xacts
Definition: twophase.c:115

References Assert, SERIALIZABLEXACT::commitSeqNo, CreatePredicateLock(), CreatePredXact(), TwoPhasePredicateRecord::data, dlist_init(), dlist_node_init(), ereport, errcode(), errmsg(), ERROR, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, HASH_ENTER, HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, INVALID_PROC_NUMBER, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, len, VirtualTransactionId::localTransactionId, TwoPhasePredicateRecord::lockRecord, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, SERIALIZABLEXID::myXact, SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pgprocno, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXact, SERIALIZABLEXACT::prepareSeqNo, VirtualTransactionId::procNumber, RecoverySerCommitSeqNo, SERIALIZABLEXACT::SeqNo, SerializableXidHash, SerialSetActiveSerXmin(), 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.

◆ PredicateLockPage()

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

Definition at line 2589 of file predicate.c.

2590{
2592
2593 if (!SerializationNeededForRead(relation, snapshot))
2594 return;
2595
2597 relation->rd_locator.dbOid,
2598 relation->rd_id,
2599 blkno);
2601}
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2507

References RelFileLocator::dbOid, PredicateLockAcquire(), RelationData::rd_id, RelationData::rd_locator, SerializationNeededForRead(), and SET_PREDICATELOCKTARGETTAG_PAGE.

Referenced by _bt_readpage(), _hash_first(), _hash_readnext(), collectMatchBitmap(), gistScanPage(), IndexOnlyNext(), moveRightIfItNeeded(), scanPendingInsert(), and startScanEntry().

◆ PredicateLockPageCombine()

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

Definition at line 3219 of file predicate.c.

3221{
3222 /*
3223 * Page combines differ from page splits in that we ought to be able to
3224 * remove the locks on the old page after transferring them to the new
3225 * page, instead of duplicating them. However, because we can't edit other
3226 * backends' local lock tables, removing the old lock would leave them
3227 * with an entry in their LocalPredicateLockHash for a lock they're not
3228 * holding, which isn't acceptable. So we wind up having to do the same
3229 * work as a page split, acquiring a lock on the new page and keeping the
3230 * old page locked too. That can lead to some false positives, but should
3231 * be rare in practice.
3232 */
3233 PredicateLockPageSplit(relation, oldblkno, newblkno);
3234}
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3134

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePage().

◆ PredicateLockPageSplit()

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

Definition at line 3134 of file predicate.c.

3136{
3137 PREDICATELOCKTARGETTAG oldtargettag;
3138 PREDICATELOCKTARGETTAG newtargettag;
3139 bool success;
3140
3141 /*
3142 * Bail out quickly if there are no serializable transactions running.
3143 *
3144 * It's safe to do this check without taking any additional locks. Even if
3145 * a serializable transaction starts concurrently, we know it can't take
3146 * any SIREAD locks on the page being split because the caller is holding
3147 * the associated buffer page lock. Memory reordering isn't an issue; the
3148 * memory barrier in the LWLock acquisition guarantees that this read
3149 * occurs while the buffer page lock is held.
3150 */
3152 return;
3153
3154 if (!PredicateLockingNeededForRelation(relation))
3155 return;
3156
3157 Assert(oldblkno != newblkno);
3158 Assert(BlockNumberIsValid(oldblkno));
3159 Assert(BlockNumberIsValid(newblkno));
3160
3162 relation->rd_locator.dbOid,
3163 relation->rd_id,
3164 oldblkno);
3166 relation->rd_locator.dbOid,
3167 relation->rd_id,
3168 newblkno);
3169
3170 LWLockAcquire(SerializablePredicateListLock, LW_EXCLUSIVE);
3171
3172 /*
3173 * Try copying the locks over to the new page's tag, creating it if
3174 * necessary.
3175 */
3177 newtargettag,
3178 false);
3179
3180 if (!success)
3181 {
3182 /*
3183 * No more predicate lock entries are available. Failure isn't an
3184 * option here, so promote the page lock to a relation lock.
3185 */
3186
3187 /* Get the parent relation lock's lock tag */
3188 success = GetParentPredicateLockTag(&oldtargettag,
3189 &newtargettag);
3190 Assert(success);
3191
3192 /*
3193 * Move the locks to the parent. This shouldn't fail.
3194 *
3195 * Note that here we are removing locks held by other backends,
3196 * leading to a possible inconsistency in their local lock hash table.
3197 * This is OK because we're replacing it with a lock that covers the
3198 * old one.
3199 */
3201 newtargettag,
3202 true);
3203 Assert(success);
3204 }
3205
3206 LWLockRelease(SerializablePredicateListLock);
3207}
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
static bool success
Definition: initdb.c:186
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:498
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:2062
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2720

References Assert, BlockNumberIsValid(), RelFileLocator::dbOid, GetParentPredicateLockTag(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PredicateLockingNeededForRelation(), PredXact, RelationData::rd_id, RelationData::rd_locator, SET_PREDICATELOCKTARGETTAG_PAGE, success, PredXactListData::SxactGlobalXmin, TransactionIdIsValid, and TransferPredicateLocksToNewTarget().

Referenced by _bt_insertonpg(), _hash_splitbucket(), createPostingTree(), ginPlaceToPage(), gistplacetopage(), and PredicateLockPageCombine().

◆ PredicateLockRelation()

void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

◆ PredicateLockShmemInit()

void PredicateLockShmemInit ( void  )

Definition at line 1145 of file predicate.c.

1146{
1147 HASHCTL info;
1148 long max_table_size;
1149 Size requestSize;
1150 bool found;
1151
1152#ifndef EXEC_BACKEND
1154#endif
1155
1156 /*
1157 * Compute size of predicate lock target hashtable. Note these
1158 * calculations must agree with PredicateLockShmemSize!
1159 */
1160 max_table_size = NPREDICATELOCKTARGETENTS();
1161
1162 /*
1163 * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1164 * per-predicate-lock-target information.
1165 */
1166 info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1167 info.entrysize = sizeof(PREDICATELOCKTARGET);
1169
1170 PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1171 max_table_size,
1172 max_table_size,
1173 &info,
1176
1177 /*
1178 * Reserve a dummy entry in the hash table; we use it to make sure there's
1179 * always one entry available when we need to split or combine a page,
1180 * because running out of space there could mean aborting a
1181 * non-serializable transaction.
1182 */
1183 if (!IsUnderPostmaster)
1184 {
1186 HASH_ENTER, &found);
1187 Assert(!found);
1188 }
1189
1190 /* Pre-calculate the hash and partition lock of the scratch entry */
1193
1194 /*
1195 * Allocate hash table for PREDICATELOCK structs. This stores per
1196 * xact-lock-of-a-target information.
1197 */
1198 info.keysize = sizeof(PREDICATELOCKTAG);
1199 info.entrysize = sizeof(PREDICATELOCK);
1200 info.hash = predicatelock_hash;
1202
1203 /* Assume an average of 2 xacts per target */
1204 max_table_size *= 2;
1205
1206 PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1207 max_table_size,
1208 max_table_size,
1209 &info,
1212
1213 /*
1214 * Compute size for serializable transaction hashtable. Note these
1215 * calculations must agree with PredicateLockShmemSize!
1216 */
1217 max_table_size = (MaxBackends + max_prepared_xacts);
1218
1219 /*
1220 * Allocate a list to hold information on transactions participating in
1221 * predicate locking.
1222 *
1223 * Assume an average of 10 predicate locking transactions per backend.
1224 * This allows aggressive cleanup while detail is present before data must
1225 * be summarized for storage in SLRU and the "dummy" transaction.
1226 */
1227 max_table_size *= 10;
1228
1229 PredXact = ShmemInitStruct("PredXactList",
1231 &found);
1232 Assert(found == IsUnderPostmaster);
1233 if (!found)
1234 {
1235 int i;
1236
1245 requestSize = mul_size((Size) max_table_size,
1246 sizeof(SERIALIZABLEXACT));
1247 PredXact->element = ShmemAlloc(requestSize);
1248 /* Add all elements to available list, clean. */
1249 memset(PredXact->element, 0, requestSize);
1250 for (i = 0; i < max_table_size; i++)
1251 {
1255 }
1272 }
1273 /* This never changes, so let's keep a local copy. */
1275
1276 /*
1277 * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1278 * information for serializable transactions which have accessed data.
1279 */
1280 info.keysize = sizeof(SERIALIZABLEXIDTAG);
1281 info.entrysize = sizeof(SERIALIZABLEXID);
1282
1283 SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1284 max_table_size,
1285 max_table_size,
1286 &info,
1289
1290 /*
1291 * Allocate space for tracking rw-conflicts in lists attached to the
1292 * transactions.
1293 *
1294 * Assume an average of 5 conflicts per transaction. Calculations suggest
1295 * that this will prevent resource exhaustion in even the most pessimal
1296 * loads up to max_connections = 200 with all 200 connections pounding the
1297 * database with serializable transactions. Beyond that, there may be
1298 * occasional transactions canceled when trying to flag conflicts. That's
1299 * probably OK.
1300 */
1301 max_table_size *= 5;
1302
1303 RWConflictPool = ShmemInitStruct("RWConflictPool",
1305 &found);
1306 Assert(found == IsUnderPostmaster);
1307 if (!found)
1308 {
1309 int i;
1310
1312 requestSize = mul_size((Size) max_table_size,
1314 RWConflictPool->element = ShmemAlloc(requestSize);
1315 /* Add all elements to available list, clean. */
1316 memset(RWConflictPool->element, 0, requestSize);
1317 for (i = 0; i < max_table_size; i++)
1318 {
1321 }
1322 }
1323
1324 /*
1325 * Create or attach to the header for the list of finished serializable
1326 * transactions.
1327 */
1329 ShmemInitStruct("FinishedSerializableTransactions",
1330 sizeof(dlist_head),
1331 &found);
1332 Assert(found == IsUnderPostmaster);
1333 if (!found)
1335
1336 /*
1337 * Initialize the SLRU storage for old committed serializable
1338 * transactions.
1339 */
1340 SerialInit();
1341}
size_t Size
Definition: c.h:562
bool IsUnderPostmaster
Definition: globals.c:119
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_FUNCTION
Definition: hsearch.h:98
#define HASH_BLOBS
Definition: hsearch.h:97
#define HASH_FIXED_SIZE
Definition: hsearch.h:105
#define HASH_PARTITION
Definition: hsearch.h:92
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:74
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:707
@ LWTRANCHE_PER_XACT_PREDICATE_LIST
Definition: lwlock.h:202
static HTAB * PredicateLockHash
Definition: predicate.c:398
static LWLock * ScratchPartitionLock
Definition: predicate.c:408
static uint32 ScratchTargetTagHash
Definition: predicate.c:407
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1409
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:362
static void SerialInit(void)
Definition: predicate.c:806
static dlist_head * FinishedSerializableTransactions
Definition: predicate.c:399
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:406
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:264
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:390
#define RWConflictDataSize
#define FirstNormalSerCommitSeqNo
struct PREDICATELOCKTAG PREDICATELOCKTAG
#define PredXactListDataSize
#define RWConflictPoolHeaderDataSize
struct SERIALIZABLEXIDTAG SERIALIZABLEXIDTAG
struct PREDICATELOCKTARGET PREDICATELOCKTARGET
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
struct SERIALIZABLEXID SERIALIZABLEXID
#define SXACT_FLAG_COMMITTED
struct PREDICATELOCK PREDICATELOCK
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:327
Size mul_size(Size s1, Size s2)
Definition: shmem.c:505
void * ShmemAlloc(Size size)
Definition: shmem.c:147
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:382
Size keysize
Definition: hsearch.h:75
HashValueFunc hash
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:76
long num_partitions
Definition: hsearch.h:68
SERIALIZABLEXACT * element
SerCommitSeqNo CanPartialClearThrough
SERIALIZABLEXACT * OldCommittedSxact
SerCommitSeqNo HavePartialClearedThrough

References PredXactListData::activeList, Assert, PredXactListData::availableList, RWConflictPoolHeaderData::availableList, PredXactListData::CanPartialClearThrough, SERIALIZABLEXACT::commitSeqNo, CreatePredXact(), dlist_init(), dlist_node_init(), dlist_push_tail(), PredXactListData::element, RWConflictPoolHeaderData::element, HASHCTL::entrysize, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FinishedSerializableTransactions, 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, INVALID_PROC_NUMBER, InvalidTransactionId, IsUnderPostmaster, HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LWLockInitialize(), LWTRANCHE_PER_XACT_PREDICATE_LIST, max_prepared_xacts, MaxBackends, mul_size(), NPREDICATELOCKTARGETENTS, HASHCTL::num_partitions, NUM_PREDICATELOCK_PARTITIONS, OldCommittedSxact, PredXactListData::OldCommittedSxact, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::perXactPredicateListLock, SERIALIZABLEXACT::pgprocno, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, predicatelock_hash(), PredicateLockHash, PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetHash, PredicateLockTargetTagHashCode, PredXact, PredXactListDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPool, RWConflictPoolHeaderDataSize, ScratchPartitionLock, ScratchTargetTag, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SerialInit(), SerializableXidHash, SetInvalidVirtualTransactionId, ShmemAlloc(), ShmemInitHash(), ShmemInitStruct(), SXACT_FLAG_COMMITTED, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SERIALIZABLEXACT::topXid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, SERIALIZABLEXACT::xactLink, and SERIALIZABLEXACT::xmin.

Referenced by CreateOrAttachShmemStructs().

◆ PredicateLockShmemSize()

Size PredicateLockShmemSize ( void  )

Definition at line 1347 of file predicate.c.

1348{
1349 Size size = 0;
1350 long max_table_size;
1351
1352 /* predicate lock target hash table */
1353 max_table_size = NPREDICATELOCKTARGETENTS();
1354 size = add_size(size, hash_estimate_size(max_table_size,
1355 sizeof(PREDICATELOCKTARGET)));
1356
1357 /* predicate lock hash table */
1358 max_table_size *= 2;
1359 size = add_size(size, hash_estimate_size(max_table_size,
1360 sizeof(PREDICATELOCK)));
1361
1362 /*
1363 * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1364 * margin.
1365 */
1366 size = add_size(size, size / 10);
1367
1368 /* transaction list */
1369 max_table_size = MaxBackends + max_prepared_xacts;
1370 max_table_size *= 10;
1372 size = add_size(size, mul_size((Size) max_table_size,
1373 sizeof(SERIALIZABLEXACT)));
1374
1375 /* transaction xid table */
1376 size = add_size(size, hash_estimate_size(max_table_size,
1377 sizeof(SERIALIZABLEXID)));
1378
1379 /* rw-conflict pool */
1380 max_table_size *= 5;
1382 size = add_size(size, mul_size((Size) max_table_size,
1384
1385 /* Head for list of finished serializable transactions. */
1386 size = add_size(size, sizeof(dlist_head));
1387
1388 /* Shared memory structures for SLRU tracking of old committed xids. */
1389 size = add_size(size, sizeof(SerialControlData));
1391
1392 return size;
1393}
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:783
int serializable_buffers
Definition: globals.c:164
Size add_size(Size s1, Size s2)
Definition: shmem.c:488
static pg_noinline void Size size
Definition: slab.c:607
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:199

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

Referenced by CalculateShmemSize().

◆ PredicateLockTID()

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

Definition at line 2611 of file predicate.c.

2613{
2615
2616 if (!SerializationNeededForRead(relation, snapshot))
2617 return;
2618
2619 /*
2620 * Return if this xact wrote it.
2621 */
2622 if (relation->rd_index == NULL)
2623 {
2624 /* If we wrote it; we already have a write lock. */
2626 return;
2627 }
2628
2629 /*
2630 * Do quick-but-not-definitive test for a relation lock first. This will
2631 * never cause a return when the relation is *not* locked, but will
2632 * occasionally let the check continue when there really *is* a relation
2633 * level lock.
2634 */
2636 relation->rd_locator.dbOid,
2637 relation->rd_id);
2638 if (PredicateLockExists(&tag))
2639 return;
2640
2642 relation->rd_locator.dbOid,
2643 relation->rd_id,
2647}
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2035
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:940

References RelFileLocator::dbOid, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), PredicateLockAcquire(), PredicateLockExists(), RelationData::rd_id, RelationData::rd_index, RelationData::rd_locator, SerializationNeededForRead(), SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, and TransactionIdIsCurrentTransactionId().

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

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4872 of file predicate.c.

4873{
4874 SERIALIZABLEXID *sxid;
4875 SERIALIZABLEXIDTAG sxidtag;
4876
4877 sxidtag.xid = xid;
4878
4879 LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4880 sxid = (SERIALIZABLEXID *)
4881 hash_search(SerializableXidHash, &sxidtag, HASH_FIND, NULL);
4882 LWLockRelease(SerializableXactHashLock);
4883
4884 /* xid will not be found if it wasn't a serializable transaction */
4885 if (sxid == NULL)
4886 return;
4887
4888 /* Release its locks */
4889 MySerializableXact = sxid->myXact;
4890 MyXactDidWrite = true; /* conservatively assume that we wrote
4891 * something */
4892 ReleasePredicateLocks(isCommit, false);
4893}
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
Definition: predicate.c:3302

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

Referenced by FinishPreparedTransaction().

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)

Definition at line 1949 of file predicate.c.

1950{
1951 SERIALIZABLEXIDTAG sxidtag;
1952 SERIALIZABLEXID *sxid;
1953 bool found;
1954
1955 /*
1956 * If we're not tracking predicate lock data for this transaction, we
1957 * should ignore the request and return quickly.
1958 */
1960 return;
1961
1962 /* We should have a valid XID and be at the top level. */
1964
1965 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1966
1967 /* This should only be done once per transaction. */
1969
1971
1972 sxidtag.xid = xid;
1974 &sxidtag,
1975 HASH_ENTER, &found);
1976 Assert(!found);
1977
1978 /* Initialize the structure. */
1979 sxid->myXact = MySerializableXact;
1980 LWLockRelease(SerializableXactHashLock);
1981}

References Assert, HASH_ENTER, hash_search(), InvalidSerializableXact, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, SERIALIZABLEXID::myXact, SerializableXidHash, SERIALIZABLEXACT::topXid, TransactionIdIsValid, and SERIALIZABLEXIDTAG::xid.

Referenced by AssignTransactionId().

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)

Definition at line 3302 of file predicate.c.

3303{
3304 bool partiallyReleasing = false;
3305 bool needToClear;
3306 SERIALIZABLEXACT *roXact;
3307 dlist_mutable_iter iter;
3308
3309 /*
3310 * We can't trust XactReadOnly here, because a transaction which started
3311 * as READ WRITE can show as READ ONLY later, e.g., within
3312 * subtransactions. We want to flag a transaction as READ ONLY if it
3313 * commits without writing so that de facto READ ONLY transactions get the
3314 * benefit of some RO optimizations, so we will use this local variable to
3315 * get some cleanup logic right which is based on whether the transaction
3316 * was declared READ ONLY at the top level.
3317 */
3318 bool topLevelIsDeclaredReadOnly;
3319
3320 /* We can't be both committing and releasing early due to RO_SAFE. */
3321 Assert(!(isCommit && isReadOnlySafe));
3322
3323 /* Are we at the end of a transaction, that is, a commit or abort? */
3324 if (!isReadOnlySafe)
3325 {
3326 /*
3327 * Parallel workers mustn't release predicate locks at the end of
3328 * their transaction. The leader will do that at the end of its
3329 * transaction.
3330 */
3331 if (IsParallelWorker())
3332 {
3334 return;
3335 }
3336
3337 /*
3338 * By the time the leader in a parallel query reaches end of
3339 * transaction, it has waited for all workers to exit.
3340 */
3342
3343 /*
3344 * If the leader in a parallel query earlier stashed a partially
3345 * released SERIALIZABLEXACT for final clean-up at end of transaction
3346 * (because workers might still have been accessing it), then it's
3347 * time to restore it.
3348 */
3350 {
3355 }
3356 }
3357
3359 {
3361 return;
3362 }
3363
3364 LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3365
3366 /*
3367 * If the transaction is committing, but it has been partially released
3368 * already, then treat this as a roll back. It was marked as rolled back.
3369 */
3371 isCommit = false;
3372
3373 /*
3374 * If we're called in the middle of a transaction because we discovered
3375 * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3376 * it (that is, release the predicate locks and conflicts, but not the
3377 * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3378 */
3379 if (isReadOnlySafe && IsInParallelMode())
3380 {
3381 /*
3382 * The leader needs to stash a pointer to it, so that it can
3383 * completely release it at end-of-transaction.
3384 */
3385 if (!IsParallelWorker())
3387
3388 /*
3389 * The first backend to reach this condition will partially release
3390 * the SERIALIZABLEXACT. All others will just clear their
3391 * backend-local state so that they stop doing SSI checks for the rest
3392 * of the transaction.
3393 */
3395 {
3396 LWLockRelease(SerializableXactHashLock);
3398 return;
3399 }
3400 else
3401 {
3403 partiallyReleasing = true;
3404 /* ... and proceed to perform the partial release below. */
3405 }
3406 }
3408 Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3412
3413 /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3415
3416 /* We'd better not already be on the cleanup list. */
3418
3419 topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3420
3421 /*
3422 * We don't hold XidGenLock lock here, assuming that TransactionId is
3423 * atomic!
3424 *
3425 * If this value is changing, we don't care that much whether we get the
3426 * old or new value -- it is just used to determine how far
3427 * SxactGlobalXmin must advance before this transaction can be fully
3428 * cleaned up. The worst that could happen is we wait for one more
3429 * transaction to complete before freeing some RAM; correctness of visible
3430 * behavior is not affected.
3431 */
3433
3434 /*
3435 * If it's not a commit it's either a rollback or a read-only transaction
3436 * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3437 */
3438 if (isCommit)
3439 {
3442 /* Recognize implicit read-only transaction (commit without write). */
3443 if (!MyXactDidWrite)
3445 }
3446 else
3447 {
3448 /*
3449 * The DOOMED flag indicates that we intend to roll back this
3450 * transaction and so it should not cause serialization failures for
3451 * other transactions that conflict with it. Note that this flag might
3452 * already be set, if another backend marked this transaction for
3453 * abort.
3454 *
3455 * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3456 * has been called, and so the SerializableXact is eligible for
3457 * cleanup. This means it should not be considered when calculating
3458 * SxactGlobalXmin.
3459 */
3462
3463 /*
3464 * If the transaction was previously prepared, but is now failing due
3465 * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3466 * prepare, clear the prepared flag. This simplifies conflict
3467 * checking.
3468 */
3469 MySerializableXact->flags &= ~SXACT_FLAG_PREPARED;
3470 }
3471
3472 if (!topLevelIsDeclaredReadOnly)
3473 {
3475 if (--(PredXact->WritableSxactCount) == 0)
3476 {
3477 /*
3478 * Release predicate locks and rw-conflicts in for all committed
3479 * transactions. There are no longer any transactions which might
3480 * conflict with the locks and no chance for new transactions to
3481 * overlap. Similarly, existing conflicts in can't cause pivots,
3482 * and any conflicts in which could have completed a dangerous
3483 * structure would already have caused a rollback, so any
3484 * remaining ones must be benign.
3485 */
3487 }
3488 }
3489 else
3490 {
3491 /*
3492 * Read-only transactions: clear the list of transactions that might
3493 * make us unsafe. Note that we use 'inLink' for the iteration as
3494 * opposed to 'outLink' for the r/w xacts.
3495 */
3497 {
3498 RWConflict possibleUnsafeConflict =
3499 dlist_container(RWConflictData, inLink, iter.cur);
3500
3501 Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3502 Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3503
3504 ReleaseRWConflict(possibleUnsafeConflict);
3505 }
3506 }
3507
3508 /* Check for conflict out to old committed transactions. */
3509 if (isCommit
3512 {
3513 /*
3514 * we don't know which old committed transaction we conflicted with,
3515 * so be conservative and use FirstNormalSerCommitSeqNo here
3516 */
3520 }
3521
3522 /*
3523 * Release all outConflicts to committed transactions. If we're rolling
3524 * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3525 * previously committed transactions.
3526 */
3528 {
3529 RWConflict conflict =
3530 dlist_container(RWConflictData, outLink, iter.cur);
3531
3532 if (isCommit
3534 && SxactIsCommitted(conflict->sxactIn))
3535 {
3540 }
3541
3542 if (!isCommit
3543 || SxactIsCommitted(conflict->sxactIn)
3545 ReleaseRWConflict(conflict);
3546 }
3547
3548 /*
3549 * Release all inConflicts from committed and read-only transactions. If
3550 * we're rolling back, clear them all.
3551 */
3553 {
3554 RWConflict conflict =
3555 dlist_container(RWConflictData, inLink, iter.cur);
3556
3557 if (!isCommit
3558 || SxactIsCommitted(conflict->sxactOut)
3559 || SxactIsReadOnly(conflict->sxactOut))
3560 ReleaseRWConflict(conflict);
3561 }
3562
3563 if (!topLevelIsDeclaredReadOnly)
3564 {
3565 /*
3566 * Remove ourselves from the list of possible conflicts for concurrent
3567 * READ ONLY transactions, flagging them as unsafe if we have a
3568 * conflict out. If any are waiting DEFERRABLE transactions, wake them
3569 * up if they are known safe or known unsafe.
3570 */
3572 {
3573 RWConflict possibleUnsafeConflict =
3574 dlist_container(RWConflictData, outLink, iter.cur);
3575
3576 roXact = possibleUnsafeConflict->sxactIn;
3577 Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3578 Assert(SxactIsReadOnly(roXact));
3579
3580 /* Mark conflicted if necessary. */
3581 if (isCommit
3585 <= roXact->SeqNo.lastCommitBeforeSnapshot))
3586 {
3587 /*
3588 * This releases possibleUnsafeConflict (as well as all other
3589 * possible conflicts for roXact)
3590 */
3591 FlagSxactUnsafe(roXact);
3592 }
3593 else
3594 {
3595 ReleaseRWConflict(possibleUnsafeConflict);
3596
3597 /*
3598 * If we were the last possible conflict, flag it safe. The
3599 * transaction can now safely release its predicate locks (but
3600 * that transaction's backend has to do that itself).
3601 */
3603 roXact->flags |= SXACT_FLAG_RO_SAFE;
3604 }
3605
3606 /*
3607 * Wake up the process for a waiting DEFERRABLE transaction if we
3608 * now know it's either safe or conflicted.
3609 */
3610 if (SxactIsDeferrableWaiting(roXact) &&
3611 (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3612 ProcSendSignal(roXact->pgprocno);
3613 }
3614 }
3615
3616 /*
3617 * Check whether it's time to clean up old transactions. This can only be
3618 * done when the last serializable transaction with the oldest xmin among
3619 * serializable transactions completes. We then find the "new oldest"
3620 * xmin and purge any transactions which finished before this transaction
3621 * was launched.
3622 *
3623 * For parallel queries in read-only transactions, it might run twice. We
3624 * only release the reference on the first call.
3625 */
3626 needToClear = false;
3627 if ((partiallyReleasing ||
3631 {
3633 if (--(PredXact->SxactGlobalXminCount) == 0)
3634 {
3636 needToClear = true;
3637 }
3638 }
3639
3640 LWLockRelease(SerializableXactHashLock);
3641
3642 LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3643
3644 /* Add this to the list of transactions to check for later cleanup. */
3645 if (isCommit)
3648
3649 /*
3650 * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3651 * partially release it. That's necessary because other backends may have
3652 * a reference to it. The leader will release the SERIALIZABLEXACT itself
3653 * at the end of the transaction after workers have stopped running.
3654 */
3655 if (!isCommit)
3657 isReadOnlySafe && IsInParallelMode(),
3658 false);
3659
3660 LWLockRelease(SerializableFinishedListLock);
3661
3662 if (needToClear)
3664
3666}
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3241
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:292
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:290
static void ReleasePredicateLocksLocal(void)
Definition: predicate.c:3669
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3687
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:699
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:267
#define SxactIsROSafe(sxact)
Definition: predicate.c:291
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:691
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3825
#define SxactIsRolledBack(sxact)
Definition: predicate.c:279
static SERIALIZABLEXACT * SavedSerializableXact
Definition: predicate.c:431
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_READ_ONLY
#define SXACT_FLAG_ROLLED_BACK
#define SXACT_FLAG_PARTIALLY_RELEASED
#define SXACT_FLAG_RO_SAFE
void ProcSendSignal(ProcNumber procNumber)
Definition: proc.c:1908
SERIALIZABLEXACT * sxactIn
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransamVariablesData * TransamVariables
Definition: varsup.c:34
bool IsInParallelMode(void)
Definition: xact.c:1088

References Assert, PredXactListData::CanPartialClearThrough, ClearOldPredicateLocks(), SERIALIZABLEXACT::commitSeqNo, dlist_mutable_iter::cur, dlist_container, dlist_foreach_modify, dlist_is_empty(), dlist_push_tail(), SERIALIZABLEXACT::earliestOutConflictCommit, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FinishedSerializableTransactions, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, FlagSxactUnsafe(), SERIALIZABLEXACT::inConflicts, InvalidSerializableXact, IsInParallelMode(), IsolationIsSerializable, IsParallelWorker, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LocalPredicateLockHash, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, MyXactDidWrite, TransamVariablesData::nextXid, SERIALIZABLEXACT::outConflicts, ParallelContextActive(), SERIALIZABLEXACT::pgprocno, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, PredXact, SERIALIZABLEXACT::prepareSeqNo, ProcSendSignal(), ReleaseOneSerializableXact(), ReleasePredicateLocksLocal(), ReleaseRWConflict(), SavedSerializableXact, SERIALIZABLEXACT::SeqNo, SetNewSxactGlobalXmin(), SXACT_FLAG_COMMITTED, SXACT_FLAG_CONFLICT_OUT, SXACT_FLAG_DOOMED, SXACT_FLAG_PARTIALLY_RELEASED, 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, TransamVariables, PredXactListData::WritableSxactCount, XidFromFullTransactionId, and SERIALIZABLEXACT::xmin.

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

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1712 of file predicate.c.

1715{
1717
1718 /*
1719 * If this is called by parallel.c in a parallel worker, we don't want to
1720 * create a SERIALIZABLEXACT just yet because the leader's
1721 * SERIALIZABLEXACT will be installed with AttachSerializableXact(). We
1722 * also don't want to reject SERIALIZABLE READ ONLY DEFERRABLE in this
1723 * case, because the leader has already determined that the snapshot it
1724 * has passed us is safe. So there is nothing for us to do.
1725 */
1726 if (IsParallelWorker())
1727 return;
1728
1729 /*
1730 * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1731 * import snapshots, since there's no way to wait for a safe snapshot when
1732 * we're using the snap we're told to. (XXX instead of throwing an error,
1733 * we could just ignore the XactDeferrable flag?)
1734 */
1736 ereport(ERROR,
1737 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1738 errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1739
1740 (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1741 sourcepid);
1742}

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

Referenced by SetTransactionSnapshot().

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )

Definition at line 5036 of file predicate.c.

5037{
5038 return MySerializableXact;
5039}

References MySerializableXact.

Referenced by InitializeParallelDSM().

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3113 of file predicate.c.

3114{
3115 DropAllPredicateLocksFromTable(relation, true);
3116}
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2927

References DropAllPredicateLocksFromTable().

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

Variable Documentation

◆ max_predicate_locks_per_page

PGDLLIMPORT int max_predicate_locks_per_page
extern

Definition at line 373 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

PGDLLIMPORT int max_predicate_locks_per_relation
extern

Definition at line 372 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

PGDLLIMPORT int max_predicate_locks_per_xact
extern

Definition at line 371 of file predicate.c.

Referenced by CreateLocalPredicateLockHash(), and MaxPredicateChildLocks().