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 4720 of file predicate.c.

4721{
4724 TwoPhasePredicateXactRecord *xactRecord;
4725 TwoPhasePredicateLockRecord *lockRecord;
4726 dlist_iter iter;
4727
4729 xactRecord = &(record.data.xactRecord);
4730 lockRecord = &(record.data.lockRecord);
4731
4733 return;
4734
4735 /* Generate an xact record for our SERIALIZABLEXACT */
4737 xactRecord->xmin = MySerializableXact->xmin;
4738 xactRecord->flags = MySerializableXact->flags;
4739
4740 /*
4741 * Note that we don't include the list of conflicts in our out in the
4742 * statefile, because new conflicts can be added even after the
4743 * transaction prepares. We'll just make a conservative assumption during
4744 * recovery instead.
4745 */
4746
4748 &record, sizeof(record));
4749
4750 /*
4751 * Generate a lock record for each lock.
4752 *
4753 * To do this, we need to walk the predicate lock list in our sxact rather
4754 * than using the local predicate lock table because the latter is not
4755 * guaranteed to be accurate.
4756 */
4758
4759 /*
4760 * No need to take sxact->perXactPredicateListLock in parallel mode
4761 * because there cannot be any parallel workers running while we are
4762 * preparing a transaction.
4763 */
4765
4766 dlist_foreach(iter, &sxact->predicateLocks)
4767 {
4769 dlist_container(PREDICATELOCK, xactLink, iter.cur);
4770
4772 lockRecord->target = predlock->tag.myTarget->tag;
4773
4775 &record, sizeof(record));
4776 }
4777
4779}
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 4986 of file predicate.c.

4987{
4988
4990
4994}
static void CreateLocalPredicateLockHash(void)
Definition predicate.c:1870

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

Referenced by ParallelWorkerMain().

◆ CheckForSerializableConflictIn()

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

Definition at line 4266 of file predicate.c.

4267{
4269
4270 if (!SerializationNeededForWrite(relation))
4271 return;
4272
4273 /* Check if someone else has already decided that we need to die */
4275 ereport(ERROR,
4277 errmsg("could not serialize access due to read/write dependencies among transactions"),
4278 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4279 errhint("The transaction might succeed if retried.")));
4280
4281 /*
4282 * We're doing a write which might cause rw-conflicts now or later.
4283 * Memorize that fact.
4284 */
4285 MyXactDidWrite = true;
4286
4287 /*
4288 * It is important that we check for locks from the finest granularity to
4289 * the coarsest granularity, so that granularity promotion doesn't cause
4290 * us to miss a lock. The new (coarser) lock will be acquired before the
4291 * old (finer) locks are released.
4292 *
4293 * It is not possible to take and hold a lock across the checks for all
4294 * granularities because each target could be in a separate partition.
4295 */
4296 if (tid != NULL)
4297 {
4299 relation->rd_locator.dbOid,
4300 relation->rd_id,
4304 }
4305
4306 if (blkno != InvalidBlockNumber)
4307 {
4309 relation->rd_locator.dbOid,
4310 relation->rd_id,
4311 blkno);
4313 }
4314
4316 relation->rd_locator.dbOid,
4317 relation->rd_id);
4319}
#define InvalidBlockNumber
Definition block.h:33
int errcode(int sqlerrcode)
Definition elog.c:874
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:39
#define ereport(elevel,...)
Definition elog.h:151
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:4096
#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 3953 of file predicate.c.

3954{
3958
3959 if (!SerializationNeededForRead(relation, snapshot))
3960 return;
3961
3962 /* Check if someone else has already decided that we need to die */
3964 {
3965 ereport(ERROR,
3967 errmsg("could not serialize access due to read/write dependencies among transactions"),
3968 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3969 errhint("The transaction might succeed if retried.")));
3970 }
3972
3974 return;
3975
3976 /*
3977 * Find sxact or summarized info for the top level xid.
3978 */
3979 sxidtag.xid = xid;
3981 sxid = (SERIALIZABLEXID *)
3983 if (!sxid)
3984 {
3985 /*
3986 * Transaction not found in "normal" SSI structures. Check whether it
3987 * got pushed out to SLRU storage for "old committed" transactions.
3988 */
3990
3992 if (conflictCommitSeqNo != 0)
3993 {
3998 ereport(ERROR,
4000 errmsg("could not serialize access due to read/write dependencies among transactions"),
4001 errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4002 errhint("The transaction might succeed if retried.")));
4003
4006 ereport(ERROR,
4008 errmsg("could not serialize access due to read/write dependencies among transactions"),
4009 errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4010 errhint("The transaction might succeed if retried.")));
4011
4013 }
4014
4015 /* It's not serializable or otherwise not important. */
4017 return;
4018 }
4019 sxact = sxid->myXact;
4020 Assert(TransactionIdEquals(sxact->topXid, xid));
4022 {
4023 /* Can't conflict with ourself or a transaction that will roll back. */
4025 return;
4026 }
4027
4028 /*
4029 * We have a conflict out to a transaction which has a conflict out to a
4030 * summarized transaction. That summarized transaction must have
4031 * committed first, and we can't tell when it committed in relation to our
4032 * snapshot acquisition, so something needs to be canceled.
4033 */
4035 {
4036 if (!SxactIsPrepared(sxact))
4037 {
4038 sxact->flags |= SXACT_FLAG_DOOMED;
4040 return;
4041 }
4042 else
4043 {
4045 ereport(ERROR,
4047 errmsg("could not serialize access due to read/write dependencies among transactions"),
4048 errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4049 errhint("The transaction might succeed if retried.")));
4050 }
4051 }
4052
4053 /*
4054 * If this is a read-only transaction and the writing transaction has
4055 * committed, and it doesn't have a rw-conflict to a transaction which
4056 * committed before it, no conflict.
4057 */
4062 || MySerializableXact->SeqNo.lastCommitBeforeSnapshot < sxact->SeqNo.earliestOutConflictCommit))
4063 {
4064 /* Read-only transaction will appear to run first. No conflict. */
4066 return;
4067 }
4068
4069 if (!XidIsConcurrent(xid))
4070 {
4071 /* This write was already in our snapshot; no conflict. */
4073 return;
4074 }
4075
4077 {
4078 /* We don't want duplicate conflict records in the list. */
4080 return;
4081 }
4082
4083 /*
4084 * Flag the conflict. But first, if this conflict creates a dangerous
4085 * structure, ereport an error.
4086 */
4089}
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:4431
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
Definition predicate.c:930
static bool XidIsConcurrent(TransactionId xid)
Definition predicate.c:3902
#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 3921 of file predicate.c.

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

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 4349 of file predicate.c.

4350{
4352 PREDICATELOCKTARGET *target;
4353 Oid dbId;
4354 Oid heapId;
4355 int i;
4356
4357 /*
4358 * Bail out quickly if there are no serializable transactions running.
4359 * It's safe to check this without taking locks because the caller is
4360 * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4361 * would matter here can be acquired while that is held.
4362 */
4364 return;
4365
4366 if (!SerializationNeededForWrite(relation))
4367 return;
4368
4369 /*
4370 * We're doing a write which might cause rw-conflicts now or later.
4371 * Memorize that fact.
4372 */
4373 MyXactDidWrite = true;
4374
4375 Assert(relation->rd_index == NULL); /* not an index relation */
4376
4377 dbId = relation->rd_locator.dbOid;
4378 heapId = relation->rd_id;
4379
4381 for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4384
4385 /* Scan through target list */
4387
4388 while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4389 {
4390 dlist_mutable_iter iter;
4391
4392 /*
4393 * Check whether this is a target which needs attention.
4394 */
4396 continue; /* wrong relation id */
4397 if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4398 continue; /* wrong database id */
4399
4400 /*
4401 * Loop through locks for this target and flag conflicts.
4402 */
4403 dlist_foreach_modify(iter, &target->predicateLocks)
4404 {
4406 dlist_container(PREDICATELOCK, targetLink, iter.cur);
4407
4408 if (predlock->tag.myXact != MySerializableXact
4410 {
4412 }
4413 }
4414 }
4415
4416 /* Release locks in reverse order */
4418 for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4421}
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 1612 of file predicate.c.

1613{
1615
1616 /*
1617 * Can't use serializable mode while recovery is still active, as it is,
1618 * for example, on a hot standby. We could get here despite the check in
1619 * check_transaction_isolation() if default_transaction_isolation is set
1620 * to serializable, so phrase the hint accordingly.
1621 */
1622 if (RecoveryInProgress())
1623 ereport(ERROR,
1625 errmsg("cannot use serializable mode in a hot standby"),
1626 errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1627 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1628
1629 /*
1630 * A special optimization is available for SERIALIZABLE READ ONLY
1631 * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1632 * thereby avoid all SSI overhead once it's running.
1633 */
1635 return GetSafeSnapshot(snapshot);
1636
1638 NULL, InvalidPid);
1639}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define InvalidPid
Definition miscadmin.h:32
static Snapshot GetSafeSnapshot(Snapshot origSnapshot)
Definition predicate.c:1488
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition predicate.c:1694
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 1938 of file predicate.c.

1939{
1943 PREDICATELOCKTARGET *target;
1944
1946 relation->rd_locator.dbOid,
1947 relation->rd_id,
1948 blkno);
1949
1953 target = (PREDICATELOCKTARGET *)
1956 HASH_FIND, NULL);
1958
1959 return (target != NULL);
1960}
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 4633 of file predicate.c.

4634{
4636
4638 return;
4639
4641
4643
4644 /*
4645 * Check if someone else has already decided that we need to die. Since
4646 * we set our own DOOMED flag when partially releasing, ignore in that
4647 * case.
4648 */
4651 {
4653 ereport(ERROR,
4655 errmsg("could not serialize access due to read/write dependencies among transactions"),
4656 errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4657 errhint("The transaction might succeed if retried.")));
4658 }
4659
4661 {
4664
4665 if (!SxactIsCommitted(nearConflict->sxactOut)
4666 && !SxactIsDoomed(nearConflict->sxactOut))
4667 {
4669
4670 dlist_foreach(far_iter, &nearConflict->sxactOut->inConflicts)
4671 {
4674
4675 if (farConflict->sxactOut == MySerializableXact
4676 || (!SxactIsCommitted(farConflict->sxactOut)
4677 && !SxactIsReadOnly(farConflict->sxactOut)
4678 && !SxactIsDoomed(farConflict->sxactOut)))
4679 {
4680 /*
4681 * Normally, we kill the pivot transaction to make sure we
4682 * make progress if the failing transaction is retried.
4683 * However, we can't kill it if it's already prepared, so
4684 * in that case we commit suicide instead.
4685 */
4686 if (SxactIsPrepared(nearConflict->sxactOut))
4687 {
4689 ereport(ERROR,
4691 errmsg("could not serialize access due to read/write dependencies among transactions"),
4692 errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4693 errhint("The transaction might succeed if retried.")));
4694 }
4695 nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4696 break;
4697 }
4698 }
4699 }
4700 }
4701
4704
4706}
#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 4839 of file predicate.c.

4841{
4844
4846
4847 record = (TwoPhasePredicateRecord *) recdata;
4848
4850 (record->type == TWOPHASEPREDICATERECORD_LOCK));
4851
4852 if (record->type == TWOPHASEPREDICATERECORD_XACT)
4853 {
4854 /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4855 TwoPhasePredicateXactRecord *xactRecord;
4859 bool found;
4860
4861 xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4862
4865 if (!sxact)
4866 ereport(ERROR,
4868 errmsg("out of shared memory")));
4869
4870 /* vxid for a prepared xact is INVALID_PROC_NUMBER/xid; no pid */
4871 sxact->vxid.procNumber = INVALID_PROC_NUMBER;
4872 sxact->vxid.localTransactionId = (LocalTransactionId) xid;
4873 sxact->pid = 0;
4874 sxact->pgprocno = INVALID_PROC_NUMBER;
4875
4876 /* a prepared xact hasn't committed yet */
4877 sxact->prepareSeqNo = RecoverySerCommitSeqNo;
4878 sxact->commitSeqNo = InvalidSerCommitSeqNo;
4879 sxact->finishedBefore = InvalidTransactionId;
4880
4881 sxact->SeqNo.lastCommitBeforeSnapshot = RecoverySerCommitSeqNo;
4882
4883 /*
4884 * Don't need to track this; no transactions running at the time the
4885 * recovered xact started are still active, except possibly other
4886 * prepared xacts and we don't care whether those are RO_SAFE or not.
4887 */
4888 dlist_init(&(sxact->possibleUnsafeConflicts));
4889
4890 dlist_init(&(sxact->predicateLocks));
4891 dlist_node_init(&sxact->finishedLink);
4892
4893 sxact->topXid = xid;
4894 sxact->xmin = xactRecord->xmin;
4895 sxact->flags = xactRecord->flags;
4897 if (!SxactIsReadOnly(sxact))
4898 {
4902 }
4903
4904 /*
4905 * We don't know whether the transaction had any conflicts or not, so
4906 * we'll conservatively assume that it had both a conflict in and a
4907 * conflict out, and represent that with the summary conflict flags.
4908 */
4909 dlist_init(&(sxact->outConflicts));
4910 dlist_init(&(sxact->inConflicts));
4913
4914 /* Register the transaction's xid */
4915 sxidtag.xid = xid;
4917 &sxidtag,
4918 HASH_ENTER, &found);
4919 Assert(sxid != NULL);
4920 Assert(!found);
4921 sxid->myXact = sxact;
4922
4923 /*
4924 * Update global xmin. Note that this is a special case compared to
4925 * registering a normal transaction, because the global xmin might go
4926 * backwards. That's OK, because until recovery is over we're not
4927 * going to complete any transactions or create any non-prepared
4928 * transactions, so there's no danger of throwing away.
4929 */
4932 {
4936 }
4938 {
4941 }
4942
4944 }
4945 else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
4946 {
4947 /* Lock record. Recreate the PREDICATELOCK */
4948 TwoPhasePredicateLockRecord *lockRecord;
4953
4954 lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
4955 targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
4956
4958 sxidtag.xid = xid;
4959 sxid = (SERIALIZABLEXID *)
4962
4963 Assert(sxid != NULL);
4964 sxact = sxid->myXact;
4966
4967 CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
4968 }
4969}
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:2383
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 2529 of file predicate.c.

2530{
2532
2533 if (!SerializationNeededForRead(relation, snapshot))
2534 return;
2535
2537 relation->rd_locator.dbOid,
2538 relation->rd_id,
2539 blkno);
2541}
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition predicate.c:2447

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 3159 of file predicate.c.

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

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 3074 of file predicate.c.

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

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 2551 of file predicate.c.

2553{
2555
2556 if (!SerializationNeededForRead(relation, snapshot))
2557 return;
2558
2559 /*
2560 * Return if this xact wrote it.
2561 */
2562 if (relation->rd_index == NULL)
2563 {
2564 /* If we wrote it; we already have a write lock. */
2566 return;
2567 }
2568
2569 /*
2570 * Do quick-but-not-definitive test for a relation lock first. This will
2571 * never cause a return when the relation is *not* locked, but will
2572 * occasionally let the check continue when there really *is* a relation
2573 * level lock.
2574 */
2576 relation->rd_locator.dbOid,
2577 relation->rd_id);
2578 if (PredicateLockExists(&tag))
2579 return;
2580
2582 relation->rd_locator.dbOid,
2583 relation->rd_id,
2587}
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition predicate.c:1975
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 4812 of file predicate.c.

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

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 1889 of file predicate.c.

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

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 3242 of file predicate.c.

3243{
3244 bool partiallyReleasing = false;
3245 bool needToClear;
3247 dlist_mutable_iter iter;
3248
3249 /*
3250 * We can't trust XactReadOnly here, because a transaction which started
3251 * as READ WRITE can show as READ ONLY later, e.g., within
3252 * subtransactions. We want to flag a transaction as READ ONLY if it
3253 * commits without writing so that de facto READ ONLY transactions get the
3254 * benefit of some RO optimizations, so we will use this local variable to
3255 * get some cleanup logic right which is based on whether the transaction
3256 * was declared READ ONLY at the top level.
3257 */
3259
3260 /* We can't be both committing and releasing early due to RO_SAFE. */
3262
3263 /* Are we at the end of a transaction, that is, a commit or abort? */
3264 if (!isReadOnlySafe)
3265 {
3266 /*
3267 * Parallel workers mustn't release predicate locks at the end of
3268 * their transaction. The leader will do that at the end of its
3269 * transaction.
3270 */
3271 if (IsParallelWorker())
3272 {
3274 return;
3275 }
3276
3277 /*
3278 * By the time the leader in a parallel query reaches end of
3279 * transaction, it has waited for all workers to exit.
3280 */
3282
3283 /*
3284 * If the leader in a parallel query earlier stashed a partially
3285 * released SERIALIZABLEXACT for final clean-up at end of transaction
3286 * (because workers might still have been accessing it), then it's
3287 * time to restore it.
3288 */
3290 {
3295 }
3296 }
3297
3299 {
3301 return;
3302 }
3303
3305
3306 /*
3307 * If the transaction is committing, but it has been partially released
3308 * already, then treat this as a roll back. It was marked as rolled back.
3309 */
3311 isCommit = false;
3312
3313 /*
3314 * If we're called in the middle of a transaction because we discovered
3315 * that the SXACT_FLAG_RO_SAFE flag was set, then we'll partially release
3316 * it (that is, release the predicate locks and conflicts, but not the
3317 * SERIALIZABLEXACT itself) if we're the first backend to have noticed.
3318 */
3320 {
3321 /*
3322 * The leader needs to stash a pointer to it, so that it can
3323 * completely release it at end-of-transaction.
3324 */
3325 if (!IsParallelWorker())
3327
3328 /*
3329 * The first backend to reach this condition will partially release
3330 * the SERIALIZABLEXACT. All others will just clear their
3331 * backend-local state so that they stop doing SSI checks for the rest
3332 * of the transaction.
3333 */
3335 {
3338 return;
3339 }
3340 else
3341 {
3343 partiallyReleasing = true;
3344 /* ... and proceed to perform the partial release below. */
3345 }
3346 }
3352
3353 /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3355
3356 /* We'd better not already be on the cleanup list. */
3358
3360
3361 /*
3362 * We don't hold XidGenLock lock here, assuming that TransactionId is
3363 * atomic!
3364 *
3365 * If this value is changing, we don't care that much whether we get the
3366 * old or new value -- it is just used to determine how far
3367 * SxactGlobalXmin must advance before this transaction can be fully
3368 * cleaned up. The worst that could happen is we wait for one more
3369 * transaction to complete before freeing some RAM; correctness of visible
3370 * behavior is not affected.
3371 */
3373
3374 /*
3375 * If it's not a commit it's either a rollback or a read-only transaction
3376 * flagged SXACT_FLAG_RO_SAFE, and we can clear our locks immediately.
3377 */
3378 if (isCommit)
3379 {
3382 /* Recognize implicit read-only transaction (commit without write). */
3383 if (!MyXactDidWrite)
3385 }
3386 else
3387 {
3388 /*
3389 * The DOOMED flag indicates that we intend to roll back this
3390 * transaction and so it should not cause serialization failures for
3391 * other transactions that conflict with it. Note that this flag might
3392 * already be set, if another backend marked this transaction for
3393 * abort.
3394 *
3395 * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3396 * has been called, and so the SerializableXact is eligible for
3397 * cleanup. This means it should not be considered when calculating
3398 * SxactGlobalXmin.
3399 */
3402
3403 /*
3404 * If the transaction was previously prepared, but is now failing due
3405 * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3406 * prepare, clear the prepared flag. This simplifies conflict
3407 * checking.
3408 */
3410 }
3411
3413 {
3415 if (--(PredXact->WritableSxactCount) == 0)
3416 {
3417 /*
3418 * Release predicate locks and rw-conflicts in for all committed
3419 * transactions. There are no longer any transactions which might
3420 * conflict with the locks and no chance for new transactions to
3421 * overlap. Similarly, existing conflicts in can't cause pivots,
3422 * and any conflicts in which could have completed a dangerous
3423 * structure would already have caused a rollback, so any
3424 * remaining ones must be benign.
3425 */
3427 }
3428 }
3429 else
3430 {
3431 /*
3432 * Read-only transactions: clear the list of transactions that might
3433 * make us unsafe. Note that we use 'inLink' for the iteration as
3434 * opposed to 'outLink' for the r/w xacts.
3435 */
3437 {
3439 dlist_container(RWConflictData, inLink, iter.cur);
3440
3443
3445 }
3446 }
3447
3448 /* Check for conflict out to old committed transactions. */
3449 if (isCommit
3452 {
3453 /*
3454 * we don't know which old committed transaction we conflicted with,
3455 * so be conservative and use FirstNormalSerCommitSeqNo here
3456 */
3460 }
3461
3462 /*
3463 * Release all outConflicts to committed transactions. If we're rolling
3464 * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3465 * previously committed transactions.
3466 */
3468 {
3470 dlist_container(RWConflictData, outLink, iter.cur);
3471
3472 if (isCommit
3474 && SxactIsCommitted(conflict->sxactIn))
3475 {
3477 || conflict->sxactIn->prepareSeqNo < MySerializableXact->SeqNo.earliestOutConflictCommit)
3480 }
3481
3482 if (!isCommit
3483 || SxactIsCommitted(conflict->sxactIn)
3484 || (conflict->sxactIn->SeqNo.lastCommitBeforeSnapshot >= PredXact->LastSxactCommitSeqNo))
3486 }
3487
3488 /*
3489 * Release all inConflicts from committed and read-only transactions. If
3490 * we're rolling back, clear them all.
3491 */
3493 {
3495 dlist_container(RWConflictData, inLink, iter.cur);
3496
3497 if (!isCommit
3498 || SxactIsCommitted(conflict->sxactOut)
3499 || SxactIsReadOnly(conflict->sxactOut))
3501 }
3502
3504 {
3505 /*
3506 * Remove ourselves from the list of possible conflicts for concurrent
3507 * READ ONLY transactions, flagging them as unsafe if we have a
3508 * conflict out. If any are waiting DEFERRABLE transactions, wake them
3509 * up if they are known safe or known unsafe.
3510 */
3512 {
3514 dlist_container(RWConflictData, outLink, iter.cur);
3515
3516 roXact = possibleUnsafeConflict->sxactIn;
3519
3520 /* Mark conflicted if necessary. */
3521 if (isCommit
3525 <= roXact->SeqNo.lastCommitBeforeSnapshot))
3526 {
3527 /*
3528 * This releases possibleUnsafeConflict (as well as all other
3529 * possible conflicts for roXact)
3530 */
3532 }
3533 else
3534 {
3536
3537 /*
3538 * If we were the last possible conflict, flag it safe. The
3539 * transaction can now safely release its predicate locks (but
3540 * that transaction's backend has to do that itself).
3541 */
3542 if (dlist_is_empty(&roXact->possibleUnsafeConflicts))
3543 roXact->flags |= SXACT_FLAG_RO_SAFE;
3544 }
3545
3546 /*
3547 * Wake up the process for a waiting DEFERRABLE transaction if we
3548 * now know it's either safe or conflicted.
3549 */
3552 ProcSendSignal(roXact->pgprocno);
3553 }
3554 }
3555
3556 /*
3557 * Check whether it's time to clean up old transactions. This can only be
3558 * done when the last serializable transaction with the oldest xmin among
3559 * serializable transactions completes. We then find the "new oldest"
3560 * xmin and purge any transactions which finished before this transaction
3561 * was launched.
3562 *
3563 * For parallel queries in read-only transactions, it might run twice. We
3564 * only release the reference on the first call.
3565 */
3566 needToClear = false;
3567 if ((partiallyReleasing ||
3571 {
3573 if (--(PredXact->SxactGlobalXminCount) == 0)
3574 {
3576 needToClear = true;
3577 }
3578 }
3579
3581
3583
3584 /* Add this to the list of transactions to check for later cleanup. */
3585 if (isCommit)
3588
3589 /*
3590 * If we're releasing a RO_SAFE transaction in parallel mode, we'll only
3591 * partially release it. That's necessary because other backends may have
3592 * a reference to it. The leader will release the SERIALIZABLEXACT itself
3593 * at the end of the transaction after workers have stopped running.
3594 */
3595 if (!isCommit)
3598 false);
3599
3601
3602 if (needToClear)
3604
3606}
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition ilist.h:364
static void SetNewSxactGlobalXmin(void)
Definition predicate.c:3181
#define SxactIsROUnsafe(sxact)
Definition predicate.c:291
#define SxactIsDeferrableWaiting(sxact)
Definition predicate.c:289
static void ReleasePredicateLocksLocal(void)
Definition predicate.c:3609
static void ClearOldPredicateLocks(void)
Definition predicate.c:3627
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:3765
#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 1652 of file predicate.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ShareSerializableXact()

SerializableXactHandle ShareSerializableXact ( void  )
extern

Definition at line 4977 of file predicate.c.

4978{
4979 return MySerializableXact;
4980}

References MySerializableXact.

Referenced by InitializeParallelDSM().

◆ TransferPredicateLocksToHeapRelation()

void TransferPredicateLocksToHeapRelation ( Relation  relation)
extern

Definition at line 3053 of file predicate.c.

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

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