1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.213 2005/08/17 22:14:33 tgl Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/twophase.h"
26 #include "access/xact.h"
27 #include "catalog/heap.h"
28 #include "catalog/index.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
36 #include "storage/fd.h"
37 #include "storage/proc.h"
38 #include "storage/procarray.h"
39 #include "storage/smgr.h"
40 #include "utils/flatfiles.h"
41 #include "utils/guc.h"
42 #include "utils/inval.h"
43 #include "utils/memutils.h"
44 #include "utils/portal.h"
45 #include "utils/relcache.h"
46 #include "utils/resowner.h"
51 * User-tweakable parameters
53 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
56 bool DefaultXactReadOnly = false;
59 int CommitDelay = 0; /* precommit delay in microseconds */
60 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
64 * transaction states - transaction state from server perspective
66 typedef enum TransState
77 * transaction block states - transaction state of client queries
79 * Note: the subtransaction states are used only for non-topmost
80 * transactions; the others appear only in the topmost transaction.
82 typedef enum TBlockState
84 /* not-in-transaction-block states */
85 TBLOCK_DEFAULT, /* idle */
86 TBLOCK_STARTED, /* running single-query transaction */
88 /* transaction block states */
89 TBLOCK_BEGIN, /* starting transaction block */
90 TBLOCK_INPROGRESS, /* live transaction */
91 TBLOCK_END, /* COMMIT received */
92 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
93 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
94 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
95 TBLOCK_PREPARE, /* live xact, PREPARE received */
97 /* subtransaction states */
98 TBLOCK_SUBBEGIN, /* starting a subtransaction */
99 TBLOCK_SUBINPROGRESS, /* live subtransaction */
100 TBLOCK_SUBEND, /* RELEASE received */
101 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
102 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
103 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
104 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
105 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
109 * transaction state structure
111 typedef struct TransactionStateData
113 TransactionId transactionId; /* my XID, or Invalid if none */
114 SubTransactionId subTransactionId; /* my subxact ID */
115 char *name; /* savepoint name, if any */
116 int savepointLevel; /* savepoint level */
117 TransState state; /* low-level state */
118 TBlockState blockState; /* high-level state */
119 int nestingLevel; /* nest depth */
120 MemoryContext curTransactionContext; /* my xact-lifetime
122 ResourceOwner curTransactionOwner; /* my query resources */
123 List *childXids; /* subcommitted child XIDs */
124 Oid currentUser; /* subxact start current_user */
125 bool prevXactReadOnly; /* entry-time xact r/o state */
126 struct TransactionStateData *parent; /* back link to parent */
127 } TransactionStateData;
129 typedef TransactionStateData *TransactionState;
132 * childXids is currently implemented as an integer List, relying on the
133 * assumption that TransactionIds are no wider than int. We use these
134 * macros to provide some isolation in case that changes in the future.
136 #define lfirst_xid(lc) ((TransactionId) lfirst_int(lc))
137 #define lappend_xid(list, datum) lappend_int(list, (int) (datum))
140 * CurrentTransactionState always points to the current transaction state
141 * block. It will point to TopTransactionStateData when not in a
142 * transaction at all, or when in a top-level transaction.
144 static TransactionStateData TopTransactionStateData = {
145 0, /* transaction id */
146 0, /* subtransaction id */
147 NULL, /* savepoint name */
148 0, /* savepoint level */
149 TRANS_DEFAULT, /* transaction state */
150 TBLOCK_DEFAULT, /* transaction block state from the client
152 0, /* nesting level */
153 NULL, /* cur transaction context */
154 NULL, /* cur transaction resource owner */
155 NIL, /* subcommitted child Xids */
156 0, /* entry-time current userid */
157 false, /* entry-time xact r/o state */
158 NULL /* link to parent state block */
161 static TransactionState CurrentTransactionState = &TopTransactionStateData;
164 * The subtransaction ID and command ID assignment counters are global
165 * to a whole transaction, so we do not keep them in the state stack.
167 static SubTransactionId currentSubTransactionId;
168 static CommandId currentCommandId;
171 * This is the value of now(), ie, the transaction start time.
172 * This does not change as we enter and exit subtransactions, so we don't
173 * keep it inside the TransactionState stack.
175 static TimestampTz xactStartTimestamp;
178 * GID to be used for preparing the current transaction. This is also
179 * global to a whole transaction, so we don't keep it in the state stack.
181 static char *prepareGID;
185 * List of add-on start- and end-of-xact callbacks
187 typedef struct XactCallbackItem
189 struct XactCallbackItem *next;
190 XactCallback callback;
194 static XactCallbackItem *Xact_callbacks = NULL;
197 * List of add-on start- and end-of-subxact callbacks
199 typedef struct SubXactCallbackItem
201 struct SubXactCallbackItem *next;
202 SubXactCallback callback;
204 } SubXactCallbackItem;
206 static SubXactCallbackItem *SubXact_callbacks = NULL;
209 /* local function prototypes */
210 static void AssignSubTransactionId(TransactionState s);
211 static void AbortTransaction(void);
212 static void AtAbort_Memory(void);
213 static void AtCleanup_Memory(void);
214 static void AtAbort_ResourceOwner(void);
215 static void AtCommit_LocalCache(void);
216 static void AtCommit_Memory(void);
217 static void AtStart_Cache(void);
218 static void AtStart_Memory(void);
219 static void AtStart_ResourceOwner(void);
220 static void CallXactCallbacks(XactEvent event);
221 static void CallSubXactCallbacks(SubXactEvent event,
222 SubTransactionId mySubid,
223 SubTransactionId parentSubid);
224 static void CleanupTransaction(void);
225 static void CommitTransaction(void);
226 static void RecordTransactionAbort(void);
227 static void StartTransaction(void);
229 static void RecordSubTransactionCommit(void);
230 static void StartSubTransaction(void);
231 static void CommitSubTransaction(void);
232 static void AbortSubTransaction(void);
233 static void CleanupSubTransaction(void);
234 static void PushTransaction(void);
235 static void PopTransaction(void);
237 static void AtSubAbort_Memory(void);
238 static void AtSubCleanup_Memory(void);
239 static void AtSubAbort_ResourceOwner(void);
240 static void AtSubCommit_Memory(void);
241 static void AtSubStart_Memory(void);
242 static void AtSubStart_ResourceOwner(void);
244 static void ShowTransactionState(const char *str);
245 static void ShowTransactionStateRec(TransactionState state);
246 static const char *BlockStateAsString(TBlockState blockState);
247 static const char *TransStateAsString(TransState state);
250 /* ----------------------------------------------------------------
251 * transaction state accessors
252 * ----------------------------------------------------------------
258 * This returns true if we are currently running a query
259 * within an executing transaction.
262 IsTransactionState(void)
264 TransactionState s = CurrentTransactionState;
272 case TRANS_INPROGRESS:
283 * Shouldn't get here, but lint is not happy without this...
289 * IsAbortedTransactionBlockState
291 * This returns true if we are currently running a query
292 * within an aborted transaction block.
295 IsAbortedTransactionBlockState(void)
297 TransactionState s = CurrentTransactionState;
299 if (s->blockState == TBLOCK_ABORT ||
300 s->blockState == TBLOCK_SUBABORT)
308 * GetTopTransactionId
310 * Get the ID of the main transaction, even if we are currently inside
314 GetTopTransactionId(void)
316 return TopTransactionStateData.transactionId;
321 * GetCurrentTransactionId
323 * We do not assign XIDs to subtransactions until/unless this is called.
324 * When we do assign an XID to a subtransaction, recursively make sure
325 * its parent has one as well (this maintains the invariant that a child
326 * transaction has an XID following its parent's).
329 GetCurrentTransactionId(void)
331 TransactionState s = CurrentTransactionState;
333 if (!TransactionIdIsValid(s->transactionId))
334 AssignSubTransactionId(s);
336 return s->transactionId;
340 AssignSubTransactionId(TransactionState s)
342 ResourceOwner currentOwner;
344 Assert(s->parent != NULL);
345 Assert(s->state == TRANS_INPROGRESS);
346 if (!TransactionIdIsValid(s->parent->transactionId))
347 AssignSubTransactionId(s->parent);
350 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
352 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere
353 * in shared storage other than PG_PROC; because if there's no room for
354 * it in PG_PROC, the subtrans entry is needed to ensure that other
355 * backends see the Xid as "running". See GetNewTransactionId.
357 s->transactionId = GetNewTransactionId(true);
359 SubTransSetParent(s->transactionId, s->parent->transactionId);
362 * Acquire lock on the transaction XID. (We assume this cannot block.)
363 * We have to be sure that the lock is assigned to the transaction's
366 currentOwner = CurrentResourceOwner;
369 CurrentResourceOwner = s->curTransactionOwner;
371 XactLockTableInsert(s->transactionId);
375 /* Ensure CurrentResourceOwner is restored on error */
376 CurrentResourceOwner = currentOwner;
380 CurrentResourceOwner = currentOwner;
385 * GetCurrentTransactionIdIfAny
387 * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
388 * if we are currently not in a transaction, or in a transaction or
389 * subtransaction that has not yet assigned itself an XID.
392 GetCurrentTransactionIdIfAny(void)
394 TransactionState s = CurrentTransactionState;
396 return s->transactionId;
401 * GetCurrentSubTransactionId
404 GetCurrentSubTransactionId(void)
406 TransactionState s = CurrentTransactionState;
408 return s->subTransactionId;
413 * GetCurrentCommandId
416 GetCurrentCommandId(void)
418 /* this is global to a transaction, not subtransaction-local */
419 return currentCommandId;
423 * GetCurrentTransactionStartTimestamp
426 GetCurrentTransactionStartTimestamp(void)
428 return xactStartTimestamp;
432 * GetCurrentTransactionNestLevel
434 * Note: this will return zero when not inside any transaction, one when
435 * inside a top-level transaction, etc.
438 GetCurrentTransactionNestLevel(void)
440 TransactionState s = CurrentTransactionState;
442 return s->nestingLevel;
447 * TransactionIdIsCurrentTransactionId
450 TransactionIdIsCurrentTransactionId(TransactionId xid)
455 * We always say that BootstrapTransactionId is "not my transaction ID"
456 * even when it is (ie, during bootstrap). Along with the fact that
457 * transam.c always treats BootstrapTransactionId as already committed,
458 * this causes the tqual.c routines to see all tuples as committed,
459 * which is what we need during bootstrap. (Bootstrap mode only inserts
460 * tuples, it never updates or deletes them, so all tuples can be presumed
463 if (xid == BootstrapTransactionId)
467 * We will return true for the Xid of the current subtransaction, any
468 * of its subcommitted children, any of its parents, or any of their
469 * previously subcommitted children. However, a transaction being
470 * aborted is no longer "current", even though it may still have an
471 * entry on the state stack.
473 for (s = CurrentTransactionState; s != NULL; s = s->parent)
477 if (s->state == TRANS_ABORT)
479 if (!TransactionIdIsValid(s->transactionId))
480 continue; /* it can't have any child XIDs either */
481 if (TransactionIdEquals(xid, s->transactionId))
483 foreach(cell, s->childXids)
485 if (TransactionIdEquals(xid, lfirst_xid(cell)))
495 * CommandCounterIncrement
498 CommandCounterIncrement(void)
500 currentCommandId += 1;
501 if (currentCommandId == FirstCommandId) /* check for overflow */
503 currentCommandId -= 1;
505 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
506 errmsg("cannot have more than 2^32-1 commands in a transaction")));
509 /* Propagate new command ID into static snapshots, if set */
510 if (SerializableSnapshot)
511 SerializableSnapshot->curcid = currentCommandId;
513 LatestSnapshot->curcid = currentCommandId;
516 * make cache changes visible to me.
518 AtCommit_LocalCache();
523 /* ----------------------------------------------------------------
524 * StartTransaction stuff
525 * ----------------------------------------------------------------
534 AcceptInvalidationMessages();
543 TransactionState s = CurrentTransactionState;
546 * We shouldn't have a transaction context already.
548 Assert(TopTransactionContext == NULL);
551 * Create a toplevel context for the transaction.
553 TopTransactionContext =
554 AllocSetContextCreate(TopMemoryContext,
555 "TopTransactionContext",
556 ALLOCSET_DEFAULT_MINSIZE,
557 ALLOCSET_DEFAULT_INITSIZE,
558 ALLOCSET_DEFAULT_MAXSIZE);
561 * In a top-level transaction, CurTransactionContext is the same as
562 * TopTransactionContext.
564 CurTransactionContext = TopTransactionContext;
565 s->curTransactionContext = CurTransactionContext;
567 /* Make the CurTransactionContext active. */
568 MemoryContextSwitchTo(CurTransactionContext);
572 * AtStart_ResourceOwner
575 AtStart_ResourceOwner(void)
577 TransactionState s = CurrentTransactionState;
580 * We shouldn't have a transaction resource owner already.
582 Assert(TopTransactionResourceOwner == NULL);
585 * Create a toplevel resource owner for the transaction.
587 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
589 TopTransactionResourceOwner = s->curTransactionOwner;
590 CurTransactionResourceOwner = s->curTransactionOwner;
591 CurrentResourceOwner = s->curTransactionOwner;
594 /* ----------------------------------------------------------------
595 * StartSubTransaction stuff
596 * ----------------------------------------------------------------
603 AtSubStart_Memory(void)
605 TransactionState s = CurrentTransactionState;
607 Assert(CurTransactionContext != NULL);
610 * Create a CurTransactionContext, which will be used to hold data
611 * that survives subtransaction commit but disappears on
612 * subtransaction abort. We make it a child of the immediate parent's
613 * CurTransactionContext.
615 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
616 "CurTransactionContext",
617 ALLOCSET_DEFAULT_MINSIZE,
618 ALLOCSET_DEFAULT_INITSIZE,
619 ALLOCSET_DEFAULT_MAXSIZE);
620 s->curTransactionContext = CurTransactionContext;
622 /* Make the CurTransactionContext active. */
623 MemoryContextSwitchTo(CurTransactionContext);
627 * AtSubStart_ResourceOwner
630 AtSubStart_ResourceOwner(void)
632 TransactionState s = CurrentTransactionState;
634 Assert(s->parent != NULL);
637 * Create a resource owner for the subtransaction. We make it a child
638 * of the immediate parent's resource owner.
640 s->curTransactionOwner =
641 ResourceOwnerCreate(s->parent->curTransactionOwner,
644 CurTransactionResourceOwner = s->curTransactionOwner;
645 CurrentResourceOwner = s->curTransactionOwner;
648 /* ----------------------------------------------------------------
649 * CommitTransaction stuff
650 * ----------------------------------------------------------------
654 * RecordTransactionCommit
657 RecordTransactionCommit(void)
662 TransactionId *children;
664 /* Get data needed for commit record */
665 nrels = smgrGetPendingDeletes(true, &rels);
666 nchildren = xactGetCommittedChildren(&children);
669 * If we made neither any XLOG entries nor any temp-rel updates, and
670 * have no files to be deleted, we can omit recording the transaction
671 * commit at all. (This test includes the effects of subtransactions,
672 * so the presence of committed subxacts need not alone force a
675 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
677 TransactionId xid = GetCurrentTransactionId();
681 /* Tell bufmgr and smgr to prepare for commit */
684 START_CRIT_SECTION();
687 * If our transaction made any transaction-controlled XLOG
688 * entries, we need to lock out checkpoint start between writing
689 * our XLOG record and updating pg_clog. Otherwise it is possible
690 * for the checkpoint to set REDO after the XLOG record but fail
691 * to flush the pg_clog update to disk, leading to loss of the
692 * transaction commit if we crash a little later. Slightly klugy
693 * fix for problem discovered 2004-08-10.
695 * (If it made no transaction-controlled XLOG entries, its XID
696 * appears nowhere in permanent storage, so no one else will ever
697 * care if it committed; so it doesn't matter if we lose the
700 * Note we only need a shared lock.
702 madeTCentries = (MyLastRecPtr.xrecoff != 0);
704 LWLockAcquire(CheckpointStartLock, LW_SHARED);
707 * We only need to log the commit in XLOG if the transaction made
708 * any transaction-controlled XLOG entries or will delete files.
710 if (madeTCentries || nrels > 0)
712 XLogRecData rdata[3];
714 xl_xact_commit xlrec;
716 xlrec.xtime = time(NULL);
718 xlrec.nsubxacts = nchildren;
719 rdata[0].data = (char *) (&xlrec);
720 rdata[0].len = MinSizeOfXactCommit;
721 rdata[0].buffer = InvalidBuffer;
722 /* dump rels to delete */
725 rdata[0].next = &(rdata[1]);
726 rdata[1].data = (char *) rels;
727 rdata[1].len = nrels * sizeof(RelFileNode);
728 rdata[1].buffer = InvalidBuffer;
731 /* dump committed child Xids */
734 rdata[lastrdata].next = &(rdata[2]);
735 rdata[2].data = (char *) children;
736 rdata[2].len = nchildren * sizeof(TransactionId);
737 rdata[2].buffer = InvalidBuffer;
740 rdata[lastrdata].next = NULL;
742 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
746 /* Just flush through last record written by me */
747 recptr = ProcLastRecEnd;
751 * We must flush our XLOG entries to disk if we made any XLOG
752 * entries, whether in or out of transaction control. For
753 * example, if we reported a nextval() result to the client, this
754 * ensures that any XLOG record generated by nextval will hit the
755 * disk before we report the transaction committed.
757 * Note: if we generated a commit record above, MyXactMadeXLogEntry
758 * will certainly be set now.
760 if (MyXactMadeXLogEntry)
763 * Sleep before flush! So we can flush more than one commit
764 * records per single fsync. (The idea is some other backend
765 * may do the XLogFlush while we're sleeping. This needs work
766 * still, because on most Unixen, the minimum select() delay
767 * is 10msec or more, which is way too long.)
769 * We do not sleep if enableFsync is not turned on, nor if there
770 * are fewer than CommitSiblings other backends with active
773 if (CommitDelay > 0 && enableFsync &&
774 CountActiveBackends() >= CommitSiblings)
775 pg_usleep(CommitDelay);
781 * We must mark the transaction committed in clog if its XID
782 * appears either in permanent rels or in local temporary rels. We
783 * test this by seeing if we made transaction-controlled entries
784 * *OR* local-rel tuple updates. Note that if we made only the
785 * latter, we have not emitted an XLOG record for our commit, and
786 * so in the event of a crash the clog update might be lost. This
787 * is okay because no one else will ever care whether we
790 if (madeTCentries || MyXactMadeTempRelUpdate)
792 TransactionIdCommit(xid);
793 /* to avoid race conditions, the parent must commit first */
794 TransactionIdCommitTree(nchildren, children);
797 /* Unlock checkpoint lock if we acquired it */
799 LWLockRelease(CheckpointStartLock);
804 /* Break the chain of back-links in the XLOG records I output */
805 MyLastRecPtr.xrecoff = 0;
806 MyXactMadeXLogEntry = false;
807 MyXactMadeTempRelUpdate = false;
809 /* And clean up local data */
818 * AtCommit_LocalCache
821 AtCommit_LocalCache(void)
824 * Make catalog changes visible to me for the next command.
826 CommandEndInvalidationMessages();
833 AtCommit_Memory(void)
836 * Now that we're "out" of a transaction, have the system allocate
837 * things in the top memory context instead of per-transaction
840 MemoryContextSwitchTo(TopMemoryContext);
843 * Release all transaction-local memory.
845 Assert(TopTransactionContext != NULL);
846 MemoryContextDelete(TopTransactionContext);
847 TopTransactionContext = NULL;
848 CurTransactionContext = NULL;
849 CurrentTransactionState->curTransactionContext = NULL;
852 /* ----------------------------------------------------------------
853 * CommitSubTransaction stuff
854 * ----------------------------------------------------------------
861 AtSubCommit_Memory(void)
863 TransactionState s = CurrentTransactionState;
865 Assert(s->parent != NULL);
867 /* Return to parent transaction level's memory context. */
868 CurTransactionContext = s->parent->curTransactionContext;
869 MemoryContextSwitchTo(CurTransactionContext);
872 * Ordinarily we cannot throw away the child's CurTransactionContext,
873 * since the data it contains will be needed at upper commit. However,
874 * if there isn't actually anything in it, we can throw it away. This
875 * avoids a small memory leak in the common case of "trivial" subxacts.
877 if (MemoryContextIsEmpty(s->curTransactionContext))
879 MemoryContextDelete(s->curTransactionContext);
880 s->curTransactionContext = NULL;
885 * AtSubCommit_childXids
887 * Pass my own XID and my child XIDs up to my parent as committed children.
890 AtSubCommit_childXids(void)
892 TransactionState s = CurrentTransactionState;
893 MemoryContext old_cxt;
895 Assert(s->parent != NULL);
898 * We keep the child-XID lists in TopTransactionContext; this avoids
899 * setting up child-transaction contexts for what might be just a few
900 * bytes of grandchild XIDs.
902 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
904 s->parent->childXids = lappend_xid(s->parent->childXids,
907 if (s->childXids != NIL)
909 s->parent->childXids = list_concat(s->parent->childXids,
912 * list_concat doesn't free the list header for the second list;
913 * do so here to avoid memory leakage (kluge)
919 MemoryContextSwitchTo(old_cxt);
923 * RecordSubTransactionCommit
926 RecordSubTransactionCommit(void)
929 * We do not log the subcommit in XLOG; it doesn't matter until the
930 * top-level transaction commits.
932 * We must mark the subtransaction subcommitted in clog if its XID
933 * appears either in permanent rels or in local temporary rels. We
934 * test this by seeing if we made transaction-controlled entries *OR*
935 * local-rel tuple updates. (The test here actually covers the entire
936 * transaction tree so far, so it may mark subtransactions that don't
937 * really need it, but it's probably not worth being tenser. Note that
938 * if a prior subtransaction dirtied these variables, then
939 * RecordTransactionCommit will have to do the full pushup anyway...)
941 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
943 TransactionId xid = GetCurrentTransactionId();
945 /* XXX does this really need to be a critical section? */
946 START_CRIT_SECTION();
948 /* Record subtransaction subcommit */
949 TransactionIdSubCommit(xid);
955 /* ----------------------------------------------------------------
956 * AbortTransaction stuff
957 * ----------------------------------------------------------------
961 * RecordTransactionAbort
964 RecordTransactionAbort(void)
969 TransactionId *children;
971 /* Get data needed for abort record */
972 nrels = smgrGetPendingDeletes(false, &rels);
973 nchildren = xactGetCommittedChildren(&children);
976 * If we made neither any transaction-controlled XLOG entries nor any
977 * temp-rel updates, and are not going to delete any files, we can
978 * omit recording the transaction abort at all. No one will ever care
979 * that it aborted. (These tests cover our whole transaction tree.)
981 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
983 TransactionId xid = GetCurrentTransactionId();
986 * Catch the scenario where we aborted partway through
987 * RecordTransactionCommit ...
989 if (TransactionIdDidCommit(xid))
990 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
992 START_CRIT_SECTION();
995 * We only need to log the abort in XLOG if the transaction made
996 * any transaction-controlled XLOG entries or will delete files.
997 * (If it made no transaction-controlled XLOG entries, its XID
998 * appears nowhere in permanent storage, so no one else will ever
999 * care if it committed.)
1001 * We do not flush XLOG to disk unless deleting files, since the
1002 * default assumption after a crash would be that we aborted,
1003 * anyway. For the same reason, we don't need to worry about
1004 * interlocking against checkpoint start.
1006 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1008 XLogRecData rdata[3];
1010 xl_xact_abort xlrec;
1013 xlrec.xtime = time(NULL);
1014 xlrec.nrels = nrels;
1015 xlrec.nsubxacts = nchildren;
1016 rdata[0].data = (char *) (&xlrec);
1017 rdata[0].len = MinSizeOfXactAbort;
1018 rdata[0].buffer = InvalidBuffer;
1019 /* dump rels to delete */
1022 rdata[0].next = &(rdata[1]);
1023 rdata[1].data = (char *) rels;
1024 rdata[1].len = nrels * sizeof(RelFileNode);
1025 rdata[1].buffer = InvalidBuffer;
1028 /* dump committed child Xids */
1031 rdata[lastrdata].next = &(rdata[2]);
1032 rdata[2].data = (char *) children;
1033 rdata[2].len = nchildren * sizeof(TransactionId);
1034 rdata[2].buffer = InvalidBuffer;
1037 rdata[lastrdata].next = NULL;
1039 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1041 /* Must flush if we are deleting files... */
1047 * Mark the transaction aborted in clog. This is not absolutely
1048 * necessary but we may as well do it while we are here.
1050 * The ordering here isn't critical but it seems best to mark the
1051 * parent first. This assures an atomic transition of all the
1052 * subtransactions to aborted state from the point of view of
1053 * concurrent TransactionIdDidAbort calls.
1055 TransactionIdAbort(xid);
1056 TransactionIdAbortTree(nchildren, children);
1061 /* Break the chain of back-links in the XLOG records I output */
1062 MyLastRecPtr.xrecoff = 0;
1063 MyXactMadeXLogEntry = false;
1064 MyXactMadeTempRelUpdate = false;
1066 /* And clean up local data */
1077 AtAbort_Memory(void)
1080 * Make sure we are in a valid context (not a child of
1081 * TopTransactionContext...). Note that it is possible for this code
1082 * to be called when we aren't in a transaction at all; go directly to
1083 * TopMemoryContext in that case.
1085 if (TopTransactionContext != NULL)
1087 MemoryContextSwitchTo(TopTransactionContext);
1090 * We do not want to destroy the transaction's global state yet,
1091 * so we can't free any memory here.
1095 MemoryContextSwitchTo(TopMemoryContext);
1102 AtSubAbort_Memory(void)
1104 Assert(TopTransactionContext != NULL);
1106 MemoryContextSwitchTo(TopTransactionContext);
1111 * AtAbort_ResourceOwner
1114 AtAbort_ResourceOwner(void)
1117 * Make sure we have a valid ResourceOwner, if possible (else it
1118 * will be NULL, which is OK)
1120 CurrentResourceOwner = TopTransactionResourceOwner;
1124 * AtSubAbort_ResourceOwner
1127 AtSubAbort_ResourceOwner(void)
1129 TransactionState s = CurrentTransactionState;
1131 /* Make sure we have a valid ResourceOwner */
1132 CurrentResourceOwner = s->curTransactionOwner;
1137 * AtSubAbort_childXids
1140 AtSubAbort_childXids(void)
1142 TransactionState s = CurrentTransactionState;
1145 * We keep the child-XID lists in TopTransactionContext (see
1146 * AtSubCommit_childXids). This means we'd better free the list
1147 * explicitly at abort to avoid leakage.
1149 list_free(s->childXids);
1154 * RecordSubTransactionAbort
1157 RecordSubTransactionAbort(void)
1161 TransactionId xid = GetCurrentTransactionId();
1163 TransactionId *children;
1165 /* Get data needed for abort record */
1166 nrels = smgrGetPendingDeletes(false, &rels);
1167 nchildren = xactGetCommittedChildren(&children);
1170 * If we made neither any transaction-controlled XLOG entries nor any
1171 * temp-rel updates, and are not going to delete any files, we can
1172 * omit recording the transaction abort at all. No one will ever care
1173 * that it aborted. (These tests cover our whole transaction tree,
1174 * and therefore may mark subxacts that don't really need it, but it's
1175 * probably not worth being tenser.)
1177 * In this case we needn't worry about marking subcommitted children as
1178 * aborted, because they didn't mark themselves as subcommitted in the
1179 * first place; see the optimization in RecordSubTransactionCommit.
1181 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1183 START_CRIT_SECTION();
1186 * We only need to log the abort in XLOG if the transaction made
1187 * any transaction-controlled XLOG entries or will delete files.
1189 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1191 XLogRecData rdata[3];
1193 xl_xact_abort xlrec;
1196 xlrec.xtime = time(NULL);
1197 xlrec.nrels = nrels;
1198 xlrec.nsubxacts = nchildren;
1199 rdata[0].data = (char *) (&xlrec);
1200 rdata[0].len = MinSizeOfXactAbort;
1201 rdata[0].buffer = InvalidBuffer;
1202 /* dump rels to delete */
1205 rdata[0].next = &(rdata[1]);
1206 rdata[1].data = (char *) rels;
1207 rdata[1].len = nrels * sizeof(RelFileNode);
1208 rdata[1].buffer = InvalidBuffer;
1211 /* dump committed child Xids */
1214 rdata[lastrdata].next = &(rdata[2]);
1215 rdata[2].data = (char *) children;
1216 rdata[2].len = nchildren * sizeof(TransactionId);
1217 rdata[2].buffer = InvalidBuffer;
1220 rdata[lastrdata].next = NULL;
1222 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1224 /* Must flush if we are deleting files... */
1230 * Mark the transaction aborted in clog. This is not absolutely
1231 * necessary but XactLockTableWait makes use of it to avoid waiting
1232 * for already-aborted subtransactions.
1234 TransactionIdAbort(xid);
1235 TransactionIdAbortTree(nchildren, children);
1241 * We can immediately remove failed XIDs from PGPROC's cache of
1242 * running child XIDs. It's easiest to do it here while we have the
1243 * child XID array at hand, even though in the main-transaction case
1244 * the equivalent work happens just after return from
1245 * RecordTransactionAbort.
1247 XidCacheRemoveRunningXids(xid, nchildren, children);
1249 /* And clean up local data */
1256 /* ----------------------------------------------------------------
1257 * CleanupTransaction stuff
1258 * ----------------------------------------------------------------
1265 AtCleanup_Memory(void)
1268 * Now that we're "out" of a transaction, have the system allocate
1269 * things in the top memory context instead of per-transaction
1272 MemoryContextSwitchTo(TopMemoryContext);
1274 Assert(CurrentTransactionState->parent == NULL);
1277 * Release all transaction-local memory.
1279 if (TopTransactionContext != NULL)
1280 MemoryContextDelete(TopTransactionContext);
1281 TopTransactionContext = NULL;
1282 CurTransactionContext = NULL;
1283 CurrentTransactionState->curTransactionContext = NULL;
1287 /* ----------------------------------------------------------------
1288 * CleanupSubTransaction stuff
1289 * ----------------------------------------------------------------
1293 * AtSubCleanup_Memory
1296 AtSubCleanup_Memory(void)
1298 TransactionState s = CurrentTransactionState;
1300 Assert(s->parent != NULL);
1302 /* Make sure we're not in an about-to-be-deleted context */
1303 MemoryContextSwitchTo(s->parent->curTransactionContext);
1304 CurTransactionContext = s->parent->curTransactionContext;
1307 * Delete the subxact local memory contexts. Its CurTransactionContext
1308 * can go too (note this also kills CurTransactionContexts from any
1309 * children of the subxact).
1311 if (s->curTransactionContext)
1312 MemoryContextDelete(s->curTransactionContext);
1313 s->curTransactionContext = NULL;
1316 /* ----------------------------------------------------------------
1317 * interface routines
1318 * ----------------------------------------------------------------
1325 StartTransaction(void)
1330 * Let's just make sure the state stack is empty
1332 s = &TopTransactionStateData;
1333 CurrentTransactionState = s;
1336 * check the current transaction state
1338 if (s->state != TRANS_DEFAULT)
1339 elog(WARNING, "StartTransaction while in %s state",
1340 TransStateAsString(s->state));
1343 * set the current transaction state information appropriately during
1346 s->state = TRANS_START;
1347 s->transactionId = InvalidTransactionId; /* until assigned */
1350 * Make sure we've freed any old snapshot, and reset xact state
1354 XactIsoLevel = DefaultXactIsoLevel;
1355 XactReadOnly = DefaultXactReadOnly;
1358 * reinitialize within-transaction counters
1360 s->subTransactionId = TopSubTransactionId;
1361 currentSubTransactionId = TopSubTransactionId;
1362 currentCommandId = FirstCommandId;
1365 * must initialize resource-management stuff first
1368 AtStart_ResourceOwner();
1371 * generate a new transaction id
1373 s->transactionId = GetNewTransactionId(false);
1375 XactLockTableInsert(s->transactionId);
1380 xactStartTimestamp = GetCurrentTimestamp();
1383 * initialize current transaction state fields
1385 s->nestingLevel = 1;
1389 * You might expect to see "s->currentUser = GetUserId();" here, but
1390 * you won't because it doesn't work during startup; the userid isn't
1391 * set yet during a backend's first transaction start. We only use
1392 * the currentUser field in sub-transaction state structs.
1394 * prevXactReadOnly is also valid only in sub-transactions.
1398 * initialize other subsystems for new transaction
1402 AfterTriggerBeginXact();
1405 * done with start processing, set current transaction state to "in
1408 s->state = TRANS_INPROGRESS;
1410 ShowTransactionState("StartTransaction");
1417 * NB: if you change this routine, better look at PrepareTransaction too!
1420 CommitTransaction(void)
1422 TransactionState s = CurrentTransactionState;
1424 ShowTransactionState("CommitTransaction");
1427 * check the current transaction state
1429 if (s->state != TRANS_INPROGRESS)
1430 elog(WARNING, "CommitTransaction while in %s state",
1431 TransStateAsString(s->state));
1432 Assert(s->parent == NULL);
1435 * Do pre-commit processing (most of this stuff requires database
1436 * access, and in fact could still cause an error...)
1438 * It is possible for CommitHoldablePortals to invoke functions that
1439 * queue deferred triggers, and it's also possible that triggers create
1440 * holdable cursors. So we have to loop until there's nothing left to
1446 * Fire all currently pending deferred triggers.
1448 AfterTriggerFireDeferred();
1451 * Convert any open holdable cursors into static portals. If there
1452 * weren't any, we are done ... otherwise loop back to check if they
1453 * queued deferred triggers. Lather, rinse, repeat.
1455 if (!CommitHoldablePortals())
1459 /* Now we can shut down the deferred-trigger manager */
1460 AfterTriggerEndXact(true);
1462 /* Close any open regular cursors */
1466 * Let ON COMMIT management do its thing (must happen after closing
1467 * cursors, to avoid dangling-reference problems)
1469 PreCommit_on_commit_actions();
1471 /* close large objects before lower-level cleanup */
1472 AtEOXact_LargeObject(true);
1474 /* NOTIFY commit must come before lower-level cleanup */
1478 * Update flat files if we changed pg_database, pg_authid or
1479 * pg_auth_members. This should be the last step before commit.
1481 AtEOXact_UpdateFlatFiles(true);
1483 /* Prevent cancel/die interrupt while cleaning up */
1487 * set the current transaction state information appropriately during
1490 s->state = TRANS_COMMIT;
1493 * Here is where we really truly commit.
1495 RecordTransactionCommit();
1498 * Let others know about no transaction in progress by me. Note that
1499 * this must be done _before_ releasing locks we hold and _after_
1500 * RecordTransactionCommit.
1502 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1503 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1504 * xid 1 is doing commit while xid 2 gets snapshot.
1505 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1506 * xid 0 as running as well, or it will be able to see two tuple versions
1507 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1510 * Note: MyProc may be null during bootstrap.
1515 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1516 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1517 MyProc->xid = InvalidTransactionId;
1518 MyProc->xmin = InvalidTransactionId;
1520 /* Clear the subtransaction-XID cache too while holding the lock */
1521 MyProc->subxids.nxids = 0;
1522 MyProc->subxids.overflowed = false;
1524 LWLockRelease(ProcArrayLock);
1528 * This is all post-commit cleanup. Note that if an error is raised
1529 * here, it's too late to abort the transaction. This should be just
1530 * noncritical resource releasing.
1532 * The ordering of operations is not entirely random. The idea is:
1533 * release resources visible to other backends (eg, files, buffer
1534 * pins); then release locks; then release backend-local resources. We
1535 * want to release locks at the point where any backend waiting for us
1536 * will see our transaction as being fully cleaned up.
1538 * Resources that can be associated with individual queries are handled
1539 * by the ResourceOwner mechanism. The other calls here are for
1540 * backend-wide state.
1543 CallXactCallbacks(XACT_EVENT_COMMIT);
1545 ResourceOwnerRelease(TopTransactionResourceOwner,
1546 RESOURCE_RELEASE_BEFORE_LOCKS,
1549 /* Check we've released all buffer pins */
1550 AtEOXact_Buffers(true);
1552 /* Clean up the relation cache */
1553 AtEOXact_RelationCache(true);
1556 * Make catalog changes visible to all backends. This has to happen
1557 * after relcache references are dropped (see comments for
1558 * AtEOXact_RelationCache), but before locks are released (if anyone
1559 * is waiting for lock on a relation we've modified, we want them to
1560 * know about the catalog change before they start using the
1563 AtEOXact_Inval(true);
1566 * Likewise, dropping of files deleted during the transaction is best done
1567 * after releasing relcache and buffer pins. (This is not strictly
1568 * necessary during commit, since such pins should have been released
1569 * already, but this ordering is definitely critical during abort.)
1571 smgrDoPendingDeletes(true);
1573 AtEOXact_MultiXact();
1575 ResourceOwnerRelease(TopTransactionResourceOwner,
1576 RESOURCE_RELEASE_LOCKS,
1578 ResourceOwnerRelease(TopTransactionResourceOwner,
1579 RESOURCE_RELEASE_AFTER_LOCKS,
1582 /* Check we've released all catcache entries */
1583 AtEOXact_CatCache(true);
1585 AtEOXact_GUC(true, false);
1587 AtEOXact_on_commit_actions(true);
1588 AtEOXact_Namespace(true);
1589 /* smgrcommit already done */
1591 pgstat_count_xact_commit();
1593 CurrentResourceOwner = NULL;
1594 ResourceOwnerDelete(TopTransactionResourceOwner);
1595 s->curTransactionOwner = NULL;
1596 CurTransactionResourceOwner = NULL;
1597 TopTransactionResourceOwner = NULL;
1601 s->transactionId = InvalidTransactionId;
1602 s->subTransactionId = InvalidSubTransactionId;
1603 s->nestingLevel = 0;
1607 * done with commit processing, set current transaction state back to
1610 s->state = TRANS_DEFAULT;
1612 RESUME_INTERRUPTS();
1617 * PrepareTransaction
1619 * NB: if you change this routine, better look at CommitTransaction too!
1622 PrepareTransaction(void)
1624 TransactionState s = CurrentTransactionState;
1625 TransactionId xid = GetCurrentTransactionId();
1626 GlobalTransaction gxact;
1627 TimestampTz prepared_at;
1629 ShowTransactionState("PrepareTransaction");
1632 * check the current transaction state
1634 if (s->state != TRANS_INPROGRESS)
1635 elog(WARNING, "PrepareTransaction while in %s state",
1636 TransStateAsString(s->state));
1637 Assert(s->parent == NULL);
1640 * Do pre-commit processing (most of this stuff requires database
1641 * access, and in fact could still cause an error...)
1643 * It is possible for PrepareHoldablePortals to invoke functions that
1644 * queue deferred triggers, and it's also possible that triggers create
1645 * holdable cursors. So we have to loop until there's nothing left to
1651 * Fire all currently pending deferred triggers.
1653 AfterTriggerFireDeferred();
1656 * Convert any open holdable cursors into static portals. If there
1657 * weren't any, we are done ... otherwise loop back to check if they
1658 * queued deferred triggers. Lather, rinse, repeat.
1660 if (!PrepareHoldablePortals())
1664 /* Now we can shut down the deferred-trigger manager */
1665 AfterTriggerEndXact(true);
1667 /* Close any open regular cursors */
1671 * Let ON COMMIT management do its thing (must happen after closing
1672 * cursors, to avoid dangling-reference problems)
1674 PreCommit_on_commit_actions();
1676 /* close large objects before lower-level cleanup */
1677 AtEOXact_LargeObject(true);
1679 /* NOTIFY and flatfiles will be handled below */
1681 /* Prevent cancel/die interrupt while cleaning up */
1685 * set the current transaction state information appropriately during
1686 * prepare processing
1688 s->state = TRANS_PREPARE;
1690 prepared_at = GetCurrentTimestamp();
1692 /* Tell bufmgr and smgr to prepare for commit */
1696 * Reserve the GID for this transaction. This could fail if the
1697 * requested GID is invalid or already in use.
1699 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1700 GetUserId(), MyDatabaseId);
1704 * Collect data for the 2PC state file. Note that in general, no actual
1705 * state change should happen in the called modules during this step,
1706 * since it's still possible to fail before commit, and in that case we
1707 * want transaction abort to be able to clean up. (In particular, the
1708 * AtPrepare routines may error out if they find cases they cannot
1709 * handle.) State cleanup should happen in the PostPrepare routines
1710 * below. However, some modules can go ahead and clear state here
1711 * because they wouldn't do anything with it during abort anyway.
1713 * Note: because the 2PC state file records will be replayed in the same
1714 * order they are made, the order of these calls has to match the order
1715 * in which we want things to happen during COMMIT PREPARED or
1716 * ROLLBACK PREPARED; in particular, pay attention to whether things
1717 * should happen before or after releasing the transaction's locks.
1719 StartPrepare(gxact);
1722 AtPrepare_UpdateFlatFiles();
1727 * Here is where we really truly prepare.
1729 * We have to record transaction prepares even if we didn't
1730 * make any updates, because the transaction manager might
1731 * get confused if we lose a global transaction.
1736 * Now we clean up backend-internal state and release internal
1740 /* Break the chain of back-links in the XLOG records I output */
1741 MyLastRecPtr.xrecoff = 0;
1742 MyXactMadeXLogEntry = false;
1743 MyXactMadeTempRelUpdate = false;
1746 * Let others know about no transaction in progress by me. This has
1747 * to be done *after* the prepared transaction has been marked valid,
1748 * else someone may think it is unlocked and recyclable.
1751 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1752 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1753 MyProc->xid = InvalidTransactionId;
1754 MyProc->xmin = InvalidTransactionId;
1756 /* Clear the subtransaction-XID cache too while holding the lock */
1757 MyProc->subxids.nxids = 0;
1758 MyProc->subxids.overflowed = false;
1760 LWLockRelease(ProcArrayLock);
1763 * This is all post-transaction cleanup. Note that if an error is raised
1764 * here, it's too late to abort the transaction. This should be just
1765 * noncritical resource releasing. See notes in CommitTransaction.
1768 CallXactCallbacks(XACT_EVENT_PREPARE);
1770 ResourceOwnerRelease(TopTransactionResourceOwner,
1771 RESOURCE_RELEASE_BEFORE_LOCKS,
1774 /* Check we've released all buffer pins */
1775 AtEOXact_Buffers(true);
1777 /* Clean up the relation cache */
1778 AtEOXact_RelationCache(true);
1780 /* notify and flatfiles don't need a postprepare call */
1782 PostPrepare_Inval();
1786 AtEOXact_MultiXact();
1788 PostPrepare_Locks(xid);
1790 ResourceOwnerRelease(TopTransactionResourceOwner,
1791 RESOURCE_RELEASE_LOCKS,
1793 ResourceOwnerRelease(TopTransactionResourceOwner,
1794 RESOURCE_RELEASE_AFTER_LOCKS,
1797 /* Check we've released all catcache entries */
1798 AtEOXact_CatCache(true);
1800 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1801 AtEOXact_GUC(true, false);
1803 AtEOXact_on_commit_actions(true);
1804 AtEOXact_Namespace(true);
1805 /* smgrcommit already done */
1808 CurrentResourceOwner = NULL;
1809 ResourceOwnerDelete(TopTransactionResourceOwner);
1810 s->curTransactionOwner = NULL;
1811 CurTransactionResourceOwner = NULL;
1812 TopTransactionResourceOwner = NULL;
1816 s->transactionId = InvalidTransactionId;
1817 s->subTransactionId = InvalidSubTransactionId;
1818 s->nestingLevel = 0;
1822 * done with 1st phase commit processing, set current transaction
1823 * state back to default
1825 s->state = TRANS_DEFAULT;
1827 RESUME_INTERRUPTS();
1835 AbortTransaction(void)
1837 TransactionState s = CurrentTransactionState;
1839 /* Prevent cancel/die interrupt while cleaning up */
1843 * Release any LW locks we might be holding as quickly as possible.
1844 * (Regular locks, however, must be held till we finish aborting.)
1845 * Releasing LW locks is critical since we might try to grab them
1846 * again while cleaning up!
1850 /* Clean up buffer I/O and buffer context locks, too */
1855 * Also clean up any open wait for lock, since the lock manager will
1856 * choke if we try to wait for another lock before doing this.
1861 * check the current transaction state
1863 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1864 elog(WARNING, "AbortTransaction while in %s state",
1865 TransStateAsString(s->state));
1866 Assert(s->parent == NULL);
1869 * set the current transaction state information appropriately during
1870 * the abort processing
1872 s->state = TRANS_ABORT;
1874 /* Make sure we have a valid memory context and resource owner */
1876 AtAbort_ResourceOwner();
1879 * Reset user id which might have been changed transiently. We cannot
1880 * use s->currentUser, since it may not be set yet; instead rely on
1881 * internal state of miscinit.c.
1883 * (Note: it is not necessary to restore session authorization here
1884 * because that can only be changed via GUC, and GUC will take care of
1885 * rolling it back if need be. However, an error within a SECURITY
1886 * DEFINER function could send control here with the wrong current
1892 * do abort processing
1894 AfterTriggerEndXact(false);
1896 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1898 AtEOXact_UpdateFlatFiles(false);
1901 * Advertise the fact that we aborted in pg_clog (assuming that we
1902 * got as far as assigning an XID to advertise).
1904 if (TransactionIdIsValid(s->transactionId))
1905 RecordTransactionAbort();
1908 * Let others know about no transaction in progress by me. Note that
1909 * this must be done _before_ releasing locks we hold and _after_
1910 * RecordTransactionAbort.
1914 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1915 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1916 MyProc->xid = InvalidTransactionId;
1917 MyProc->xmin = InvalidTransactionId;
1919 /* Clear the subtransaction-XID cache too while holding the lock */
1920 MyProc->subxids.nxids = 0;
1921 MyProc->subxids.overflowed = false;
1923 LWLockRelease(ProcArrayLock);
1927 * Post-abort cleanup. See notes in CommitTransaction() concerning
1931 CallXactCallbacks(XACT_EVENT_ABORT);
1933 ResourceOwnerRelease(TopTransactionResourceOwner,
1934 RESOURCE_RELEASE_BEFORE_LOCKS,
1936 AtEOXact_Buffers(false);
1937 AtEOXact_RelationCache(false);
1938 AtEOXact_Inval(false);
1939 smgrDoPendingDeletes(false);
1940 AtEOXact_MultiXact();
1941 ResourceOwnerRelease(TopTransactionResourceOwner,
1942 RESOURCE_RELEASE_LOCKS,
1944 ResourceOwnerRelease(TopTransactionResourceOwner,
1945 RESOURCE_RELEASE_AFTER_LOCKS,
1947 AtEOXact_CatCache(false);
1949 AtEOXact_GUC(false, false);
1950 AtEOXact_SPI(false);
1951 AtEOXact_on_commit_actions(false);
1952 AtEOXact_Namespace(false);
1955 pgstat_count_xact_rollback();
1958 * State remains TRANS_ABORT until CleanupTransaction().
1960 RESUME_INTERRUPTS();
1964 * CleanupTransaction
1967 CleanupTransaction(void)
1969 TransactionState s = CurrentTransactionState;
1972 * State should still be TRANS_ABORT from AbortTransaction().
1974 if (s->state != TRANS_ABORT)
1975 elog(FATAL, "CleanupTransaction: unexpected state %s",
1976 TransStateAsString(s->state));
1979 * do abort cleanup processing
1981 AtCleanup_Portals(); /* now safe to release portal memory */
1983 CurrentResourceOwner = NULL; /* and resource owner */
1984 if (TopTransactionResourceOwner)
1985 ResourceOwnerDelete(TopTransactionResourceOwner);
1986 s->curTransactionOwner = NULL;
1987 CurTransactionResourceOwner = NULL;
1988 TopTransactionResourceOwner = NULL;
1990 AtCleanup_Memory(); /* and transaction memory */
1992 s->transactionId = InvalidTransactionId;
1993 s->subTransactionId = InvalidSubTransactionId;
1994 s->nestingLevel = 0;
1998 * done with abort processing, set current transaction state back to
2001 s->state = TRANS_DEFAULT;
2005 * StartTransactionCommand
2008 StartTransactionCommand(void)
2010 TransactionState s = CurrentTransactionState;
2012 switch (s->blockState)
2015 * if we aren't in a transaction block, we just do our usual
2016 * start transaction.
2018 case TBLOCK_DEFAULT:
2020 s->blockState = TBLOCK_STARTED;
2024 * We are somewhere in a transaction block or subtransaction
2025 * and about to start a new command. For now we do nothing,
2026 * but someday we may do command-local resource initialization.
2027 * (Note that any needed CommandCounterIncrement was done by
2028 * the previous CommitTransactionCommand.)
2030 case TBLOCK_INPROGRESS:
2031 case TBLOCK_SUBINPROGRESS:
2035 * Here we are in a failed transaction block (one of
2036 * the commands caused an abort) so we do nothing but remain in
2037 * the abort state. Eventually we will get a ROLLBACK command
2038 * which will get us out of this state. (It is up to other
2039 * code to ensure that no commands other than ROLLBACK will be
2040 * processed in these states.)
2043 case TBLOCK_SUBABORT:
2046 /* These cases are invalid. */
2047 case TBLOCK_STARTED:
2049 case TBLOCK_SUBBEGIN:
2052 case TBLOCK_ABORT_END:
2053 case TBLOCK_SUBABORT_END:
2054 case TBLOCK_ABORT_PENDING:
2055 case TBLOCK_SUBABORT_PENDING:
2056 case TBLOCK_SUBRESTART:
2057 case TBLOCK_SUBABORT_RESTART:
2058 case TBLOCK_PREPARE:
2059 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2060 BlockStateAsString(s->blockState));
2065 * We must switch to CurTransactionContext before returning. This is
2066 * already done if we called StartTransaction, otherwise not.
2068 Assert(CurTransactionContext != NULL);
2069 MemoryContextSwitchTo(CurTransactionContext);
2073 * CommitTransactionCommand
2076 CommitTransactionCommand(void)
2078 TransactionState s = CurrentTransactionState;
2080 switch (s->blockState)
2083 * This shouldn't happen, because it means the previous
2084 * StartTransactionCommand didn't set the STARTED state
2087 case TBLOCK_DEFAULT:
2088 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2089 BlockStateAsString(s->blockState));
2093 * If we aren't in a transaction block, just do our usual
2094 * transaction commit, and return to the idle state.
2096 case TBLOCK_STARTED:
2097 CommitTransaction();
2098 s->blockState = TBLOCK_DEFAULT;
2102 * We are completing a "BEGIN TRANSACTION" command, so we
2103 * change to the "transaction block in progress" state and
2104 * return. (We assume the BEGIN did nothing to the database,
2105 * so we need no CommandCounterIncrement.)
2108 s->blockState = TBLOCK_INPROGRESS;
2112 * This is the case when we have finished executing a command
2113 * someplace within a transaction block. We increment the
2114 * command counter and return.
2116 case TBLOCK_INPROGRESS:
2117 case TBLOCK_SUBINPROGRESS:
2118 CommandCounterIncrement();
2122 * We are completing a "COMMIT" command. Do it and return to
2126 CommitTransaction();
2127 s->blockState = TBLOCK_DEFAULT;
2131 * Here we are in the middle of a transaction block but one of
2132 * the commands caused an abort so we do nothing but remain in
2133 * the abort state. Eventually we will get a ROLLBACK comand.
2136 case TBLOCK_SUBABORT:
2140 * Here we were in an aborted transaction block and we just
2141 * got the ROLLBACK command from the user, so clean up the
2142 * already-aborted transaction and return to the idle state.
2144 case TBLOCK_ABORT_END:
2145 CleanupTransaction();
2146 s->blockState = TBLOCK_DEFAULT;
2150 * Here we were in a perfectly good transaction block but the
2151 * user told us to ROLLBACK anyway. We have to abort the
2152 * transaction and then clean up.
2154 case TBLOCK_ABORT_PENDING:
2156 CleanupTransaction();
2157 s->blockState = TBLOCK_DEFAULT;
2161 * We are completing a "PREPARE TRANSACTION" command. Do it and
2162 * return to the idle state.
2164 case TBLOCK_PREPARE:
2165 PrepareTransaction();
2166 s->blockState = TBLOCK_DEFAULT;
2170 * We were just issued a SAVEPOINT inside a transaction block.
2171 * Start a subtransaction. (DefineSavepoint already did
2172 * PushTransaction, so as to have someplace to put the
2175 case TBLOCK_SUBBEGIN:
2176 StartSubTransaction();
2177 s->blockState = TBLOCK_SUBINPROGRESS;
2181 * We were issued a COMMIT or RELEASE command, so we end the
2182 * current subtransaction and return to the parent transaction.
2183 * The parent might be ended too, so repeat till we are all the
2184 * way out or find an INPROGRESS transaction.
2189 CommitSubTransaction();
2190 s = CurrentTransactionState; /* changed by pop */
2191 } while (s->blockState == TBLOCK_SUBEND);
2192 /* If we had a COMMIT command, finish off the main xact too */
2193 if (s->blockState == TBLOCK_END)
2195 Assert(s->parent == NULL);
2196 CommitTransaction();
2197 s->blockState = TBLOCK_DEFAULT;
2199 else if (s->blockState == TBLOCK_PREPARE)
2201 Assert(s->parent == NULL);
2202 PrepareTransaction();
2203 s->blockState = TBLOCK_DEFAULT;
2207 Assert(s->blockState == TBLOCK_INPROGRESS ||
2208 s->blockState == TBLOCK_SUBINPROGRESS);
2213 * The current already-failed subtransaction is ending due to a
2214 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2215 * examine the parent (which could be in any of several states).
2217 case TBLOCK_SUBABORT_END:
2218 CleanupSubTransaction();
2219 CommitTransactionCommand();
2223 * As above, but it's not dead yet, so abort first.
2225 case TBLOCK_SUBABORT_PENDING:
2226 AbortSubTransaction();
2227 CleanupSubTransaction();
2228 CommitTransactionCommand();
2232 * The current subtransaction is the target of a ROLLBACK TO
2233 * command. Abort and pop it, then start a new subtransaction
2234 * with the same name.
2236 case TBLOCK_SUBRESTART:
2241 /* save name and keep Cleanup from freeing it */
2244 savepointLevel = s->savepointLevel;
2246 AbortSubTransaction();
2247 CleanupSubTransaction();
2249 DefineSavepoint(NULL);
2250 s = CurrentTransactionState; /* changed by push */
2252 s->savepointLevel = savepointLevel;
2254 /* This is the same as TBLOCK_SUBBEGIN case */
2255 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2256 StartSubTransaction();
2257 s->blockState = TBLOCK_SUBINPROGRESS;
2262 * Same as above, but the subtransaction had already failed,
2263 * so we don't need AbortSubTransaction.
2265 case TBLOCK_SUBABORT_RESTART:
2270 /* save name and keep Cleanup from freeing it */
2273 savepointLevel = s->savepointLevel;
2275 CleanupSubTransaction();
2277 DefineSavepoint(NULL);
2278 s = CurrentTransactionState; /* changed by push */
2280 s->savepointLevel = savepointLevel;
2282 /* This is the same as TBLOCK_SUBBEGIN case */
2283 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2284 StartSubTransaction();
2285 s->blockState = TBLOCK_SUBINPROGRESS;
2292 * AbortCurrentTransaction
2295 AbortCurrentTransaction(void)
2297 TransactionState s = CurrentTransactionState;
2299 switch (s->blockState)
2301 case TBLOCK_DEFAULT:
2302 if (s->state == TRANS_DEFAULT)
2304 /* we are idle, so nothing to do */
2309 * We can get here after an error during transaction start
2310 * (state will be TRANS_START). Need to clean up the
2311 * incompletely started transaction. First, adjust the
2312 * low-level state to suppress warning message from
2315 if (s->state == TRANS_START)
2316 s->state = TRANS_INPROGRESS;
2318 CleanupTransaction();
2323 * if we aren't in a transaction block, we just do the basic
2324 * abort & cleanup transaction.
2326 case TBLOCK_STARTED:
2328 CleanupTransaction();
2329 s->blockState = TBLOCK_DEFAULT;
2333 * If we are in TBLOCK_BEGIN it means something screwed up
2334 * right after reading "BEGIN TRANSACTION". We assume that
2335 * the user will interpret the error as meaning the BEGIN
2336 * failed to get him into a transaction block, so we should
2337 * abort and return to idle state.
2341 CleanupTransaction();
2342 s->blockState = TBLOCK_DEFAULT;
2346 * We are somewhere in a transaction block and we've gotten a
2347 * failure, so we abort the transaction and set up the persistent
2348 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2350 case TBLOCK_INPROGRESS:
2352 s->blockState = TBLOCK_ABORT;
2353 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2357 * Here, we failed while trying to COMMIT. Clean up the
2358 * transaction and return to idle state (we do not want to
2359 * stay in the transaction).
2363 CleanupTransaction();
2364 s->blockState = TBLOCK_DEFAULT;
2368 * Here, we are already in an aborted transaction state and
2369 * are waiting for a ROLLBACK, but for some reason we failed
2370 * again! So we just remain in the abort state.
2373 case TBLOCK_SUBABORT:
2377 * We are in a failed transaction and we got the ROLLBACK command.
2378 * We have already aborted, we just need to cleanup and go to
2381 case TBLOCK_ABORT_END:
2382 CleanupTransaction();
2383 s->blockState = TBLOCK_DEFAULT;
2387 * We are in a live transaction and we got a ROLLBACK command.
2388 * Abort, cleanup, go to idle state.
2390 case TBLOCK_ABORT_PENDING:
2392 CleanupTransaction();
2393 s->blockState = TBLOCK_DEFAULT;
2397 * Here, we failed while trying to PREPARE. Clean up the
2398 * transaction and return to idle state (we do not want to
2399 * stay in the transaction).
2401 case TBLOCK_PREPARE:
2403 CleanupTransaction();
2404 s->blockState = TBLOCK_DEFAULT;
2408 * We got an error inside a subtransaction. Abort just the
2409 * subtransaction, and go to the persistent SUBABORT state
2410 * until we get ROLLBACK.
2412 case TBLOCK_SUBINPROGRESS:
2413 AbortSubTransaction();
2414 s->blockState = TBLOCK_SUBABORT;
2418 * If we failed while trying to create a subtransaction, clean up
2419 * the broken subtransaction and abort the parent. The same
2420 * applies if we get a failure while ending a subtransaction.
2422 case TBLOCK_SUBBEGIN:
2424 case TBLOCK_SUBABORT_PENDING:
2425 case TBLOCK_SUBRESTART:
2426 AbortSubTransaction();
2427 CleanupSubTransaction();
2428 AbortCurrentTransaction();
2432 * Same as above, except the Abort() was already done.
2434 case TBLOCK_SUBABORT_END:
2435 case TBLOCK_SUBABORT_RESTART:
2436 CleanupSubTransaction();
2437 AbortCurrentTransaction();
2443 * PreventTransactionChain
2445 * This routine is to be called by statements that must not run inside
2446 * a transaction block, typically because they have non-rollback-able
2447 * side effects or do internal commits.
2449 * If we have already started a transaction block, issue an error; also issue
2450 * an error if we appear to be running inside a user-defined function (which
2451 * could issue more commands and possibly cause a failure after the statement
2452 * completes). Subtransactions are verboten too.
2454 * stmtNode: pointer to parameter block for statement; this is used in
2455 * a very klugy way to determine whether we are inside a function.
2456 * stmtType: statement type name for error messages.
2459 PreventTransactionChain(void *stmtNode, const char *stmtType)
2462 * xact block already started?
2464 if (IsTransactionBlock())
2466 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2467 /* translator: %s represents an SQL statement name */
2468 errmsg("%s cannot run inside a transaction block",
2474 if (IsSubTransaction())
2476 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2477 /* translator: %s represents an SQL statement name */
2478 errmsg("%s cannot run inside a subtransaction",
2482 * Are we inside a function call? If the statement's parameter block
2483 * was allocated in QueryContext, assume it is an interactive command.
2484 * Otherwise assume it is coming from a function.
2486 if (!MemoryContextContains(QueryContext, stmtNode))
2488 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2489 /* translator: %s represents an SQL statement name */
2490 errmsg("%s cannot be executed from a function", stmtType)));
2492 /* If we got past IsTransactionBlock test, should be in default state */
2493 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2494 CurrentTransactionState->blockState != TBLOCK_STARTED)
2495 elog(FATAL, "cannot prevent transaction chain");
2500 * RequireTransactionChain
2502 * This routine is to be called by statements that must run inside
2503 * a transaction block, because they have no effects that persist past
2504 * transaction end (and so calling them outside a transaction block
2505 * is presumably an error). DECLARE CURSOR is an example.
2507 * If we appear to be running inside a user-defined function, we do not
2508 * issue an error, since the function could issue more commands that make
2509 * use of the current statement's results. Likewise subtransactions.
2510 * Thus this is an inverse for PreventTransactionChain.
2512 * stmtNode: pointer to parameter block for statement; this is used in
2513 * a very klugy way to determine whether we are inside a function.
2514 * stmtType: statement type name for error messages.
2517 RequireTransactionChain(void *stmtNode, const char *stmtType)
2520 * xact block already started?
2522 if (IsTransactionBlock())
2528 if (IsSubTransaction())
2532 * Are we inside a function call? If the statement's parameter block
2533 * was allocated in QueryContext, assume it is an interactive command.
2534 * Otherwise assume it is coming from a function.
2536 if (!MemoryContextContains(QueryContext, stmtNode))
2539 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2540 /* translator: %s represents an SQL statement name */
2541 errmsg("%s may only be used in transaction blocks",
2546 * IsInTransactionChain
2548 * This routine is for statements that need to behave differently inside
2549 * a transaction block than when running as single commands. ANALYZE is
2550 * currently the only example.
2552 * stmtNode: pointer to parameter block for statement; this is used in
2553 * a very klugy way to determine whether we are inside a function.
2556 IsInTransactionChain(void *stmtNode)
2559 * Return true on same conditions that would make
2560 * PreventTransactionChain error out
2562 if (IsTransactionBlock())
2565 if (IsSubTransaction())
2568 if (!MemoryContextContains(QueryContext, stmtNode))
2571 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2572 CurrentTransactionState->blockState != TBLOCK_STARTED)
2580 * Register or deregister callback functions for start- and end-of-xact
2583 * These functions are intended for use by dynamically loaded modules.
2584 * For built-in modules we generally just hardwire the appropriate calls
2585 * (mainly because it's easier to control the order that way, where needed).
2587 * At transaction end, the callback occurs post-commit or post-abort, so the
2588 * callback functions can only do noncritical cleanup.
2591 RegisterXactCallback(XactCallback callback, void *arg)
2593 XactCallbackItem *item;
2595 item = (XactCallbackItem *)
2596 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2597 item->callback = callback;
2599 item->next = Xact_callbacks;
2600 Xact_callbacks = item;
2604 UnregisterXactCallback(XactCallback callback, void *arg)
2606 XactCallbackItem *item;
2607 XactCallbackItem *prev;
2610 for (item = Xact_callbacks; item; prev = item, item = item->next)
2612 if (item->callback == callback && item->arg == arg)
2615 prev->next = item->next;
2617 Xact_callbacks = item->next;
2625 CallXactCallbacks(XactEvent event)
2627 XactCallbackItem *item;
2629 for (item = Xact_callbacks; item; item = item->next)
2630 (*item->callback) (event, item->arg);
2635 * Register or deregister callback functions for start- and end-of-subxact
2638 * Pretty much same as above, but for subtransaction events.
2640 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2641 * so the callback functions can only do noncritical cleanup. At
2642 * subtransaction start, the callback is called when the subtransaction has
2643 * finished initializing.
2646 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2648 SubXactCallbackItem *item;
2650 item = (SubXactCallbackItem *)
2651 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2652 item->callback = callback;
2654 item->next = SubXact_callbacks;
2655 SubXact_callbacks = item;
2659 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2661 SubXactCallbackItem *item;
2662 SubXactCallbackItem *prev;
2665 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2667 if (item->callback == callback && item->arg == arg)
2670 prev->next = item->next;
2672 SubXact_callbacks = item->next;
2680 CallSubXactCallbacks(SubXactEvent event,
2681 SubTransactionId mySubid,
2682 SubTransactionId parentSubid)
2684 SubXactCallbackItem *item;
2686 for (item = SubXact_callbacks; item; item = item->next)
2687 (*item->callback) (event, mySubid, parentSubid, item->arg);
2691 /* ----------------------------------------------------------------
2692 * transaction block support
2693 * ----------------------------------------------------------------
2697 * BeginTransactionBlock
2698 * This executes a BEGIN command.
2701 BeginTransactionBlock(void)
2703 TransactionState s = CurrentTransactionState;
2705 switch (s->blockState)
2708 * We are not inside a transaction block, so allow one to
2711 case TBLOCK_STARTED:
2712 s->blockState = TBLOCK_BEGIN;
2716 * Already a transaction block in progress.
2718 case TBLOCK_INPROGRESS:
2719 case TBLOCK_SUBINPROGRESS:
2721 case TBLOCK_SUBABORT:
2723 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2724 errmsg("there is already a transaction in progress")));
2727 /* These cases are invalid. */
2728 case TBLOCK_DEFAULT:
2730 case TBLOCK_SUBBEGIN:
2733 case TBLOCK_ABORT_END:
2734 case TBLOCK_SUBABORT_END:
2735 case TBLOCK_ABORT_PENDING:
2736 case TBLOCK_SUBABORT_PENDING:
2737 case TBLOCK_SUBRESTART:
2738 case TBLOCK_SUBABORT_RESTART:
2739 case TBLOCK_PREPARE:
2740 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2741 BlockStateAsString(s->blockState));
2747 * PrepareTransactionBlock
2748 * This executes a PREPARE command.
2750 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2751 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2753 * Note that we don't actually do anything here except change blockState.
2754 * The real work will be done in the upcoming PrepareTransaction().
2755 * We do it this way because it's not convenient to change memory context,
2756 * resource owner, etc while executing inside a Portal.
2759 PrepareTransactionBlock(char *gid)
2764 /* Set up to commit the current transaction */
2765 result = EndTransactionBlock();
2767 /* If successful, change outer tblock state to PREPARE */
2770 s = CurrentTransactionState;
2772 while (s->parent != NULL)
2775 if (s->blockState == TBLOCK_END)
2777 /* Save GID where PrepareTransaction can find it again */
2778 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2780 s->blockState = TBLOCK_PREPARE;
2785 * ignore case where we are not in a transaction;
2786 * EndTransactionBlock already issued a warning.
2788 Assert(s->blockState == TBLOCK_STARTED);
2789 /* Don't send back a PREPARE result tag... */
2798 * EndTransactionBlock
2799 * This executes a COMMIT command.
2801 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2802 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2804 * Note that we don't actually do anything here except change blockState.
2805 * The real work will be done in the upcoming CommitTransactionCommand().
2806 * We do it this way because it's not convenient to change memory context,
2807 * resource owner, etc while executing inside a Portal.
2810 EndTransactionBlock(void)
2812 TransactionState s = CurrentTransactionState;
2813 bool result = false;
2815 switch (s->blockState)
2818 * We are in a transaction block, so tell CommitTransactionCommand
2821 case TBLOCK_INPROGRESS:
2822 s->blockState = TBLOCK_END;
2827 * We are in a failed transaction block. Tell
2828 * CommitTransactionCommand it's time to exit the block.
2831 s->blockState = TBLOCK_ABORT_END;
2835 * We are in a live subtransaction block. Set up to subcommit
2836 * all open subtransactions and then commit the main transaction.
2838 case TBLOCK_SUBINPROGRESS:
2839 while (s->parent != NULL)
2841 if (s->blockState == TBLOCK_SUBINPROGRESS)
2842 s->blockState = TBLOCK_SUBEND;
2844 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2845 BlockStateAsString(s->blockState));
2848 if (s->blockState == TBLOCK_INPROGRESS)
2849 s->blockState = TBLOCK_END;
2851 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2852 BlockStateAsString(s->blockState));
2857 * Here we are inside an aborted subtransaction. Treat the
2858 * COMMIT as ROLLBACK: set up to abort everything and exit
2859 * the main transaction.
2861 case TBLOCK_SUBABORT:
2862 while (s->parent != NULL)
2864 if (s->blockState == TBLOCK_SUBINPROGRESS)
2865 s->blockState = TBLOCK_SUBABORT_PENDING;
2866 else if (s->blockState == TBLOCK_SUBABORT)
2867 s->blockState = TBLOCK_SUBABORT_END;
2869 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2870 BlockStateAsString(s->blockState));
2873 if (s->blockState == TBLOCK_INPROGRESS)
2874 s->blockState = TBLOCK_ABORT_PENDING;
2875 else if (s->blockState == TBLOCK_ABORT)
2876 s->blockState = TBLOCK_ABORT_END;
2878 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2879 BlockStateAsString(s->blockState));
2883 * The user issued COMMIT when not inside a transaction. Issue a
2884 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2885 * CommitTransactionCommand() will then close the transaction and
2886 * put us back into the default state.
2888 case TBLOCK_STARTED:
2890 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2891 errmsg("there is no transaction in progress")));
2895 /* These cases are invalid. */
2896 case TBLOCK_DEFAULT:
2898 case TBLOCK_SUBBEGIN:
2901 case TBLOCK_ABORT_END:
2902 case TBLOCK_SUBABORT_END:
2903 case TBLOCK_ABORT_PENDING:
2904 case TBLOCK_SUBABORT_PENDING:
2905 case TBLOCK_SUBRESTART:
2906 case TBLOCK_SUBABORT_RESTART:
2907 case TBLOCK_PREPARE:
2908 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2909 BlockStateAsString(s->blockState));
2917 * UserAbortTransactionBlock
2918 * This executes a ROLLBACK command.
2920 * As above, we don't actually do anything here except change blockState.
2923 UserAbortTransactionBlock(void)
2925 TransactionState s = CurrentTransactionState;
2927 switch (s->blockState)
2930 * We are inside a transaction block and we got a ROLLBACK
2931 * command from the user, so tell CommitTransactionCommand
2932 * to abort and exit the transaction block.
2934 case TBLOCK_INPROGRESS:
2935 s->blockState = TBLOCK_ABORT_PENDING;
2939 * We are inside a failed transaction block and we got a ROLLBACK
2940 * command from the user. Abort processing is already done,
2941 * so CommitTransactionCommand just has to cleanup and go back
2945 s->blockState = TBLOCK_ABORT_END;
2949 * We are inside a subtransaction. Mark everything
2950 * up to top level as exitable.
2952 case TBLOCK_SUBINPROGRESS:
2953 case TBLOCK_SUBABORT:
2954 while (s->parent != NULL)
2956 if (s->blockState == TBLOCK_SUBINPROGRESS)
2957 s->blockState = TBLOCK_SUBABORT_PENDING;
2958 else if (s->blockState == TBLOCK_SUBABORT)
2959 s->blockState = TBLOCK_SUBABORT_END;
2961 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2962 BlockStateAsString(s->blockState));
2965 if (s->blockState == TBLOCK_INPROGRESS)
2966 s->blockState = TBLOCK_ABORT_PENDING;
2967 else if (s->blockState == TBLOCK_ABORT)
2968 s->blockState = TBLOCK_ABORT_END;
2970 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2971 BlockStateAsString(s->blockState));
2975 * The user issued ABORT when not inside a transaction. Issue
2976 * a WARNING and go to abort state. The upcoming call to
2977 * CommitTransactionCommand() will then put us back into the
2980 case TBLOCK_STARTED:
2982 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2983 errmsg("there is no transaction in progress")));
2984 s->blockState = TBLOCK_ABORT_PENDING;
2987 /* These cases are invalid. */
2988 case TBLOCK_DEFAULT:
2990 case TBLOCK_SUBBEGIN:
2993 case TBLOCK_ABORT_END:
2994 case TBLOCK_SUBABORT_END:
2995 case TBLOCK_ABORT_PENDING:
2996 case TBLOCK_SUBABORT_PENDING:
2997 case TBLOCK_SUBRESTART:
2998 case TBLOCK_SUBABORT_RESTART:
2999 case TBLOCK_PREPARE:
3000 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3001 BlockStateAsString(s->blockState));
3008 * This executes a SAVEPOINT command.
3011 DefineSavepoint(char *name)
3013 TransactionState s = CurrentTransactionState;
3015 switch (s->blockState)
3017 case TBLOCK_INPROGRESS:
3018 case TBLOCK_SUBINPROGRESS:
3019 /* Normal subtransaction start */
3021 s = CurrentTransactionState; /* changed by push */
3024 * Savepoint names, like the TransactionState block itself,
3025 * live in TopTransactionContext.
3028 s->name = MemoryContextStrdup(TopTransactionContext, name);
3031 /* These cases are invalid. */
3032 case TBLOCK_DEFAULT:
3033 case TBLOCK_STARTED:
3035 case TBLOCK_SUBBEGIN:
3039 case TBLOCK_SUBABORT:
3040 case TBLOCK_ABORT_END:
3041 case TBLOCK_SUBABORT_END:
3042 case TBLOCK_ABORT_PENDING:
3043 case TBLOCK_SUBABORT_PENDING:
3044 case TBLOCK_SUBRESTART:
3045 case TBLOCK_SUBABORT_RESTART:
3046 case TBLOCK_PREPARE:
3047 elog(FATAL, "DefineSavepoint: unexpected state %s",
3048 BlockStateAsString(s->blockState));
3055 * This executes a RELEASE command.
3057 * As above, we don't actually do anything here except change blockState.
3060 ReleaseSavepoint(List *options)
3062 TransactionState s = CurrentTransactionState;
3063 TransactionState target,
3068 switch (s->blockState)
3071 * We can't rollback to a savepoint if there is no savepoint
3074 case TBLOCK_INPROGRESS:
3076 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3077 errmsg("no such savepoint")));
3081 * We are in a non-aborted subtransaction. This is the only
3084 case TBLOCK_SUBINPROGRESS:
3087 /* These cases are invalid. */
3088 case TBLOCK_DEFAULT:
3089 case TBLOCK_STARTED:
3091 case TBLOCK_SUBBEGIN:
3095 case TBLOCK_SUBABORT:
3096 case TBLOCK_ABORT_END:
3097 case TBLOCK_SUBABORT_END:
3098 case TBLOCK_ABORT_PENDING:
3099 case TBLOCK_SUBABORT_PENDING:
3100 case TBLOCK_SUBRESTART:
3101 case TBLOCK_SUBABORT_RESTART:
3102 case TBLOCK_PREPARE:
3103 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3104 BlockStateAsString(s->blockState));
3108 foreach(cell, options)
3110 DefElem *elem = lfirst(cell);
3112 if (strcmp(elem->defname, "savepoint_name") == 0)
3113 name = strVal(elem->arg);
3116 Assert(PointerIsValid(name));
3118 for (target = s; PointerIsValid(target); target = target->parent)
3120 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3124 if (!PointerIsValid(target))
3126 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3127 errmsg("no such savepoint")));
3129 /* disallow crossing savepoint level boundaries */
3130 if (target->savepointLevel != s->savepointLevel)
3132 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3133 errmsg("no such savepoint")));
3136 * Mark "commit pending" all subtransactions up to the target
3137 * subtransaction. The actual commits will happen when control gets
3138 * to CommitTransactionCommand.
3140 xact = CurrentTransactionState;
3143 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3144 xact->blockState = TBLOCK_SUBEND;
3147 xact = xact->parent;
3148 Assert(PointerIsValid(xact));
3153 * RollbackToSavepoint
3154 * This executes a ROLLBACK TO <savepoint> command.
3156 * As above, we don't actually do anything here except change blockState.
3159 RollbackToSavepoint(List *options)
3161 TransactionState s = CurrentTransactionState;
3162 TransactionState target,
3167 switch (s->blockState)
3170 * We can't rollback to a savepoint if there is no savepoint
3173 case TBLOCK_INPROGRESS:
3176 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3177 errmsg("no such savepoint")));
3181 * There is at least one savepoint, so proceed.
3183 case TBLOCK_SUBINPROGRESS:
3184 case TBLOCK_SUBABORT:
3187 /* These cases are invalid. */
3188 case TBLOCK_DEFAULT:
3189 case TBLOCK_STARTED:
3191 case TBLOCK_SUBBEGIN:
3194 case TBLOCK_ABORT_END:
3195 case TBLOCK_SUBABORT_END:
3196 case TBLOCK_ABORT_PENDING:
3197 case TBLOCK_SUBABORT_PENDING:
3198 case TBLOCK_SUBRESTART:
3199 case TBLOCK_SUBABORT_RESTART:
3200 case TBLOCK_PREPARE:
3201 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3202 BlockStateAsString(s->blockState));
3206 foreach(cell, options)
3208 DefElem *elem = lfirst(cell);
3210 if (strcmp(elem->defname, "savepoint_name") == 0)
3211 name = strVal(elem->arg);
3214 Assert(PointerIsValid(name));
3216 for (target = s; PointerIsValid(target); target = target->parent)
3218 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3222 if (!PointerIsValid(target))
3224 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3225 errmsg("no such savepoint")));
3227 /* disallow crossing savepoint level boundaries */
3228 if (target->savepointLevel != s->savepointLevel)
3230 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3231 errmsg("no such savepoint")));
3234 * Mark "abort pending" all subtransactions up to the target
3235 * subtransaction. The actual aborts will happen when control gets
3236 * to CommitTransactionCommand.
3238 xact = CurrentTransactionState;
3243 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3244 xact->blockState = TBLOCK_SUBABORT_PENDING;
3245 else if (xact->blockState == TBLOCK_SUBABORT)
3246 xact->blockState = TBLOCK_SUBABORT_END;
3248 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3249 BlockStateAsString(xact->blockState));
3250 xact = xact->parent;
3251 Assert(PointerIsValid(xact));
3254 /* And mark the target as "restart pending" */
3255 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3256 xact->blockState = TBLOCK_SUBRESTART;
3257 else if (xact->blockState == TBLOCK_SUBABORT)
3258 xact->blockState = TBLOCK_SUBABORT_RESTART;
3260 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3261 BlockStateAsString(xact->blockState));
3265 * BeginInternalSubTransaction
3266 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3267 * state, and therefore it can safely be used in a function that might
3268 * be called when not inside a BEGIN block. Also, we automatically
3269 * cycle through CommitTransactionCommand/StartTransactionCommand
3270 * instead of expecting the caller to do it.
3273 BeginInternalSubTransaction(char *name)
3275 TransactionState s = CurrentTransactionState;
3277 switch (s->blockState)
3279 case TBLOCK_STARTED:
3280 case TBLOCK_INPROGRESS:
3281 case TBLOCK_SUBINPROGRESS:
3282 /* Normal subtransaction start */
3284 s = CurrentTransactionState; /* changed by push */
3287 * Savepoint names, like the TransactionState block itself,
3288 * live in TopTransactionContext.
3291 s->name = MemoryContextStrdup(TopTransactionContext, name);
3294 /* These cases are invalid. */
3295 case TBLOCK_DEFAULT:
3297 case TBLOCK_SUBBEGIN:
3301 case TBLOCK_SUBABORT:
3302 case TBLOCK_ABORT_END:
3303 case TBLOCK_SUBABORT_END:
3304 case TBLOCK_ABORT_PENDING:
3305 case TBLOCK_SUBABORT_PENDING:
3306 case TBLOCK_SUBRESTART:
3307 case TBLOCK_SUBABORT_RESTART:
3308 case TBLOCK_PREPARE:
3309 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3310 BlockStateAsString(s->blockState));
3314 CommitTransactionCommand();
3315 StartTransactionCommand();
3319 * ReleaseCurrentSubTransaction
3321 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3322 * savepoint name (if any).
3323 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3326 ReleaseCurrentSubTransaction(void)
3328 TransactionState s = CurrentTransactionState;
3330 if (s->blockState != TBLOCK_SUBINPROGRESS)
3331 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3332 BlockStateAsString(s->blockState));
3333 Assert(s->state == TRANS_INPROGRESS);
3334 MemoryContextSwitchTo(CurTransactionContext);
3335 CommitSubTransaction();
3336 s = CurrentTransactionState; /* changed by pop */
3337 Assert(s->state == TRANS_INPROGRESS);
3341 * RollbackAndReleaseCurrentSubTransaction
3343 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3344 * of its savepoint name (if any).
3345 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3348 RollbackAndReleaseCurrentSubTransaction(void)
3350 TransactionState s = CurrentTransactionState;
3352 switch (s->blockState)
3354 /* Must be in a subtransaction */
3355 case TBLOCK_SUBINPROGRESS:
3356 case TBLOCK_SUBABORT:
3359 /* These cases are invalid. */
3360 case TBLOCK_DEFAULT:
3361 case TBLOCK_STARTED:
3363 case TBLOCK_SUBBEGIN:
3364 case TBLOCK_INPROGRESS:
3368 case TBLOCK_ABORT_END:
3369 case TBLOCK_SUBABORT_END:
3370 case TBLOCK_ABORT_PENDING:
3371 case TBLOCK_SUBABORT_PENDING:
3372 case TBLOCK_SUBRESTART:
3373 case TBLOCK_SUBABORT_RESTART:
3374 case TBLOCK_PREPARE:
3375 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3376 BlockStateAsString(s->blockState));
3381 * Abort the current subtransaction, if needed.
3383 if (s->blockState == TBLOCK_SUBINPROGRESS)
3384 AbortSubTransaction();
3386 /* And clean it up, too */
3387 CleanupSubTransaction();
3389 s = CurrentTransactionState; /* changed by pop */
3390 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3391 s->blockState == TBLOCK_INPROGRESS ||
3392 s->blockState == TBLOCK_STARTED);
3396 * AbortOutOfAnyTransaction
3398 * This routine is provided for error recovery purposes. It aborts any
3399 * active transaction or transaction block, leaving the system in a known
3403 AbortOutOfAnyTransaction(void)
3405 TransactionState s = CurrentTransactionState;
3408 * Get out of any transaction or nested transaction
3412 switch (s->blockState)
3414 case TBLOCK_DEFAULT:
3415 /* Not in a transaction, do nothing */
3417 case TBLOCK_STARTED:
3419 case TBLOCK_INPROGRESS:
3421 case TBLOCK_ABORT_PENDING:
3422 case TBLOCK_PREPARE:
3423 /* In a transaction, so clean up */
3425 CleanupTransaction();
3426 s->blockState = TBLOCK_DEFAULT;
3429 case TBLOCK_ABORT_END:
3430 /* AbortTransaction already done, still need Cleanup */
3431 CleanupTransaction();
3432 s->blockState = TBLOCK_DEFAULT;
3436 * In a subtransaction, so clean it up and abort parent
3439 case TBLOCK_SUBBEGIN:
3440 case TBLOCK_SUBINPROGRESS:
3442 case TBLOCK_SUBABORT_PENDING:
3443 case TBLOCK_SUBRESTART:
3444 AbortSubTransaction();
3445 CleanupSubTransaction();
3446 s = CurrentTransactionState; /* changed by pop */
3449 case TBLOCK_SUBABORT:
3450 case TBLOCK_SUBABORT_END:
3451 case TBLOCK_SUBABORT_RESTART:
3452 /* As above, but AbortSubTransaction already done */
3453 CleanupSubTransaction();
3454 s = CurrentTransactionState; /* changed by pop */
3457 } while (s->blockState != TBLOCK_DEFAULT);
3459 /* Should be out of all subxacts now */
3460 Assert(s->parent == NULL);
3464 * IsTransactionBlock --- are we within a transaction block?
3467 IsTransactionBlock(void)
3469 TransactionState s = CurrentTransactionState;
3471 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3478 * IsTransactionOrTransactionBlock --- are we within either a transaction
3479 * or a transaction block? (The backend is only really "idle" when this
3482 * This should match up with IsTransactionBlock and IsTransactionState.
3485 IsTransactionOrTransactionBlock(void)
3487 TransactionState s = CurrentTransactionState;
3489 if (s->blockState == TBLOCK_DEFAULT)
3496 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3499 TransactionBlockStatusCode(void)
3501 TransactionState s = CurrentTransactionState;
3503 switch (s->blockState)
3505 case TBLOCK_DEFAULT:
3506 case TBLOCK_STARTED:
3507 return 'I'; /* idle --- not in transaction */
3509 case TBLOCK_SUBBEGIN:
3510 case TBLOCK_INPROGRESS:
3511 case TBLOCK_SUBINPROGRESS:
3514 case TBLOCK_PREPARE:
3515 return 'T'; /* in transaction */
3517 case TBLOCK_SUBABORT:
3518 case TBLOCK_ABORT_END:
3519 case TBLOCK_SUBABORT_END:
3520 case TBLOCK_ABORT_PENDING:
3521 case TBLOCK_SUBABORT_PENDING:
3522 case TBLOCK_SUBRESTART:
3523 case TBLOCK_SUBABORT_RESTART:
3524 return 'E'; /* in failed transaction */
3527 /* should never get here */
3528 elog(FATAL, "invalid transaction block state: %s",
3529 BlockStateAsString(s->blockState));
3530 return 0; /* keep compiler quiet */
3537 IsSubTransaction(void)
3539 TransactionState s = CurrentTransactionState;
3541 if (s->nestingLevel >= 2)
3548 * StartSubTransaction
3550 * If you're wondering why this is separate from PushTransaction: it's because
3551 * we can't conveniently do this stuff right inside DefineSavepoint. The
3552 * SAVEPOINT utility command will be executed inside a Portal, and if we
3553 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3554 * the Portal will undo those settings. So we make DefineSavepoint just
3555 * push a dummy transaction block, and when control returns to the main
3556 * idle loop, CommitTransactionCommand will be called, and we'll come here
3557 * to finish starting the subtransaction.
3560 StartSubTransaction(void)
3562 TransactionState s = CurrentTransactionState;
3564 if (s->state != TRANS_DEFAULT)
3565 elog(WARNING, "StartSubTransaction while in %s state",
3566 TransStateAsString(s->state));
3568 s->state = TRANS_START;
3571 * Initialize subsystems for new subtransaction
3573 * must initialize resource-management stuff first
3575 AtSubStart_Memory();
3576 AtSubStart_ResourceOwner();
3578 AtSubStart_Notify();
3579 AfterTriggerBeginSubXact();
3581 s->state = TRANS_INPROGRESS;
3584 * Call start-of-subxact callbacks
3586 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3587 s->parent->subTransactionId);
3589 ShowTransactionState("StartSubTransaction");
3593 * CommitSubTransaction
3595 * The caller has to make sure to always reassign CurrentTransactionState
3596 * if it has a local pointer to it after calling this function.
3599 CommitSubTransaction(void)
3601 TransactionState s = CurrentTransactionState;
3603 ShowTransactionState("CommitSubTransaction");
3605 if (s->state != TRANS_INPROGRESS)
3606 elog(WARNING, "CommitSubTransaction while in %s state",
3607 TransStateAsString(s->state));
3609 /* Pre-commit processing goes here -- nothing to do at the moment */
3611 s->state = TRANS_COMMIT;
3613 /* Must CCI to ensure commands of subtransaction are seen as done */
3614 CommandCounterIncrement();
3616 /* Mark subtransaction as subcommitted */
3617 if (TransactionIdIsValid(s->transactionId))
3619 RecordSubTransactionCommit();
3620 AtSubCommit_childXids();
3623 /* Post-commit cleanup */
3624 AfterTriggerEndSubXact(true);
3625 AtSubCommit_Portals(s->subTransactionId,
3626 s->parent->subTransactionId,
3627 s->parent->curTransactionOwner);
3628 AtEOSubXact_LargeObject(true, s->subTransactionId,
3629 s->parent->subTransactionId);
3630 AtSubCommit_Notify();
3631 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3632 s->parent->subTransactionId);
3634 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3635 s->parent->subTransactionId);
3637 ResourceOwnerRelease(s->curTransactionOwner,
3638 RESOURCE_RELEASE_BEFORE_LOCKS,
3640 AtEOSubXact_RelationCache(true, s->subTransactionId,
3641 s->parent->subTransactionId);
3642 AtEOSubXact_Inval(true);
3646 * The only lock we actually release here is the subtransaction XID lock.
3647 * The rest just get transferred to the parent resource owner.
3649 CurrentResourceOwner = s->curTransactionOwner;
3650 if (TransactionIdIsValid(s->transactionId))
3651 XactLockTableDelete(s->transactionId);
3653 ResourceOwnerRelease(s->curTransactionOwner,
3654 RESOURCE_RELEASE_LOCKS,
3656 ResourceOwnerRelease(s->curTransactionOwner,
3657 RESOURCE_RELEASE_AFTER_LOCKS,
3660 AtEOXact_GUC(true, true);
3661 AtEOSubXact_SPI(true, s->subTransactionId);
3662 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3663 s->parent->subTransactionId);
3664 AtEOSubXact_Namespace(true, s->subTransactionId,
3665 s->parent->subTransactionId);
3666 AtEOSubXact_Files(true, s->subTransactionId,
3667 s->parent->subTransactionId);
3670 * We need to restore the upper transaction's read-only state, in case
3671 * the upper is read-write while the child is read-only; GUC will
3672 * incorrectly think it should leave the child state in place.
3674 XactReadOnly = s->prevXactReadOnly;
3676 CurrentResourceOwner = s->parent->curTransactionOwner;
3677 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3678 ResourceOwnerDelete(s->curTransactionOwner);
3679 s->curTransactionOwner = NULL;
3681 AtSubCommit_Memory();
3683 s->state = TRANS_DEFAULT;
3689 * AbortSubTransaction
3692 AbortSubTransaction(void)
3694 TransactionState s = CurrentTransactionState;
3696 ShowTransactionState("AbortSubTransaction");
3698 if (s->state != TRANS_INPROGRESS)
3699 elog(WARNING, "AbortSubTransaction while in %s state",
3700 TransStateAsString(s->state));
3704 s->state = TRANS_ABORT;
3707 * Release any LW locks we might be holding as quickly as possible.
3708 * (Regular locks, however, must be held till we finish aborting.)
3709 * Releasing LW locks is critical since we might try to grab them
3710 * again while cleaning up!
3712 * FIXME This may be incorrect --- Are there some locks we should keep?
3713 * Buffer locks, for example? I don't think so but I'm not sure.
3723 * do abort processing
3725 AtSubAbort_Memory();
3726 AtSubAbort_ResourceOwner();
3729 * We can skip all this stuff if the subxact failed before creating
3730 * a ResourceOwner...
3732 if (s->curTransactionOwner)
3734 AfterTriggerEndSubXact(false);
3735 AtSubAbort_Portals(s->subTransactionId,
3736 s->parent->subTransactionId,
3737 s->parent->curTransactionOwner);
3738 AtEOSubXact_LargeObject(false, s->subTransactionId,
3739 s->parent->subTransactionId);
3740 AtSubAbort_Notify();
3741 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3742 s->parent->subTransactionId);
3744 /* Advertise the fact that we aborted in pg_clog. */
3745 if (TransactionIdIsValid(s->transactionId))
3747 RecordSubTransactionAbort();
3748 AtSubAbort_childXids();
3751 /* Post-abort cleanup */
3752 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3753 s->parent->subTransactionId);
3755 ResourceOwnerRelease(s->curTransactionOwner,
3756 RESOURCE_RELEASE_BEFORE_LOCKS,
3758 AtEOSubXact_RelationCache(false, s->subTransactionId,
3759 s->parent->subTransactionId);
3760 AtEOSubXact_Inval(false);
3762 ResourceOwnerRelease(s->curTransactionOwner,
3763 RESOURCE_RELEASE_LOCKS,
3765 ResourceOwnerRelease(s->curTransactionOwner,
3766 RESOURCE_RELEASE_AFTER_LOCKS,
3769 AtEOXact_GUC(false, true);
3770 AtEOSubXact_SPI(false, s->subTransactionId);
3771 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3772 s->parent->subTransactionId);
3773 AtEOSubXact_Namespace(false, s->subTransactionId,
3774 s->parent->subTransactionId);
3775 AtEOSubXact_Files(false, s->subTransactionId,
3776 s->parent->subTransactionId);
3780 * Reset user id which might have been changed transiently. Here we
3781 * want to restore to the userid that was current at subxact entry.
3782 * (As in AbortTransaction, we need not worry about the session
3785 * Must do this after AtEOXact_GUC to handle the case where we entered
3786 * the subxact inside a SECURITY DEFINER function (hence current and
3787 * session userids were different) and then session auth was changed
3788 * inside the subxact. GUC will reset both current and session
3789 * userids to the entry-time session userid. This is right in every
3790 * other scenario so it seems simplest to let GUC do that and fix it
3793 SetUserId(s->currentUser);
3796 * Restore the upper transaction's read-only state, too. This should
3797 * be redundant with GUC's cleanup but we may as well do it for
3798 * consistency with the commit case.
3800 XactReadOnly = s->prevXactReadOnly;
3802 RESUME_INTERRUPTS();
3806 * CleanupSubTransaction
3808 * The caller has to make sure to always reassign CurrentTransactionState
3809 * if it has a local pointer to it after calling this function.
3812 CleanupSubTransaction(void)
3814 TransactionState s = CurrentTransactionState;
3816 ShowTransactionState("CleanupSubTransaction");
3818 if (s->state != TRANS_ABORT)
3819 elog(WARNING, "CleanupSubTransaction while in %s state",
3820 TransStateAsString(s->state));
3822 AtSubCleanup_Portals(s->subTransactionId);
3824 CurrentResourceOwner = s->parent->curTransactionOwner;
3825 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3826 if (s->curTransactionOwner)
3827 ResourceOwnerDelete(s->curTransactionOwner);
3828 s->curTransactionOwner = NULL;
3830 AtSubCleanup_Memory();
3832 s->state = TRANS_DEFAULT;
3839 * Create transaction state stack entry for a subtransaction
3841 * The caller has to make sure to always reassign CurrentTransactionState
3842 * if it has a local pointer to it after calling this function.
3845 PushTransaction(void)
3847 TransactionState p = CurrentTransactionState;
3852 * At present, GetUserId cannot fail, but let's not assume that. Get
3853 * the ID before entering the critical code sequence.
3855 currentUser = GetUserId();
3858 * We keep subtransaction state nodes in TopTransactionContext.
3860 s = (TransactionState)
3861 MemoryContextAllocZero(TopTransactionContext,
3862 sizeof(TransactionStateData));
3864 * Assign a subtransaction ID, watching out for counter wraparound.
3866 currentSubTransactionId += 1;
3867 if (currentSubTransactionId == InvalidSubTransactionId)
3869 currentSubTransactionId -= 1;
3872 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3873 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3876 * We can now stack a minimally valid subtransaction without fear of
3879 s->transactionId = InvalidTransactionId; /* until assigned */
3880 s->subTransactionId = currentSubTransactionId;
3882 s->nestingLevel = p->nestingLevel + 1;
3883 s->savepointLevel = p->savepointLevel;
3884 s->state = TRANS_DEFAULT;
3885 s->blockState = TBLOCK_SUBBEGIN;
3886 s->currentUser = currentUser;
3887 s->prevXactReadOnly = XactReadOnly;
3889 CurrentTransactionState = s;
3892 * AbortSubTransaction and CleanupSubTransaction have to be able to
3893 * cope with the subtransaction from here on out; in particular they
3894 * should not assume that it necessarily has a transaction context,
3895 * resource owner, or XID.
3901 * Pop back to parent transaction state
3903 * The caller has to make sure to always reassign CurrentTransactionState
3904 * if it has a local pointer to it after calling this function.
3907 PopTransaction(void)
3909 TransactionState s = CurrentTransactionState;
3911 if (s->state != TRANS_DEFAULT)
3912 elog(WARNING, "PopTransaction while in %s state",
3913 TransStateAsString(s->state));
3915 if (s->parent == NULL)
3916 elog(FATAL, "PopTransaction with no parent");
3918 CurrentTransactionState = s->parent;
3920 /* Let's just make sure CurTransactionContext is good */
3921 CurTransactionContext = s->parent->curTransactionContext;
3922 MemoryContextSwitchTo(CurTransactionContext);
3924 /* Ditto for ResourceOwner links */
3925 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3926 CurrentResourceOwner = s->parent->curTransactionOwner;
3928 /* Free the old child structure */
3935 * ShowTransactionState
3939 ShowTransactionState(const char *str)
3941 /* skip work if message will definitely not be printed */
3942 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3944 elog(DEBUG3, "%s", str);
3945 ShowTransactionStateRec(CurrentTransactionState);
3950 * ShowTransactionStateRec
3951 * Recursive subroutine for ShowTransactionState
3954 ShowTransactionStateRec(TransactionState s)
3957 ShowTransactionStateRec(s->parent);
3959 /* use ereport to suppress computation if msg will not be printed */
3961 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3962 PointerIsValid(s->name) ? s->name : "unnamed",
3963 BlockStateAsString(s->blockState),
3964 TransStateAsString(s->state),
3965 (unsigned int) s->transactionId,
3966 (unsigned int) s->subTransactionId,
3967 (unsigned int) currentCommandId,
3969 nodeToString(s->childXids))));
3973 * BlockStateAsString
3977 BlockStateAsString(TBlockState blockState)
3981 case TBLOCK_DEFAULT:
3983 case TBLOCK_STARTED:
3987 case TBLOCK_INPROGRESS:
3988 return "INPROGRESS";
3993 case TBLOCK_ABORT_END:
3995 case TBLOCK_ABORT_PENDING:
3996 return "ABORT PEND";
3997 case TBLOCK_PREPARE:
3999 case TBLOCK_SUBBEGIN:
4001 case TBLOCK_SUBINPROGRESS:
4002 return "SUB INPROGRS";
4005 case TBLOCK_SUBABORT:
4007 case TBLOCK_SUBABORT_END:
4008 return "SUB ABORT END";
4009 case TBLOCK_SUBABORT_PENDING:
4010 return "SUB ABRT PEND";
4011 case TBLOCK_SUBRESTART:
4012 return "SUB RESTART";
4013 case TBLOCK_SUBABORT_RESTART:
4014 return "SUB AB RESTRT";
4016 return "UNRECOGNIZED";
4020 * TransStateAsString
4024 TransStateAsString(TransState state)
4032 case TRANS_INPROGRESS:
4041 return "UNRECOGNIZED";
4045 * xactGetCommittedChildren
4047 * Gets the list of committed children of the current transaction. The return
4048 * value is the number of child transactions. *children is set to point to a
4049 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4053 xactGetCommittedChildren(TransactionId **ptr)
4055 TransactionState s = CurrentTransactionState;
4057 TransactionId *children;
4060 nchildren = list_length(s->childXids);
4067 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4070 foreach(p, s->childXids)
4072 TransactionId child = lfirst_xid(p);
4074 *children++ = child;
4081 * XLOG support routines
4085 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4087 TransactionId *sub_xids;
4088 TransactionId max_xid;
4091 TransactionIdCommit(xid);
4093 /* Mark committed subtransactions as committed */
4094 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4095 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4097 /* Make sure nextXid is beyond any XID mentioned in the record */
4099 for (i = 0; i < xlrec->nsubxacts; i++)
4101 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4102 max_xid = sub_xids[i];
4104 if (TransactionIdFollowsOrEquals(max_xid,
4105 ShmemVariableCache->nextXid))
4107 ShmemVariableCache->nextXid = max_xid;
4108 TransactionIdAdvance(ShmemVariableCache->nextXid);
4111 /* Make sure files supposed to be dropped are dropped */
4112 for (i = 0; i < xlrec->nrels; i++)
4114 XLogCloseRelation(xlrec->xnodes[i]);
4115 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4120 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4122 TransactionId *sub_xids;
4123 TransactionId max_xid;
4126 TransactionIdAbort(xid);
4128 /* Mark subtransactions as aborted */
4129 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4130 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4132 /* Make sure nextXid is beyond any XID mentioned in the record */
4134 for (i = 0; i < xlrec->nsubxacts; i++)
4136 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4137 max_xid = sub_xids[i];
4139 if (TransactionIdFollowsOrEquals(max_xid,
4140 ShmemVariableCache->nextXid))
4142 ShmemVariableCache->nextXid = max_xid;
4143 TransactionIdAdvance(ShmemVariableCache->nextXid);
4146 /* Make sure files supposed to be dropped are dropped */
4147 for (i = 0; i < xlrec->nrels; i++)
4149 XLogCloseRelation(xlrec->xnodes[i]);
4150 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4155 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4157 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4159 if (info == XLOG_XACT_COMMIT)
4161 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4163 xact_redo_commit(xlrec, record->xl_xid);
4165 else if (info == XLOG_XACT_ABORT)
4167 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4169 xact_redo_abort(xlrec, record->xl_xid);
4171 else if (info == XLOG_XACT_PREPARE)
4173 /* the record contents are exactly the 2PC file */
4174 RecreateTwoPhaseFile(record->xl_xid,
4175 XLogRecGetData(record), record->xl_len);
4177 else if (info == XLOG_XACT_COMMIT_PREPARED)
4179 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4181 xact_redo_commit(&xlrec->crec, xlrec->xid);
4182 RemoveTwoPhaseFile(xlrec->xid, false);
4184 else if (info == XLOG_XACT_ABORT_PREPARED)
4186 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4188 xact_redo_abort(&xlrec->arec, xlrec->xid);
4189 RemoveTwoPhaseFile(xlrec->xid, false);
4192 elog(PANIC, "xact_redo: unknown op code %u", info);
4196 xact_desc_commit(char *buf, xl_xact_commit *xlrec)
4198 struct tm *tm = localtime(&xlrec->xtime);
4201 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4202 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4203 tm->tm_hour, tm->tm_min, tm->tm_sec);
4204 if (xlrec->nrels > 0)
4206 sprintf(buf + strlen(buf), "; rels:");
4207 for (i = 0; i < xlrec->nrels; i++)
4209 RelFileNode rnode = xlrec->xnodes[i];
4211 sprintf(buf + strlen(buf), " %u/%u/%u",
4212 rnode.spcNode, rnode.dbNode, rnode.relNode);
4215 if (xlrec->nsubxacts > 0)
4217 TransactionId *xacts = (TransactionId *)
4218 &xlrec->xnodes[xlrec->nrels];
4220 sprintf(buf + strlen(buf), "; subxacts:");
4221 for (i = 0; i < xlrec->nsubxacts; i++)
4222 sprintf(buf + strlen(buf), " %u", xacts[i]);
4227 xact_desc_abort(char *buf, xl_xact_abort *xlrec)
4229 struct tm *tm = localtime(&xlrec->xtime);
4232 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4233 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4234 tm->tm_hour, tm->tm_min, tm->tm_sec);
4235 if (xlrec->nrels > 0)
4237 sprintf(buf + strlen(buf), "; rels:");
4238 for (i = 0; i < xlrec->nrels; i++)
4240 RelFileNode rnode = xlrec->xnodes[i];
4242 sprintf(buf + strlen(buf), " %u/%u/%u",
4243 rnode.spcNode, rnode.dbNode, rnode.relNode);
4246 if (xlrec->nsubxacts > 0)
4248 TransactionId *xacts = (TransactionId *)
4249 &xlrec->xnodes[xlrec->nrels];
4251 sprintf(buf + strlen(buf), "; subxacts:");
4252 for (i = 0; i < xlrec->nsubxacts; i++)
4253 sprintf(buf + strlen(buf), " %u", xacts[i]);
4258 xact_desc(char *buf, uint8 xl_info, char *rec)
4260 uint8 info = xl_info & ~XLR_INFO_MASK;
4262 if (info == XLOG_XACT_COMMIT)
4264 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4266 strcat(buf, "commit: ");
4267 xact_desc_commit(buf, xlrec);
4269 else if (info == XLOG_XACT_ABORT)
4271 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4273 strcat(buf, "abort: ");
4274 xact_desc_abort(buf, xlrec);
4276 else if (info == XLOG_XACT_PREPARE)
4278 strcat(buf, "prepare");
4280 else if (info == XLOG_XACT_COMMIT_PREPARED)
4282 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4284 sprintf(buf + strlen(buf), "commit %u: ", xlrec->xid);
4285 xact_desc_commit(buf, &xlrec->crec);
4287 else if (info == XLOG_XACT_ABORT_PREPARED)
4289 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4291 sprintf(buf + strlen(buf), "abort %u: ", xlrec->xid);
4292 xact_desc_abort(buf, &xlrec->arec);
4295 strcat(buf, "UNKNOWN");