PostgreSQL Source Code git master
Loading...
Searching...
No Matches
predicate.h File Reference
#include "access/transam.h"
#include "storage/itemptr.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 struct VirtualTransactionId VirtualTransactionId
 
typedef voidSerializableXactHandle
 

Functions

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, const ItemPointerData *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, const ItemPointerData *tid, BlockNumber blkno)
 
void CheckTableForSerializableConflictIn (Relation relation)
 
void PreCommit_CheckForSerializationFailure (void)
 
void AtPrepare_PredicateLocks (void)
 
void PostPrepare_PredicateLocks (FullTransactionId fxid)
 
void PredicateLockTwoPhaseFinish (FullTransactionId fxid, bool isCommit)
 
void predicatelock_twophase_recover (FullTransactionId fxid, 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

Definition at line 39 of file predicate.h.

◆ VirtualTransactionId

Definition at line 25 of file predicate.h.

Function Documentation

◆ AtPrepare_PredicateLocks()

void AtPrepare_PredicateLocks ( void  )
extern

Definition at line 4719 of file predicate.c.

4720{
4723 TwoPhasePredicateXactRecord *xactRecord;
4724 TwoPhasePredicateLockRecord *lockRecord;
4725 dlist_iter iter;
4726
4728 xactRecord = &(record.data.xactRecord);
4729 lockRecord = &(record.data.lockRecord);
4730
4732 return;
4733
4734 /* Generate an xact record for our SERIALIZABLEXACT */
4736 xactRecord->xmin = MySerializableXact->xmin;
4737 xactRecord->flags = MySerializableXact->flags;
4738
4739 /*
4740 * Note that we don't include the list of conflicts in our out in the
4741 * statefile, because new conflicts can be added even after the
4742 * transaction prepares. We'll just make a conservative assumption during
4743 * recovery instead.
4744 */
4745
4747 &record, sizeof(record));
4748
4749 /*
4750 * Generate a lock record for each lock.
4751 *
4752 * To do this, we need to walk the predicate lock list in our sxact rather
4753 * than using the local predicate lock table because the latter is not
4754 * guaranteed to be accurate.
4755 */
4757
4758 /*
4759 * No need to take sxact->perXactPredicateListLock in parallel mode
4760 * because there cannot be any parallel workers running while we are
4761 * preparing a transaction.
4762 */
4764
4765 dlist_foreach(iter, &sxact->predicateLocks)
4766 {
4768 dlist_container(PREDICATELOCK, xactLink, iter.cur);
4769
4771 lockRecord->target = predlock->tag.myTarget->tag;
4772
4774 &record, sizeof(record));
4775 }
4776
4778}
bool ParallelContextActive(void)
Definition parallel.c:1033
#define Assert(condition)
Definition c.h:943
#define dlist_foreach(iter, lhead)
Definition ilist.h:623
#define dlist_container(type, membername, ptr)
Definition ilist.h:593
#define IsParallelWorker()
Definition parallel.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_SHARED
Definition lwlock.h:105
static SERIALIZABLEXACT * MySerializableXact
Definition predicate.c:434
@ TWOPHASEPREDICATERECORD_XACT
@ TWOPHASEPREDICATERECORD_LOCK
#define InvalidSerializableXact
static int fb(int x)
PREDICATELOCKTARGETTAG target
TwoPhasePredicateRecordType type
TwoPhasePredicateLockRecord lockRecord
union TwoPhasePredicateRecord::@135 data
TwoPhasePredicateXactRecord xactRecord
dlist_node * cur
Definition ilist.h:179
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition twophase.c:1277
#define TWOPHASE_RM_PREDICATELOCK_ID

References Assert, dlist_iter::cur, TwoPhasePredicateRecord::data, dlist_container, dlist_foreach, fb(), SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, IsParallelWorker, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, ParallelContextActive(), RegisterTwoPhaseRecord(), 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)
extern

Definition at line 4985 of file predicate.c.

4986{
4987
4989
4993}
static void CreateLocalPredicateLockHash(void)
Definition predicate.c:1869

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

Referenced by ParallelWorkerMain().

◆ CheckForSerializableConflictIn()

void CheckForSerializableConflictIn ( Relation  relation,
const ItemPointerData tid,
BlockNumber  blkno 
)
extern

Definition at line 4265 of file predicate.c.

4266{
4268
4269 if (!SerializationNeededForWrite(relation))
4270 return;
4271
4272 /* Check if someone else has already decided that we need to die */
4274 ereport(ERROR,
4276 errmsg("could not serialize access due to read/write dependencies among transactions"),
4277 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4278 errhint("The transaction might succeed if retried.")));
4279
4280 /*
4281 * We're doing a write which might cause rw-conflicts now or later.
4282 * Memorize that fact.
4283 */
4284 MyXactDidWrite = true;
4285
4286 /*
4287 * It is important that we check for locks from the finest granularity to
4288 * the coarsest granularity, so that granularity promotion doesn't cause
4289 * us to miss a lock. The new (coarser) lock will be acquired before the
4290 * old (finer) locks are released.
4291 *
4292 * It is not possible to take and hold a lock across the checks for all
4293 * granularities because each target could be in a separate partition.
4294 */
4295 if (tid != NULL)
4296 {
4298 relation->rd_locator.dbOid,
4299 relation->rd_id,
4303 }
4304
4305 if (blkno != InvalidBlockNumber)
4306 {
4308 relation->rd_locator.dbOid,
4309 relation->rd_id,
4310 blkno);
4312 }
4313
4315 relation->rd_locator.dbOid,
4316 relation->rd_id);
4318}
#define InvalidBlockNumber
Definition block.h:33
int errcode(int sqlerrcode)
Definition elog.c:875
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int errhint(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition itemptr.h:103
static char * errmsg
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition pgbench.c:77
static bool MyXactDidWrite
Definition predicate.c:435
static bool SerializationNeededForWrite(Relation relation)
Definition predicate.c:574
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition predicate.c:4095
#define SxactIsDoomed(sxact)
Definition predicate.c:279
#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, fb(), 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 
)
extern

Definition at line 3952 of file predicate.c.

3953{
3957
3958 if (!SerializationNeededForRead(relation, snapshot))
3959 return;
3960
3961 /* Check if someone else has already decided that we need to die */
3963 {
3964 ereport(ERROR,
3966 errmsg("could not serialize access due to read/write dependencies among transactions"),
3967 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3968 errhint("The transaction might succeed if retried.")));
3969 }
3971
3973 return;
3974
3975 /*
3976 * Find sxact or summarized info for the top level xid.
3977 */
3978 sxidtag.xid = xid;
3980 sxid = (SERIALIZABLEXID *)
3982 if (!sxid)
3983 {
3984 /*
3985 * Transaction not found in "normal" SSI structures. Check whether it
3986 * got pushed out to SLRU storage for "old committed" transactions.
3987 */
3989
3991 if (conflictCommitSeqNo != 0)
3992 {
3997 ereport(ERROR,
3999 errmsg("could not serialize access due to read/write dependencies among transactions"),
4000 errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4001 errhint("The transaction might succeed if retried.")));
4002
4005 ereport(ERROR,
4007 errmsg("could not serialize access due to read/write dependencies among transactions"),
4008 errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4009 errhint("The transaction might succeed if retried.")));
4010
4012 }
4013
4014 /* It's not serializable or otherwise not important. */
4016 return;
4017 }
4018 sxact = sxid->myXact;
4019 Assert(TransactionIdEquals(sxact->topXid, xid));
4021 {
4022 /* Can't conflict with ourself or a transaction that will roll back. */
4024 return;
4025 }
4026
4027 /*
4028 * We have a conflict out to a transaction which has a conflict out to a
4029 * summarized transaction. That summarized transaction must have
4030 * committed first, and we can't tell when it committed in relation to our
4031 * snapshot acquisition, so something needs to be canceled.
4032 */
4034 {
4035 if (!SxactIsPrepared(sxact))
4036 {
4037 sxact->flags |= SXACT_FLAG_DOOMED;
4039 return;
4040 }
4041 else
4042 {
4044 ereport(ERROR,
4046 errmsg("could not serialize access due to read/write dependencies among transactions"),
4047 errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4048 errhint("The transaction might succeed if retried.")));
4049 }
4050 }
4051
4052 /*
4053 * If this is a read-only transaction and the writing transaction has
4054 * committed, and it doesn't have a rw-conflict to a transaction which
4055 * committed before it, no conflict.
4056 */
4061 || MySerializableXact->SeqNo.lastCommitBeforeSnapshot < sxact->SeqNo.earliestOutConflictCommit))
4062 {
4063 /* Read-only transaction will appear to run first. No conflict. */
4065 return;
4066 }
4067
4068 if (!XidIsConcurrent(xid))
4069 {
4070 /* This write was already in our snapshot; no conflict. */
4072 return;
4073 }
4074
4076 {
4077 /* We don't want duplicate conflict records in the list. */
4079 return;
4080 }
4081
4082 /*
4083 * Flag the conflict. But first, if this conflict creates a dangerous
4084 * structure, ereport an error.
4085 */
4088}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
@ HASH_FIND
Definition hsearch.h:108
static bool dlist_is_empty(const dlist_head *head)
Definition ilist.h:336
@ LW_EXCLUSIVE
Definition lwlock.h:104
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition predicate.c:624
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition predicate.c:530
#define SxactIsCommitted(sxact)
Definition predicate.c:276
#define SxactIsReadOnly(sxact)
Definition predicate.c:280
#define SxactHasSummaryConflictIn(sxact)
Definition predicate.c:281
#define SxactHasConflictOut(sxact)
Definition predicate.c:288
#define SxactIsPrepared(sxact)
Definition predicate.c:277
static HTAB * SerializableXidHash
Definition predicate.c:409
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition predicate.c:4430
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
Definition predicate.c:930
static bool XidIsConcurrent(TransactionId xid)
Definition predicate.c:3901
#define SxactHasSummaryConflictOut(sxact)
Definition predicate.c:282
#define InvalidSerCommitSeqNo
#define SXACT_FLAG_DOOMED
uint64 SerCommitSeqNo
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
SerCommitSeqNo lastCommitBeforeSnapshot
union SERIALIZABLEXACT::@134 SeqNo
#define TransactionIdEquals(id1, id2)
Definition transam.h:43
#define TransactionIdIsValid(xid)
Definition transam.h:41
TransactionId GetTopTransactionIdIfAny(void)
Definition xact.c:443

References Assert, dlist_is_empty(), ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errdetail_internal(), errhint(), errmsg, ERROR, fb(), FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerialGetMinConflictCommitSeqNo(), SerializableXidHash, SerializationNeededForRead(), SXACT_FLAG_DOOMED, SXACT_FLAG_SUMMARY_CONFLICT_OUT, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, TransactionIdEquals, TransactionIdIsValid, and XidIsConcurrent().

Referenced by HeapCheckForSerializableConflictOut().

◆ CheckForSerializableConflictOutNeeded()

bool CheckForSerializableConflictOutNeeded ( Relation  relation,
Snapshot  snapshot 
)
extern

Definition at line 3920 of file predicate.c.

3921{
3922 if (!SerializationNeededForRead(relation, snapshot))
3923 return false;
3924
3925 /* Check if someone else has already decided that we need to die */
3927 {
3928 ereport(ERROR,
3930 errmsg("could not serialize access due to read/write dependencies among transactions"),
3931 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3932 errhint("The transaction might succeed if retried.")));
3933 }
3934
3935 return true;
3936}

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  )
extern

Definition at line 1022 of file predicate.c.

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

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

Referenced by CheckPointGuts().

◆ CheckTableForSerializableConflictIn()

void CheckTableForSerializableConflictIn ( Relation  relation)
extern

Definition at line 4348 of file predicate.c.

4349{
4351 PREDICATELOCKTARGET *target;
4352 Oid dbId;
4353 Oid heapId;
4354 int i;
4355
4356 /*
4357 * Bail out quickly if there are no serializable transactions running.
4358 * It's safe to check this without taking locks because the caller is
4359 * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4360 * would matter here can be acquired while that is held.
4361 */
4363 return;
4364
4365 if (!SerializationNeededForWrite(relation))
4366 return;
4367
4368 /*
4369 * We're doing a write which might cause rw-conflicts now or later.
4370 * Memorize that fact.
4371 */
4372 MyXactDidWrite = true;
4373
4374 Assert(relation->rd_index == NULL); /* not an index relation */
4375
4376 dbId = relation->rd_locator.dbOid;
4377 heapId = relation->rd_id;
4378
4380 for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4383
4384 /* Scan through target list */
4386
4387 while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4388 {
4389 dlist_mutable_iter iter;
4390
4391 /*
4392 * Check whether this is a target which needs attention.
4393 */
4395 continue; /* wrong relation id */
4396 if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4397 continue; /* wrong database id */
4398
4399 /*
4400 * Loop through locks for this target and flag conflicts.
4401 */
4402 dlist_foreach_modify(iter, &target->predicateLocks)
4403 {
4405 dlist_container(PREDICATELOCK, targetLink, iter.cur);
4406
4407 if (predlock->tag.myXact != MySerializableXact
4409 {
4411 }
4412 }
4413 }
4414
4415 /* Release locks in reverse order */
4417 for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4420}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1317
#define dlist_foreach_modify(iter, lhead)
Definition ilist.h:640
int i
Definition isn.c:77
#define NUM_PREDICATELOCK_PARTITIONS
Definition lwlock.h:91
unsigned int Oid
static PredXactList PredXact
Definition predicate.c:386
#define PredicateLockHashPartitionLockByIndex(i)
Definition predicate.c:260
static HTAB * PredicateLockTargetHash
Definition predicate.c:410
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
PREDICATELOCKTARGETTAG tag
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, fb(), FlagRWConflict(), GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_RELATION, hash_seq_init(), hash_seq_search(), i, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, MyXactDidWrite, NUM_PREDICATELOCK_PARTITIONS, PredicateLockHashPartitionLockByIndex, PREDICATELOCKTARGET::predicateLocks, PredicateLockTargetHash, PredXact, RelationData::rd_id, RelationData::rd_index, RelationData::rd_locator, RWConflictExists(), SerializationNeededForWrite(), PredXactListData::SxactGlobalXmin, PREDICATELOCKTARGET::tag, and TransactionIdIsValid.

Referenced by ExecuteTruncateGuts(), and heap_drop_with_catalog().

◆ GetSerializableTransactionSnapshot()

Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)
extern

Definition at line 1611 of file predicate.c.

1612{
1614
1615 /*
1616 * Can't use serializable mode while recovery is still active, as it is,
1617 * for example, on a hot standby. We could get here despite the check in
1618 * check_transaction_isolation() if default_transaction_isolation is set
1619 * to serializable, so phrase the hint accordingly.
1620 */
1621 if (RecoveryInProgress())
1622 ereport(ERROR,
1624 errmsg("cannot use serializable mode in a hot standby"),
1625 errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1626 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1627
1628 /*
1629 * A special optimization is available for SERIALIZABLE READ ONLY
1630 * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1631 * thereby avoid all SSI overhead once it's running.
1632 */
1634 return GetSafeSnapshot(snapshot);
1635
1637 NULL, InvalidPid);
1638}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define InvalidPid
Definition miscadmin.h:32
static Snapshot GetSafeSnapshot(Snapshot origSnapshot)
Definition predicate.c:1487
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition predicate.c:1693
bool XactDeferrable
Definition xact.c:87
bool XactReadOnly
Definition xact.c:84
#define IsolationIsSerializable()
Definition xact.h:53
bool RecoveryInProgress(void)
Definition xlog.c:6830

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

Referenced by GetTransactionSnapshot().

◆ PageIsPredicateLocked()

bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)
extern

Definition at line 1937 of file predicate.c.

1938{
1942 PREDICATELOCKTARGET *target;
1943
1945 relation->rd_locator.dbOid,
1946 relation->rd_id,
1947 blkno);
1948
1952 target = (PREDICATELOCKTARGET *)
1955 HASH_FIND, NULL);
1957
1958 return (target != NULL);
1959}
uint32_t uint32
Definition c.h:624
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition dynahash.c:902
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition predicate.c:302
#define PredicateLockHashPartitionLock(hashcode)
Definition predicate.c:257

References RelFileLocator::dbOid, fb(), 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  )
extern

Definition at line 4632 of file predicate.c.

4633{
4635
4637 return;
4638
4640
4642
4643 /*
4644 * Check if someone else has already decided that we need to die. Since
4645 * we set our own DOOMED flag when partially releasing, ignore in that
4646 * case.
4647 */
4650 {
4652 ereport(ERROR,
4654 errmsg("could not serialize access due to read/write dependencies among transactions"),
4655 errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4656 errhint("The transaction might succeed if retried.")));
4657 }
4658
4660 {
4663
4664 if (!SxactIsCommitted(nearConflict->sxactOut)
4665 && !SxactIsDoomed(nearConflict->sxactOut))
4666 {
4668
4669 dlist_foreach(far_iter, &nearConflict->sxactOut->inConflicts)
4670 {
4673
4674 if (farConflict->sxactOut == MySerializableXact
4675 || (!SxactIsCommitted(farConflict->sxactOut)
4676 && !SxactIsReadOnly(farConflict->sxactOut)
4677 && !SxactIsDoomed(farConflict->sxactOut)))
4678 {
4679 /*
4680 * Normally, we kill the pivot transaction to make sure we
4681 * make progress if the failing transaction is retried.
4682 * However, we can't kill it if it's already prepared, so
4683 * in that case we commit suicide instead.
4684 */
4685 if (SxactIsPrepared(nearConflict->sxactOut))
4686 {
4688 ereport(ERROR,
4690 errmsg("could not serialize access due to read/write dependencies among transactions"),
4691 errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4692 errhint("The transaction might succeed if retried.")));
4693 }
4694 nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4695 break;
4696 }
4697 }
4698 }
4699 }
4700
4703
4705}
#define SxactIsPartiallyReleased(sxact)
Definition predicate.c:292
#define SXACT_FLAG_PREPARED
SerCommitSeqNo LastSxactCommitSeqNo
SerCommitSeqNo prepareSeqNo

References Assert, dlist_container, dlist_foreach, ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errdetail_internal(), errhint(), errmsg, ERROR, fb(), 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, and SxactIsReadOnly.

Referenced by CommitTransaction(), and PrepareTransaction().

◆ predicatelock_twophase_recover()

void predicatelock_twophase_recover ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 4838 of file predicate.c.

4840{
4843
4845
4846 record = (TwoPhasePredicateRecord *) recdata;
4847
4849 (record->type == TWOPHASEPREDICATERECORD_LOCK));
4850
4851 if (record->type == TWOPHASEPREDICATERECORD_XACT)
4852 {
4853 /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4854 TwoPhasePredicateXactRecord *xactRecord;
4858 bool found;
4859
4860 xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4861
4864 if (!sxact)
4865 ereport(ERROR,
4867 errmsg("out of shared memory")));
4868
4869 /* vxid for a prepared xact is INVALID_PROC_NUMBER/xid; no pid */
4870 sxact->vxid.procNumber = INVALID_PROC_NUMBER;
4871 sxact->vxid.localTransactionId = (LocalTransactionId) xid;
4872 sxact->pid = 0;
4873 sxact->pgprocno = INVALID_PROC_NUMBER;
4874
4875 /* a prepared xact hasn't committed yet */
4876 sxact->prepareSeqNo = RecoverySerCommitSeqNo;
4877 sxact->commitSeqNo = InvalidSerCommitSeqNo;
4878 sxact->finishedBefore = InvalidTransactionId;
4879
4880 sxact->SeqNo.lastCommitBeforeSnapshot = RecoverySerCommitSeqNo;
4881
4882 /*
4883 * Don't need to track this; no transactions running at the time the
4884 * recovered xact started are still active, except possibly other
4885 * prepared xacts and we don't care whether those are RO_SAFE or not.
4886 */
4887 dlist_init(&(sxact->possibleUnsafeConflicts));
4888
4889 dlist_init(&(sxact->predicateLocks));
4890 dlist_node_init(&sxact->finishedLink);
4891
4892 sxact->topXid = xid;
4893 sxact->xmin = xactRecord->xmin;
4894 sxact->flags = xactRecord->flags;
4896 if (!SxactIsReadOnly(sxact))
4897 {
4901 }
4902
4903 /*
4904 * We don't know whether the transaction had any conflicts or not, so
4905 * we'll conservatively assume that it had both a conflict in and a
4906 * conflict out, and represent that with the summary conflict flags.
4907 */
4908 dlist_init(&(sxact->outConflicts));
4909 dlist_init(&(sxact->inConflicts));
4912
4913 /* Register the transaction's xid */
4914 sxidtag.xid = xid;
4916 &sxidtag,
4917 HASH_ENTER, &found);
4918 Assert(sxid != NULL);
4919 Assert(!found);
4920 sxid->myXact = sxact;
4921
4922 /*
4923 * Update global xmin. Note that this is a special case compared to
4924 * registering a normal transaction, because the global xmin might go
4925 * backwards. That's OK, because until recovery is over we're not
4926 * going to complete any transactions or create any non-prepared
4927 * transactions, so there's no danger of throwing away.
4928 */
4931 {
4935 }
4937 {
4940 }
4941
4943 }
4944 else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
4945 {
4946 /* Lock record. Recreate the PREDICATELOCK */
4947 TwoPhasePredicateLockRecord *lockRecord;
4952
4953 lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
4954 targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
4955
4957 sxidtag.xid = xid;
4958 sxid = (SERIALIZABLEXID *)
4961
4962 Assert(sxid != NULL);
4963 sxact = sxid->myXact;
4965
4966 CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
4967 }
4968}
uint32 LocalTransactionId
Definition c.h:738
uint32 TransactionId
Definition c.h:736
int MaxBackends
Definition globals.c:149
@ HASH_ENTER
Definition hsearch.h:109
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:2382
static SERIALIZABLEXACT * CreatePredXact(void)
Definition predicate.c:596
static void SerialSetActiveSerXmin(TransactionId xid)
Definition predicate.c:971
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
#define RecoverySerCommitSeqNo
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition transam.h:297
#define InvalidTransactionId
Definition transam.h:31
#define XidFromFullTransactionId(x)
Definition transam.h:48
int max_prepared_xacts
Definition twophase.c:118

References Assert, CreatePredicateLock(), CreatePredXact(), TwoPhasePredicateRecord::data, dlist_init(), dlist_node_init(), ereport, errcode(), errmsg, ERROR, fb(), TwoPhasePredicateXactRecord::flags, HASH_ENTER, HASH_FIND, hash_search(), INVALID_PROC_NUMBER, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, len, TwoPhasePredicateRecord::lockRecord, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, PredicateLockTargetTagHashCode, PredXact, RecoverySerCommitSeqNo, SerializableXidHash, SerialSetActiveSerXmin(), SXACT_FLAG_SUMMARY_CONFLICT_IN, SXACT_FLAG_SUMMARY_CONFLICT_OUT, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactIsPrepared, SxactIsReadOnly, TwoPhasePredicateLockRecord::target, TransactionIdEquals, TransactionIdFollows(), TransactionIdIsValid, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, PredXactListData::WritableSxactCount, TwoPhasePredicateRecord::xactRecord, XidFromFullTransactionId, and TwoPhasePredicateXactRecord::xmin.

◆ PredicateLockPage()

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

Definition at line 2528 of file predicate.c.

2529{
2531
2532 if (!SerializationNeededForRead(relation, snapshot))
2533 return;
2534
2536 relation->rd_locator.dbOid,
2537 relation->rd_id,
2538 blkno);
2540}
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition predicate.c:2446

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 
)
extern

Definition at line 3158 of file predicate.c.

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

References fb(), and PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead(), and ginDeletePostingPage().

◆ PredicateLockPageSplit()

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

Definition at line 3073 of file predicate.c.

3075{
3078 bool success;
3079
3080 /*
3081 * Bail out quickly if there are no serializable transactions running.
3082 *
3083 * It's safe to do this check without taking any additional locks. Even if
3084 * a serializable transaction starts concurrently, we know it can't take
3085 * any SIREAD locks on the page being split because the caller is holding
3086 * the associated buffer page lock. Memory reordering isn't an issue; the
3087 * memory barrier in the LWLock acquisition guarantees that this read
3088 * occurs while the buffer page lock is held.
3089 */
3091 return;
3092
3093 if (!PredicateLockingNeededForRelation(relation))
3094 return;
3095
3099
3101 relation->rd_locator.dbOid,
3102 relation->rd_id,
3103 oldblkno);
3105 relation->rd_locator.dbOid,
3106 relation->rd_id,
3107 newblkno);
3108
3110
3111 /*
3112 * Try copying the locks over to the new page's tag, creating it if
3113 * necessary.
3114 */
3117 false);
3118
3119 if (!success)
3120 {
3121 /*
3122 * No more predicate lock entries are available. Failure isn't an
3123 * option here, so promote the page lock to a relation lock.
3124 */
3125
3126 /* Get the parent relation lock's lock tag */
3128 &newtargettag);
3129 Assert(success);
3130
3131 /*
3132 * Move the locks to the parent. This shouldn't fail.
3133 *
3134 * Note that here we are removing locks held by other backends,
3135 * leading to a possible inconsistency in their local lock hash table.
3136 * This is OK because we're replacing it with a lock that covers the
3137 * old one.
3138 */
3141 true);
3142 Assert(success);
3143 }
3144
3146}
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition block.h:71
static bool success
Definition initdb.c:188
static bool PredicateLockingNeededForRelation(Relation relation)
Definition predicate.c:512
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition predicate.c:2001
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition predicate.c:2659

References Assert, BlockNumberIsValid(), RelFileLocator::dbOid, fb(), 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 
)
extern

◆ PredicateLockTID()

void PredicateLockTID ( Relation  relation,
const ItemPointerData tid,
Snapshot  snapshot,
TransactionId  tuple_xid 
)
extern

Definition at line 2550 of file predicate.c.

2552{
2554
2555 if (!SerializationNeededForRead(relation, snapshot))
2556 return;
2557
2558 /*
2559 * Return if this xact wrote it.
2560 */
2561 if (relation->rd_index == NULL)
2562 {
2563 /* If we wrote it; we already have a write lock. */
2565 return;
2566 }
2567
2568 /*
2569 * Do quick-but-not-definitive test for a relation lock first. This will
2570 * never cause a return when the relation is *not* locked, but will
2571 * occasionally let the check continue when there really *is* a relation
2572 * level lock.
2573 */
2575 relation->rd_locator.dbOid,
2576 relation->rd_id);
2577 if (PredicateLockExists(&tag))
2578 return;
2579
2581 relation->rd_locator.dbOid,
2582 relation->rd_id,
2586}
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition predicate.c:1974
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition xact.c:943

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

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

◆ PredicateLockTwoPhaseFinish()

void PredicateLockTwoPhaseFinish ( FullTransactionId  fxid,
bool  isCommit 
)
extern

Definition at line 4811 of file predicate.c.

4812{
4815
4817
4819 sxid = (SERIALIZABLEXID *)
4822
4823 /* xid will not be found if it wasn't a serializable transaction */
4824 if (sxid == NULL)
4825 return;
4826
4827 /* Release its locks */
4828 MySerializableXact = sxid->myXact;
4829 MyXactDidWrite = true; /* conservatively assume that we wrote
4830 * something */
4832}
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
Definition predicate.c:3241

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

Referenced by FinishPreparedTransaction().

◆ RegisterPredicateLockingXid()

void RegisterPredicateLockingXid ( TransactionId  xid)
extern

Definition at line 1888 of file predicate.c.

1889{
1892 bool found;
1893
1894 /*
1895 * If we're not tracking predicate lock data for this transaction, we
1896 * should ignore the request and return quickly.
1897 */
1899 return;
1900
1901 /* We should have a valid XID and be at the top level. */
1903
1905
1906 /* This should only be done once per transaction. */
1908
1910
1911 sxidtag.xid = xid;
1913 &sxidtag,
1914 HASH_ENTER, &found);
1915 Assert(!found);
1916
1917 /* Initialize the structure. */
1918 sxid->myXact = MySerializableXact;
1920}

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

Referenced by AssignTransactionId().

◆ ReleasePredicateLocks()

void ReleasePredicateLocks ( bool  isCommit,
bool  isReadOnlySafe 
)
extern

Definition at line 3241 of file predicate.c.

3242{
3243 bool partiallyReleasing = false;
3244 bool needToClear;
3246 dlist_mutable_iter iter;
3247
3248 /*
3249 * We can't trust XactReadOnly here, because a transaction which started
3250 * as READ WRITE can show as READ ONLY later, e.g., within
3251 * subtransactions. We want to flag a transaction as READ ONLY if it
3252 * commits without writing so that de facto READ ONLY transactions get the
3253 * benefit of some RO optimizations, so we will use this local variable to
3254 * get some cleanup logic right which is based on whether the transaction
3255 * was declared READ ONLY at the top level.
3256 */
3258
3259 /* We can't be both committing and releasing early due to RO_SAFE. */
3261
3262 /* Are we at the end of a transaction, that is, a commit or abort? */
3263 if (!isReadOnlySafe)
3264 {
3265 /*
3266 * Parallel workers mustn't release predicate locks at the end of
3267 * their transaction. The leader will do that at the end of its
3268 * transaction.
3269 */
3270 if (IsParallelWorker())
3271 {
3273 return;
3274 }
3275
3276 /*
3277 * By the time the leader in a parallel query reaches end of
3278 * transaction, it has waited for all workers to exit.
3279 */
3281
3282 /*
3283 * If the leader in a parallel query earlier stashed a partially
3284 * released SERIALIZABLEXACT for final clean-up at end of transaction
3285 * (because workers might still have been accessing it), then it's
3286 * time to restore it.
3287 */
3289 {
3294 }
3295 }
3296
3298 {
3300 return;
3301 }
3302
3304
3305 /*
3306 * If the transaction is committing, but it has been partially released
3307 * already, then treat this as a roll back. It was marked as rolled back.
3308 */
3310 isCommit = false;
3311
3312 /*
3313 * If we're called in the middle of a transaction because we discovered
3314 * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3315 * it (that is, release the predicate locks and conflicts, but not the
3316 * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3317 */
3319 {
3320 /*
3321 * The leader needs to stash a pointer to it, so that it can
3322 * completely release it at end-of-transaction.
3323 */
3324 if (!IsParallelWorker())
3326
3327 /*
3328 * The first backend to reach this condition will partially release
3329 * the SERIALIZABLEXACT. All others will just clear their
3330 * backend-local state so that they stop doing SSI checks for the rest
3331 * of the transaction.
3332 */
3334 {
3337 return;
3338 }
3339 else
3340 {
3342 partiallyReleasing = true;
3343 /* ... and proceed to perform the partial release below. */
3344 }
3345 }
3351
3352 /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3354
3355 /* We'd better not already be on the cleanup list. */
3357
3359
3360 /*
3361 * We don't hold XidGenLock lock here, assuming that TransactionId is
3362 * atomic!
3363 *
3364 * If this value is changing, we don't care that much whether we get the
3365 * old or new value -- it is just used to determine how far
3366 * SxactGlobalXmin must advance before this transaction can be fully
3367 * cleaned up. The worst that could happen is we wait for one more
3368 * transaction to complete before freeing some RAM; correctness of visible
3369 * behavior is not affected.
3370 */
3372
3373 /*
3374 * If it's not a commit it's either a rollback or a read-only transaction
3375 * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3376 */
3377 if (isCommit)
3378 {
3381 /* Recognize implicit read-only transaction (commit without write). */
3382 if (!MyXactDidWrite)
3384 }
3385 else
3386 {
3387 /*
3388 * The DOOMED flag indicates that we intend to roll back this
3389 * transaction and so it should not cause serialization failures for
3390 * other transactions that conflict with it. Note that this flag might
3391 * already be set, if another backend marked this transaction for
3392 * abort.
3393 *
3394 * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3395 * has been called, and so the SerializableXact is eligible for
3396 * cleanup. This means it should not be considered when calculating
3397 * SxactGlobalXmin.
3398 */
3401
3402 /*
3403 * If the transaction was previously prepared, but is now failing due
3404 * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3405 * prepare, clear the prepared flag. This simplifies conflict
3406 * checking.
3407 */
3409 }
3410
3412 {
3414 if (--(PredXact->WritableSxactCount) == 0)
3415 {
3416 /*
3417 * Release predicate locks and rw-conflicts in for all committed
3418 * transactions. There are no longer any transactions which might
3419 * conflict with the locks and no chance for new transactions to
3420 * overlap. Similarly, existing conflicts in can't cause pivots,
3421 * and any conflicts in which could have completed a dangerous
3422 * structure would already have caused a rollback, so any
3423 * remaining ones must be benign.
3424 */
3426 }
3427 }
3428 else
3429 {
3430 /*
3431 * Read-only transactions: clear the list of transactions that might
3432 * make us unsafe. Note that we use 'inLink' for the iteration as
3433 * opposed to 'outLink' for the r/w xacts.
3434 */
3436 {
3438 dlist_container(RWConflictData, inLink, iter.cur);
3439
3442
3444 }
3445 }
3446
3447 /* Check for conflict out to old committed transactions. */
3448 if (isCommit
3451 {
3452 /*
3453 * we don't know which old committed transaction we conflicted with,
3454 * so be conservative and use FirstNormalSerCommitSeqNo here
3455 */
3459 }
3460
3461 /*
3462 * Release all outConflicts to committed transactions. If we're rolling
3463 * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3464 * previously committed transactions.
3465 */
3467 {
3469 dlist_container(RWConflictData, outLink, iter.cur);
3470
3471 if (isCommit
3473 && SxactIsCommitted(conflict->sxactIn))
3474 {
3476 || conflict->sxactIn->prepareSeqNo < MySerializableXact->SeqNo.earliestOutConflictCommit)
3479 }
3480
3481 if (!isCommit
3482 || SxactIsCommitted(conflict->sxactIn)
3483 || (conflict->sxactIn->SeqNo.lastCommitBeforeSnapshot >= PredXact->LastSxactCommitSeqNo))
3485 }
3486
3487 /*
3488 * Release all inConflicts from committed and read-only transactions. If
3489 * we're rolling back, clear them all.
3490 */
3492 {
3494 dlist_container(RWConflictData, inLink, iter.cur);
3495
3496 if (!isCommit
3497 || SxactIsCommitted(conflict->sxactOut)
3498 || SxactIsReadOnly(conflict->sxactOut))
3500 }
3501
3503 {
3504 /*
3505 * Remove ourselves from the list of possible conflicts for concurrent
3506 * READ ONLY transactions, flagging them as unsafe if we have a
3507 * conflict out. If any are waiting DEFERRABLE transactions, wake them
3508 * up if they are known safe or known unsafe.
3509 */
3511 {
3513 dlist_container(RWConflictData, outLink, iter.cur);
3514
3515 roXact = possibleUnsafeConflict->sxactIn;
3518
3519 /* Mark conflicted if necessary. */
3520 if (isCommit
3524 <= roXact->SeqNo.lastCommitBeforeSnapshot))
3525 {
3526 /*
3527 * This releases possibleUnsafeConflict (as well as all other
3528 * possible conflicts for roXact)
3529 */
3531 }
3532 else
3533 {
3535
3536 /*
3537 * If we were the last possible conflict, flag it safe. The
3538 * transaction can now safely release its predicate locks (but
3539 * that transaction's backend has to do that itself).
3540 */
3541 if (dlist_is_empty(&roXact->possibleUnsafeConflicts))
3542 roXact->flags |= SXACT_FLAG_RO_SAFE;
3543 }
3544
3545 /*
3546 * Wake up the process for a waiting DEFERRABLE transaction if we
3547 * now know it's either safe or conflicted.
3548 */
3551 ProcSendSignal(roXact->pgprocno);
3552 }
3553 }
3554
3555 /*
3556 * Check whether it's time to clean up old transactions. This can only be
3557 * done when the last serializable transaction with the oldest xmin among
3558 * serializable transactions completes. We then find the "new oldest"
3559 * xmin and purge any transactions which finished before this transaction
3560 * was launched.
3561 *
3562 * For parallel queries in read-only transactions, it might run twice. We
3563 * only release the reference on the first call.
3564 */
3565 needToClear = false;
3566 if ((partiallyReleasing ||
3570 {
3572 if (--(PredXact->SxactGlobalXminCount) == 0)
3573 {
3575 needToClear = true;
3576 }
3577 }
3578
3580
3582
3583 /* Add this to the list of transactions to check for later cleanup. */
3584 if (isCommit)
3587
3588 /*
3589 * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3590 * partially release it. That's necessary because other backends may have
3591 * a reference to it. The leader will release the SERIALIZABLEXACT itself
3592 * at the end of the transaction after workers have stopped running.
3593 */
3594 if (!isCommit)
3597 false);
3598
3600
3601 if (needToClear)
3603
3605}
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition ilist.h:364
static void SetNewSxactGlobalXmin(void)
Definition predicate.c:3180
#define SxactIsROUnsafe(sxact)
Definition predicate.c:291
#define SxactIsDeferrableWaiting(sxact)
Definition predicate.c:289
static void ReleasePredicateLocksLocal(void)
Definition predicate.c:3608
static void ClearOldPredicateLocks(void)
Definition predicate.c:3626
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition predicate.c:713
#define SxactIsOnFinishedList(sxact)
Definition predicate.c:266
static dlist_head * FinishedSerializableTransactions
Definition predicate.c:412
#define SxactIsROSafe(sxact)
Definition predicate.c:290
static void ReleaseRWConflict(RWConflict conflict)
Definition predicate.c:705
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition predicate.c:3764
#define SxactIsRolledBack(sxact)
Definition predicate.c:278
static SERIALIZABLEXACT * SavedSerializableXact
Definition predicate.c:444
#define FirstNormalSerCommitSeqNo
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_READ_ONLY
#define SXACT_FLAG_ROLLED_BACK
#define SXACT_FLAG_COMMITTED
#define SXACT_FLAG_PARTIALLY_RELEASED
#define SXACT_FLAG_RO_SAFE
void ProcSendSignal(ProcNumber procNumber)
Definition proc.c:2027
SerCommitSeqNo CanPartialClearThrough
dlist_head possibleUnsafeConflicts
SerCommitSeqNo commitSeqNo
TransactionId finishedBefore
SerCommitSeqNo earliestOutConflictCommit
FullTransactionId nextXid
Definition transam.h:220
TransamVariablesData * TransamVariables
Definition varsup.c:37
bool IsInParallelMode(void)
Definition xact.c:1119

References Assert, PredXactListData::CanPartialClearThrough, ClearOldPredicateLocks(), SERIALIZABLEXACT::commitSeqNo, dlist_mutable_iter::cur, dlist_container, dlist_foreach_modify, dlist_is_empty(), dlist_push_tail(), SERIALIZABLEXACT::earliestOutConflictCommit, fb(), SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FinishedSerializableTransactions, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, FlagSxactUnsafe(), SERIALIZABLEXACT::inConflicts, InvalidSerializableXact, IsInParallelMode(), IsolationIsSerializable, IsParallelWorker, PredXactListData::LastSxactCommitSeqNo, LocalPredicateLockHash, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, MyXactDidWrite, TransamVariablesData::nextXid, SERIALIZABLEXACT::outConflicts, ParallelContextActive(), SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, PredXact, 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, SxactIsCommitted, SxactIsDeferrableWaiting, SxactIsDoomed, SxactIsOnFinishedList, SxactIsPartiallyReleased, SxactIsPrepared, SxactIsReadOnly, SxactIsRolledBack, SxactIsROSafe, SxactIsROUnsafe, TransactionIdEquals, TransamVariables, PredXactListData::WritableSxactCount, XidFromFullTransactionId, and SERIALIZABLEXACT::xmin.

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

◆ SetSerializableTransactionSnapshot()

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

Definition at line 1651 of file predicate.c.

1654{
1656
1657 /*
1658 * If this is called by parallel.c in a parallel worker, we don't want to
1659 * create a SERIALIZABLEXACT just yet because the leader's
1660 * SERIALIZABLEXACT will be installed with AttachSerializableXact(). We
1661 * also don't want to reject SERIALIZABLE READ ONLY DEFERRABLE in this
1662 * case, because the leader has already determined that the snapshot it
1663 * has passed us is safe. So there is nothing for us to do.
1664 */
1665 if (IsParallelWorker())
1666 return;
1667
1668 /*
1669 * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1670 * import snapshots, since there's no way to wait for a safe snapshot when
1671 * we're using the snap we're told to. (XXX instead of throwing an error,
1672 * we could just ignore the XactDeferrable flag?)
1673 */
1675 ereport(ERROR,
1677 errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1678
1680 sourcepid);
1681}

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

Referenced by SetTransactionSnapshot().

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )
extern

Definition at line 4976 of file predicate.c.

4977{
4978 return MySerializableXact;
4979}

References MySerializableXact.

Referenced by InitializeParallelDSM().

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)
extern

Definition at line 3052 of file predicate.c.

3053{
3054 DropAllPredicateLocksFromTable(relation, true);
3055}
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition predicate.c:2866

References DropAllPredicateLocksFromTable().

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

Variable Documentation

◆ max_predicate_locks_per_page

PGDLLIMPORT int max_predicate_locks_per_page
extern

Definition at line 375 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_relation

PGDLLIMPORT int max_predicate_locks_per_relation
extern

Definition at line 374 of file predicate.c.

Referenced by MaxPredicateChildLocks().

◆ max_predicate_locks_per_xact

PGDLLIMPORT int max_predicate_locks_per_xact
extern

Definition at line 373 of file predicate.c.

Referenced by CreateLocalPredicateLockHash(), and MaxPredicateChildLocks().