1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2007, 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.242 2007/04/30 21:01:52 tgl Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.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"
37 #include "storage/fd.h"
38 #include "storage/lmgr.h"
39 #include "storage/procarray.h"
40 #include "storage/smgr.h"
41 #include "utils/combocid.h"
42 #include "utils/flatfiles.h"
43 #include "utils/guc.h"
44 #include "utils/inval.h"
45 #include "utils/memutils.h"
46 #include "utils/relcache.h"
50 * User-tweakable parameters
52 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
55 bool DefaultXactReadOnly = false;
58 int CommitDelay = 0; /* precommit delay in microseconds */
59 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
63 * transaction states - transaction state from server perspective
65 typedef enum TransState
76 * transaction block states - transaction state of client queries
78 * Note: the subtransaction states are used only for non-topmost
79 * transactions; the others appear only in the topmost transaction.
81 typedef enum TBlockState
83 /* not-in-transaction-block states */
84 TBLOCK_DEFAULT, /* idle */
85 TBLOCK_STARTED, /* running single-query transaction */
87 /* transaction block states */
88 TBLOCK_BEGIN, /* starting transaction block */
89 TBLOCK_INPROGRESS, /* live transaction */
90 TBLOCK_END, /* COMMIT received */
91 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
92 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
93 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
94 TBLOCK_PREPARE, /* live xact, PREPARE received */
96 /* subtransaction states */
97 TBLOCK_SUBBEGIN, /* starting a subtransaction */
98 TBLOCK_SUBINPROGRESS, /* live subtransaction */
99 TBLOCK_SUBEND, /* RELEASE received */
100 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
101 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
102 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
103 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
104 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
108 * transaction state structure
110 typedef struct TransactionStateData
112 TransactionId transactionId; /* my XID, or Invalid if none */
113 SubTransactionId subTransactionId; /* my subxact ID */
114 char *name; /* savepoint name, if any */
115 int savepointLevel; /* savepoint level */
116 TransState state; /* low-level state */
117 TBlockState blockState; /* high-level state */
118 int nestingLevel; /* nest depth */
119 MemoryContext curTransactionContext; /* my xact-lifetime context */
120 ResourceOwner curTransactionOwner; /* my query resources */
121 List *childXids; /* subcommitted child XIDs */
122 Oid currentUser; /* subxact start current_user */
123 bool prevXactReadOnly; /* entry-time xact r/o state */
124 struct TransactionStateData *parent; /* back link to parent */
125 } TransactionStateData;
127 typedef TransactionStateData *TransactionState;
130 * CurrentTransactionState always points to the current transaction state
131 * block. It will point to TopTransactionStateData when not in a
132 * transaction at all, or when in a top-level transaction.
134 static TransactionStateData TopTransactionStateData = {
135 0, /* transaction id */
136 0, /* subtransaction id */
137 NULL, /* savepoint name */
138 0, /* savepoint level */
139 TRANS_DEFAULT, /* transaction state */
140 TBLOCK_DEFAULT, /* transaction block state from the client
142 0, /* nesting level */
143 NULL, /* cur transaction context */
144 NULL, /* cur transaction resource owner */
145 NIL, /* subcommitted child Xids */
146 0, /* entry-time current userid */
147 false, /* entry-time xact r/o state */
148 NULL /* link to parent state block */
151 static TransactionState CurrentTransactionState = &TopTransactionStateData;
154 * The subtransaction ID and command ID assignment counters are global
155 * to a whole transaction, so we do not keep them in the state stack.
157 static SubTransactionId currentSubTransactionId;
158 static CommandId currentCommandId;
161 * xactStartTimestamp is the value of transaction_timestamp().
162 * stmtStartTimestamp is the value of statement_timestamp().
163 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
164 * These do not change as we enter and exit subtransactions, so we don't
165 * keep them inside the TransactionState stack.
167 static TimestampTz xactStartTimestamp;
168 static TimestampTz stmtStartTimestamp;
169 static TimestampTz xactStopTimestamp;
172 * GID to be used for preparing the current transaction. This is also
173 * global to a whole transaction, so we don't keep it in the state stack.
175 static char *prepareGID;
178 * Private context for transaction-abort work --- we reserve space for this
179 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
180 * when we've run out of memory.
182 static MemoryContext TransactionAbortContext = NULL;
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 in
353 * shared storage other than PG_PROC; because if there's no room for it in
354 * PG_PROC, the subtrans entry is needed to ensure that other backends see
355 * 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.) We
363 * 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 * GetCurrentStatementStartTimestamp
435 GetCurrentStatementStartTimestamp(void)
437 return stmtStartTimestamp;
441 * GetCurrentTransactionStopTimestamp
443 * We return current time if the transaction stop time hasn't been set
444 * (which can happen if we decide we don't need to log an XLOG record).
447 GetCurrentTransactionStopTimestamp(void)
449 if (xactStopTimestamp != 0)
450 return xactStopTimestamp;
451 return GetCurrentTimestamp();
455 * SetCurrentStatementStartTimestamp
458 SetCurrentStatementStartTimestamp(void)
460 stmtStartTimestamp = GetCurrentTimestamp();
464 * SetCurrentTransactionStopTimestamp
467 SetCurrentTransactionStopTimestamp(void)
469 xactStopTimestamp = GetCurrentTimestamp();
473 * GetCurrentTransactionNestLevel
475 * Note: this will return zero when not inside any transaction, one when
476 * inside a top-level transaction, etc.
479 GetCurrentTransactionNestLevel(void)
481 TransactionState s = CurrentTransactionState;
483 return s->nestingLevel;
488 * TransactionIdIsCurrentTransactionId
491 TransactionIdIsCurrentTransactionId(TransactionId xid)
496 * We always say that BootstrapTransactionId is "not my transaction ID"
497 * even when it is (ie, during bootstrap). Along with the fact that
498 * transam.c always treats BootstrapTransactionId as already committed,
499 * this causes the tqual.c routines to see all tuples as committed, which
500 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
501 * it never updates or deletes them, so all tuples can be presumed good
504 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
505 * not my transaction ID, so we can just return "false" immediately for
506 * any non-normal XID.
508 if (!TransactionIdIsNormal(xid))
512 * We will return true for the Xid of the current subtransaction, any of
513 * its subcommitted children, any of its parents, or any of their
514 * previously subcommitted children. However, a transaction being aborted
515 * is no longer "current", even though it may still have an entry on the
518 for (s = CurrentTransactionState; s != NULL; s = s->parent)
522 if (s->state == TRANS_ABORT)
524 if (!TransactionIdIsValid(s->transactionId))
525 continue; /* it can't have any child XIDs either */
526 if (TransactionIdEquals(xid, s->transactionId))
528 foreach(cell, s->childXids)
530 if (TransactionIdEquals(xid, lfirst_xid(cell)))
540 * CommandCounterIncrement
543 CommandCounterIncrement(void)
545 currentCommandId += 1;
546 if (currentCommandId == FirstCommandId) /* check for overflow */
548 currentCommandId -= 1;
550 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
551 errmsg("cannot have more than 2^32-1 commands in a transaction")));
554 /* Propagate new command ID into static snapshots, if set */
555 if (SerializableSnapshot)
556 SerializableSnapshot->curcid = currentCommandId;
558 LatestSnapshot->curcid = currentCommandId;
561 * make cache changes visible to me.
563 AtCommit_LocalCache();
568 /* ----------------------------------------------------------------
569 * StartTransaction stuff
570 * ----------------------------------------------------------------
579 AcceptInvalidationMessages();
588 TransactionState s = CurrentTransactionState;
591 * If this is the first time through, create a private context for
592 * AbortTransaction to work in. By reserving some space now, we can
593 * insulate AbortTransaction from out-of-memory scenarios. Like
594 * ErrorContext, we set it up with slow growth rate and a nonzero
595 * minimum size, so that space will be reserved immediately.
597 if (TransactionAbortContext == NULL)
598 TransactionAbortContext =
599 AllocSetContextCreate(TopMemoryContext,
600 "TransactionAbortContext",
606 * We shouldn't have a transaction context already.
608 Assert(TopTransactionContext == NULL);
611 * Create a toplevel context for the transaction.
613 TopTransactionContext =
614 AllocSetContextCreate(TopMemoryContext,
615 "TopTransactionContext",
616 ALLOCSET_DEFAULT_MINSIZE,
617 ALLOCSET_DEFAULT_INITSIZE,
618 ALLOCSET_DEFAULT_MAXSIZE);
621 * In a top-level transaction, CurTransactionContext is the same as
622 * TopTransactionContext.
624 CurTransactionContext = TopTransactionContext;
625 s->curTransactionContext = CurTransactionContext;
627 /* Make the CurTransactionContext active. */
628 MemoryContextSwitchTo(CurTransactionContext);
632 * AtStart_ResourceOwner
635 AtStart_ResourceOwner(void)
637 TransactionState s = CurrentTransactionState;
640 * We shouldn't have a transaction resource owner already.
642 Assert(TopTransactionResourceOwner == NULL);
645 * Create a toplevel resource owner for the transaction.
647 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
649 TopTransactionResourceOwner = s->curTransactionOwner;
650 CurTransactionResourceOwner = s->curTransactionOwner;
651 CurrentResourceOwner = s->curTransactionOwner;
654 /* ----------------------------------------------------------------
655 * StartSubTransaction stuff
656 * ----------------------------------------------------------------
663 AtSubStart_Memory(void)
665 TransactionState s = CurrentTransactionState;
667 Assert(CurTransactionContext != NULL);
670 * Create a CurTransactionContext, which will be used to hold data that
671 * survives subtransaction commit but disappears on subtransaction abort.
672 * We make it a child of the immediate parent's CurTransactionContext.
674 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
675 "CurTransactionContext",
676 ALLOCSET_DEFAULT_MINSIZE,
677 ALLOCSET_DEFAULT_INITSIZE,
678 ALLOCSET_DEFAULT_MAXSIZE);
679 s->curTransactionContext = CurTransactionContext;
681 /* Make the CurTransactionContext active. */
682 MemoryContextSwitchTo(CurTransactionContext);
686 * AtSubStart_ResourceOwner
689 AtSubStart_ResourceOwner(void)
691 TransactionState s = CurrentTransactionState;
693 Assert(s->parent != NULL);
696 * Create a resource owner for the subtransaction. We make it a child of
697 * the immediate parent's resource owner.
699 s->curTransactionOwner =
700 ResourceOwnerCreate(s->parent->curTransactionOwner,
703 CurTransactionResourceOwner = s->curTransactionOwner;
704 CurrentResourceOwner = s->curTransactionOwner;
707 /* ----------------------------------------------------------------
708 * CommitTransaction stuff
709 * ----------------------------------------------------------------
713 * RecordTransactionCommit
716 RecordTransactionCommit(void)
721 TransactionId *children;
723 /* Get data needed for commit record */
724 nrels = smgrGetPendingDeletes(true, &rels);
725 nchildren = xactGetCommittedChildren(&children);
728 * If we made neither any XLOG entries nor any temp-rel updates, and have
729 * no files to be deleted, we can omit recording the transaction commit at
730 * all. (This test includes the effects of subtransactions, so the
731 * presence of committed subxacts need not alone force a write.)
733 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
735 TransactionId xid = GetCurrentTransactionId();
739 /* Tell bufmgr and smgr to prepare for commit */
742 START_CRIT_SECTION();
745 * We only need to log the commit in XLOG if the transaction made any
746 * transaction-controlled XLOG entries or will delete files.
748 madeTCentries = (MyLastRecPtr.xrecoff != 0);
749 if (madeTCentries || nrels > 0)
751 XLogRecData rdata[3];
753 xl_xact_commit xlrec;
756 * Mark ourselves as within our "commit critical section". This
757 * forces any concurrent checkpoint to wait until we've updated
758 * pg_clog. Without this, it is possible for the checkpoint to
759 * set REDO after the XLOG record but fail to flush the pg_clog
760 * update to disk, leading to loss of the transaction commit if
761 * the system crashes a little later.
763 * Note: we could, but don't bother to, set this flag in
764 * RecordTransactionAbort. That's because loss of a transaction
765 * abort is noncritical; the presumption would be that it aborted,
768 * It's safe to change the inCommit flag of our own backend
769 * without holding the ProcArrayLock, since we're the only one
770 * modifying it. This makes checkpoint's determination of which
771 * xacts are inCommit a bit fuzzy, but it doesn't matter.
773 MyProc->inCommit = true;
775 SetCurrentTransactionStopTimestamp();
776 xlrec.xact_time = xactStopTimestamp;
778 xlrec.nsubxacts = nchildren;
779 rdata[0].data = (char *) (&xlrec);
780 rdata[0].len = MinSizeOfXactCommit;
781 rdata[0].buffer = InvalidBuffer;
782 /* dump rels to delete */
785 rdata[0].next = &(rdata[1]);
786 rdata[1].data = (char *) rels;
787 rdata[1].len = nrels * sizeof(RelFileNode);
788 rdata[1].buffer = InvalidBuffer;
791 /* dump committed child Xids */
794 rdata[lastrdata].next = &(rdata[2]);
795 rdata[2].data = (char *) children;
796 rdata[2].len = nchildren * sizeof(TransactionId);
797 rdata[2].buffer = InvalidBuffer;
800 rdata[lastrdata].next = NULL;
802 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
806 /* Just flush through last record written by me */
807 recptr = ProcLastRecEnd;
811 * We must flush our XLOG entries to disk if we made any XLOG entries,
812 * whether in or out of transaction control. For example, if we
813 * reported a nextval() result to the client, this ensures that any
814 * XLOG record generated by nextval will hit the disk before we report
815 * the transaction committed.
817 * Note: if we generated a commit record above, MyXactMadeXLogEntry
818 * will certainly be set now.
820 if (MyXactMadeXLogEntry)
823 * Sleep before flush! So we can flush more than one commit
824 * records per single fsync. (The idea is some other backend may
825 * do the XLogFlush while we're sleeping. This needs work still,
826 * because on most Unixen, the minimum select() delay is 10msec or
827 * more, which is way too long.)
829 * We do not sleep if enableFsync is not turned on, nor if there
830 * are fewer than CommitSiblings other backends with active
833 if (CommitDelay > 0 && enableFsync &&
834 CountActiveBackends() >= CommitSiblings)
835 pg_usleep(CommitDelay);
841 * We must mark the transaction committed in clog if its XID appears
842 * either in permanent rels or in local temporary rels. We test this
843 * by seeing if we made transaction-controlled entries *OR* local-rel
844 * tuple updates. Note that if we made only the latter, we have not
845 * emitted an XLOG record for our commit, and so in the event of a
846 * crash the clog update might be lost. This is okay because no one
847 * else will ever care whether we committed.
849 if (madeTCentries || MyXactMadeTempRelUpdate)
851 TransactionIdCommit(xid);
852 /* to avoid race conditions, the parent must commit first */
853 TransactionIdCommitTree(nchildren, children);
856 /* Checkpoint can proceed now */
857 MyProc->inCommit = false;
862 /* Break the chain of back-links in the XLOG records I output */
863 MyLastRecPtr.xrecoff = 0;
864 MyXactMadeXLogEntry = false;
865 MyXactMadeTempRelUpdate = false;
867 /* And clean up local data */
876 * AtCommit_LocalCache
879 AtCommit_LocalCache(void)
882 * Make catalog changes visible to me for the next command.
884 CommandEndInvalidationMessages();
891 AtCommit_Memory(void)
894 * Now that we're "out" of a transaction, have the system allocate things
895 * in the top memory context instead of per-transaction contexts.
897 MemoryContextSwitchTo(TopMemoryContext);
900 * Release all transaction-local memory.
902 Assert(TopTransactionContext != NULL);
903 MemoryContextDelete(TopTransactionContext);
904 TopTransactionContext = NULL;
905 CurTransactionContext = NULL;
906 CurrentTransactionState->curTransactionContext = NULL;
909 /* ----------------------------------------------------------------
910 * CommitSubTransaction stuff
911 * ----------------------------------------------------------------
918 AtSubCommit_Memory(void)
920 TransactionState s = CurrentTransactionState;
922 Assert(s->parent != NULL);
924 /* Return to parent transaction level's memory context. */
925 CurTransactionContext = s->parent->curTransactionContext;
926 MemoryContextSwitchTo(CurTransactionContext);
929 * Ordinarily we cannot throw away the child's CurTransactionContext,
930 * since the data it contains will be needed at upper commit. However, if
931 * there isn't actually anything in it, we can throw it away. This avoids
932 * a small memory leak in the common case of "trivial" subxacts.
934 if (MemoryContextIsEmpty(s->curTransactionContext))
936 MemoryContextDelete(s->curTransactionContext);
937 s->curTransactionContext = NULL;
942 * AtSubCommit_childXids
944 * Pass my own XID and my child XIDs up to my parent as committed children.
947 AtSubCommit_childXids(void)
949 TransactionState s = CurrentTransactionState;
950 MemoryContext old_cxt;
952 Assert(s->parent != NULL);
955 * We keep the child-XID lists in TopTransactionContext; this avoids
956 * setting up child-transaction contexts for what might be just a few
957 * bytes of grandchild XIDs.
959 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
961 s->parent->childXids = lappend_xid(s->parent->childXids,
964 if (s->childXids != NIL)
966 s->parent->childXids = list_concat(s->parent->childXids,
970 * list_concat doesn't free the list header for the second list; do so
971 * here to avoid memory leakage (kluge)
977 MemoryContextSwitchTo(old_cxt);
981 * RecordSubTransactionCommit
984 RecordSubTransactionCommit(void)
987 * We do not log the subcommit in XLOG; it doesn't matter until the
988 * top-level transaction commits.
990 * We must mark the subtransaction subcommitted in clog if its XID appears
991 * either in permanent rels or in local temporary rels. We test this by
992 * seeing if we made transaction-controlled entries *OR* local-rel tuple
993 * updates. (The test here actually covers the entire transaction tree so
994 * far, so it may mark subtransactions that don't really need it, but it's
995 * probably not worth being tenser. Note that if a prior subtransaction
996 * dirtied these variables, then RecordTransactionCommit will have to do
997 * the full pushup anyway...)
999 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
1001 TransactionId xid = GetCurrentTransactionId();
1003 /* XXX does this really need to be a critical section? */
1004 START_CRIT_SECTION();
1006 /* Record subtransaction subcommit */
1007 TransactionIdSubCommit(xid);
1013 /* ----------------------------------------------------------------
1014 * AbortTransaction stuff
1015 * ----------------------------------------------------------------
1019 * RecordTransactionAbort
1022 RecordTransactionAbort(void)
1027 TransactionId *children;
1029 /* Get data needed for abort record */
1030 nrels = smgrGetPendingDeletes(false, &rels);
1031 nchildren = xactGetCommittedChildren(&children);
1034 * If we made neither any transaction-controlled XLOG entries nor any
1035 * temp-rel updates, and are not going to delete any files, we can omit
1036 * recording the transaction abort at all. No one will ever care that it
1037 * aborted. (These tests cover our whole transaction tree.)
1039 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1041 TransactionId xid = GetCurrentTransactionId();
1044 * Catch the scenario where we aborted partway through
1045 * RecordTransactionCommit ...
1047 if (TransactionIdDidCommit(xid))
1048 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1050 START_CRIT_SECTION();
1053 * We only need to log the abort in XLOG if the transaction made any
1054 * transaction-controlled XLOG entries or will delete files. (If it
1055 * made no transaction-controlled XLOG entries, its XID appears
1056 * nowhere in permanent storage, so no one else will ever care if it
1059 * We do not flush XLOG to disk unless deleting files, since the
1060 * default assumption after a crash would be that we aborted, anyway.
1061 * For the same reason, we don't need to worry about interlocking
1062 * against checkpoint start.
1064 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1066 XLogRecData rdata[3];
1068 xl_xact_abort xlrec;
1071 SetCurrentTransactionStopTimestamp();
1072 xlrec.xact_time = xactStopTimestamp;
1073 xlrec.nrels = nrels;
1074 xlrec.nsubxacts = nchildren;
1075 rdata[0].data = (char *) (&xlrec);
1076 rdata[0].len = MinSizeOfXactAbort;
1077 rdata[0].buffer = InvalidBuffer;
1078 /* dump rels to delete */
1081 rdata[0].next = &(rdata[1]);
1082 rdata[1].data = (char *) rels;
1083 rdata[1].len = nrels * sizeof(RelFileNode);
1084 rdata[1].buffer = InvalidBuffer;
1087 /* dump committed child Xids */
1090 rdata[lastrdata].next = &(rdata[2]);
1091 rdata[2].data = (char *) children;
1092 rdata[2].len = nchildren * sizeof(TransactionId);
1093 rdata[2].buffer = InvalidBuffer;
1096 rdata[lastrdata].next = NULL;
1098 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1100 /* Must flush if we are deleting files... */
1106 * Mark the transaction aborted in clog. This is not absolutely
1107 * necessary but we may as well do it while we are here.
1109 * The ordering here isn't critical but it seems best to mark the
1110 * parent first. This assures an atomic transition of all the
1111 * subtransactions to aborted state from the point of view of
1112 * concurrent TransactionIdDidAbort calls.
1114 TransactionIdAbort(xid);
1115 TransactionIdAbortTree(nchildren, children);
1120 /* Break the chain of back-links in the XLOG records I output */
1121 MyLastRecPtr.xrecoff = 0;
1122 MyXactMadeXLogEntry = false;
1123 MyXactMadeTempRelUpdate = false;
1125 /* And clean up local data */
1136 AtAbort_Memory(void)
1139 * Switch into TransactionAbortContext, which should have some free
1140 * space even if nothing else does. We'll work in this context until
1141 * we've finished cleaning up.
1143 * It is barely possible to get here when we've not been able to create
1144 * TransactionAbortContext yet; if so use TopMemoryContext.
1146 if (TransactionAbortContext != NULL)
1147 MemoryContextSwitchTo(TransactionAbortContext);
1149 MemoryContextSwitchTo(TopMemoryContext);
1156 AtSubAbort_Memory(void)
1158 Assert(TransactionAbortContext != NULL);
1160 MemoryContextSwitchTo(TransactionAbortContext);
1165 * AtAbort_ResourceOwner
1168 AtAbort_ResourceOwner(void)
1171 * Make sure we have a valid ResourceOwner, if possible (else it will be
1172 * NULL, which is OK)
1174 CurrentResourceOwner = TopTransactionResourceOwner;
1178 * AtSubAbort_ResourceOwner
1181 AtSubAbort_ResourceOwner(void)
1183 TransactionState s = CurrentTransactionState;
1185 /* Make sure we have a valid ResourceOwner */
1186 CurrentResourceOwner = s->curTransactionOwner;
1191 * AtSubAbort_childXids
1194 AtSubAbort_childXids(void)
1196 TransactionState s = CurrentTransactionState;
1199 * We keep the child-XID lists in TopTransactionContext (see
1200 * AtSubCommit_childXids). This means we'd better free the list
1201 * explicitly at abort to avoid leakage.
1203 list_free(s->childXids);
1208 * RecordSubTransactionAbort
1211 RecordSubTransactionAbort(void)
1215 TransactionId xid = GetCurrentTransactionId();
1217 TransactionId *children;
1219 /* Get data needed for abort record */
1220 nrels = smgrGetPendingDeletes(false, &rels);
1221 nchildren = xactGetCommittedChildren(&children);
1224 * If we made neither any transaction-controlled XLOG entries nor any
1225 * temp-rel updates, and are not going to delete any files, we can omit
1226 * recording the transaction abort at all. No one will ever care that it
1227 * aborted. (These tests cover our whole transaction tree, and therefore
1228 * may mark subxacts that don't really need it, but it's probably not
1229 * worth being tenser.)
1231 * In this case we needn't worry about marking subcommitted children as
1232 * aborted, because they didn't mark themselves as subcommitted in the
1233 * first place; see the optimization in RecordSubTransactionCommit.
1235 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1237 START_CRIT_SECTION();
1240 * We only need to log the abort in XLOG if the transaction made any
1241 * transaction-controlled XLOG entries or will delete files.
1243 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1245 XLogRecData rdata[3];
1247 xl_xact_abort xlrec;
1250 xlrec.xact_time = GetCurrentTimestamp();
1251 xlrec.nrels = nrels;
1252 xlrec.nsubxacts = nchildren;
1253 rdata[0].data = (char *) (&xlrec);
1254 rdata[0].len = MinSizeOfXactAbort;
1255 rdata[0].buffer = InvalidBuffer;
1256 /* dump rels to delete */
1259 rdata[0].next = &(rdata[1]);
1260 rdata[1].data = (char *) rels;
1261 rdata[1].len = nrels * sizeof(RelFileNode);
1262 rdata[1].buffer = InvalidBuffer;
1265 /* dump committed child Xids */
1268 rdata[lastrdata].next = &(rdata[2]);
1269 rdata[2].data = (char *) children;
1270 rdata[2].len = nchildren * sizeof(TransactionId);
1271 rdata[2].buffer = InvalidBuffer;
1274 rdata[lastrdata].next = NULL;
1276 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1278 /* Must flush if we are deleting files... */
1284 * Mark the transaction aborted in clog. This is not absolutely
1285 * necessary but XactLockTableWait makes use of it to avoid waiting
1286 * for already-aborted subtransactions.
1288 TransactionIdAbort(xid);
1289 TransactionIdAbortTree(nchildren, children);
1295 * We can immediately remove failed XIDs from PGPROC's cache of running
1296 * child XIDs. It's easiest to do it here while we have the child XID
1297 * array at hand, even though in the main-transaction case the equivalent
1298 * work happens just after return from RecordTransactionAbort.
1300 XidCacheRemoveRunningXids(xid, nchildren, children);
1302 /* And clean up local data */
1309 /* ----------------------------------------------------------------
1310 * CleanupTransaction stuff
1311 * ----------------------------------------------------------------
1318 AtCleanup_Memory(void)
1320 Assert(CurrentTransactionState->parent == NULL);
1323 * Now that we're "out" of a transaction, have the system allocate things
1324 * in the top memory context instead of per-transaction contexts.
1326 MemoryContextSwitchTo(TopMemoryContext);
1329 * Clear the special abort context for next time.
1331 if (TransactionAbortContext != NULL)
1332 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1335 * Release all transaction-local memory.
1337 if (TopTransactionContext != NULL)
1338 MemoryContextDelete(TopTransactionContext);
1339 TopTransactionContext = NULL;
1340 CurTransactionContext = NULL;
1341 CurrentTransactionState->curTransactionContext = NULL;
1345 /* ----------------------------------------------------------------
1346 * CleanupSubTransaction stuff
1347 * ----------------------------------------------------------------
1351 * AtSubCleanup_Memory
1354 AtSubCleanup_Memory(void)
1356 TransactionState s = CurrentTransactionState;
1358 Assert(s->parent != NULL);
1360 /* Make sure we're not in an about-to-be-deleted context */
1361 MemoryContextSwitchTo(s->parent->curTransactionContext);
1362 CurTransactionContext = s->parent->curTransactionContext;
1365 * Clear the special abort context for next time.
1367 if (TransactionAbortContext != NULL)
1368 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1371 * Delete the subxact local memory contexts. Its CurTransactionContext can
1372 * go too (note this also kills CurTransactionContexts from any children
1375 if (s->curTransactionContext)
1376 MemoryContextDelete(s->curTransactionContext);
1377 s->curTransactionContext = NULL;
1380 /* ----------------------------------------------------------------
1381 * interface routines
1382 * ----------------------------------------------------------------
1389 StartTransaction(void)
1394 * Let's just make sure the state stack is empty
1396 s = &TopTransactionStateData;
1397 CurrentTransactionState = s;
1400 * check the current transaction state
1402 if (s->state != TRANS_DEFAULT)
1403 elog(WARNING, "StartTransaction while in %s state",
1404 TransStateAsString(s->state));
1407 * set the current transaction state information appropriately during
1410 s->state = TRANS_START;
1411 s->transactionId = InvalidTransactionId; /* until assigned */
1414 * Make sure we've freed any old snapshot, and reset xact state variables
1417 XactIsoLevel = DefaultXactIsoLevel;
1418 XactReadOnly = DefaultXactReadOnly;
1421 * reinitialize within-transaction counters
1423 s->subTransactionId = TopSubTransactionId;
1424 currentSubTransactionId = TopSubTransactionId;
1425 currentCommandId = FirstCommandId;
1428 * must initialize resource-management stuff first
1431 AtStart_ResourceOwner();
1434 * generate a new transaction id
1436 s->transactionId = GetNewTransactionId(false);
1438 XactLockTableInsert(s->transactionId);
1440 PG_TRACE1(transaction__start, s->transactionId);
1443 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1444 * as the first command's statement_timestamp(), so don't do a fresh
1445 * GetCurrentTimestamp() call (which'd be expensive anyway). Also,
1446 * mark xactStopTimestamp as unset.
1448 xactStartTimestamp = stmtStartTimestamp;
1449 xactStopTimestamp = 0;
1450 pgstat_report_txn_timestamp(xactStartTimestamp);
1453 * initialize current transaction state fields
1455 s->nestingLevel = 1;
1459 * You might expect to see "s->currentUser = GetUserId();" here, but you
1460 * won't because it doesn't work during startup; the userid isn't set yet
1461 * during a backend's first transaction start. We only use the
1462 * currentUser field in sub-transaction state structs.
1464 * prevXactReadOnly is also valid only in sub-transactions.
1468 * initialize other subsystems for new transaction
1472 AfterTriggerBeginXact();
1475 * done with start processing, set current transaction state to "in
1478 s->state = TRANS_INPROGRESS;
1480 ShowTransactionState("StartTransaction");
1487 * NB: if you change this routine, better look at PrepareTransaction too!
1490 CommitTransaction(void)
1492 TransactionState s = CurrentTransactionState;
1494 ShowTransactionState("CommitTransaction");
1497 * check the current transaction state
1499 if (s->state != TRANS_INPROGRESS)
1500 elog(WARNING, "CommitTransaction while in %s state",
1501 TransStateAsString(s->state));
1502 Assert(s->parent == NULL);
1505 * Do pre-commit processing (most of this stuff requires database access,
1506 * and in fact could still cause an error...)
1508 * It is possible for CommitHoldablePortals to invoke functions that queue
1509 * deferred triggers, and it's also possible that triggers create holdable
1510 * cursors. So we have to loop until there's nothing left to do.
1515 * Fire all currently pending deferred triggers.
1517 AfterTriggerFireDeferred();
1520 * Convert any open holdable cursors into static portals. If there
1521 * weren't any, we are done ... otherwise loop back to check if they
1522 * queued deferred triggers. Lather, rinse, repeat.
1524 if (!CommitHoldablePortals())
1528 /* Now we can shut down the deferred-trigger manager */
1529 AfterTriggerEndXact(true);
1531 /* Close any open regular cursors */
1535 * Let ON COMMIT management do its thing (must happen after closing
1536 * cursors, to avoid dangling-reference problems)
1538 PreCommit_on_commit_actions();
1540 /* close large objects before lower-level cleanup */
1541 AtEOXact_LargeObject(true);
1543 /* NOTIFY commit must come before lower-level cleanup */
1547 * Update flat files if we changed pg_database, pg_authid or
1548 * pg_auth_members. This should be the last step before commit.
1550 AtEOXact_UpdateFlatFiles(true);
1552 /* Prevent cancel/die interrupt while cleaning up */
1556 * set the current transaction state information appropriately during
1559 s->state = TRANS_COMMIT;
1562 * Here is where we really truly commit.
1564 RecordTransactionCommit();
1567 * Let others know about no transaction in progress by me. Note that
1568 * this must be done _before_ releasing locks we hold and _after_
1569 * RecordTransactionCommit.
1571 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1572 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1573 * xid 1 is doing commit while xid 2 gets snapshot.
1574 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1575 * xid 0 as running as well, or it will be able to see two tuple versions
1576 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1579 * Note: MyProc may be null during bootstrap.
1584 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1585 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1586 MyProc->xid = InvalidTransactionId;
1587 MyProc->xmin = InvalidTransactionId;
1588 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1590 /* Clear the subtransaction-XID cache too while holding the lock */
1591 MyProc->subxids.nxids = 0;
1592 MyProc->subxids.overflowed = false;
1594 LWLockRelease(ProcArrayLock);
1597 PG_TRACE1(transaction__commit, s->transactionId);
1600 * This is all post-commit cleanup. Note that if an error is raised here,
1601 * it's too late to abort the transaction. This should be just
1602 * noncritical resource releasing.
1604 * The ordering of operations is not entirely random. The idea is:
1605 * release resources visible to other backends (eg, files, buffer pins);
1606 * then release locks; then release backend-local resources. We want to
1607 * release locks at the point where any backend waiting for us will see
1608 * our transaction as being fully cleaned up.
1610 * Resources that can be associated with individual queries are handled by
1611 * the ResourceOwner mechanism. The other calls here are for backend-wide
1615 CallXactCallbacks(XACT_EVENT_COMMIT);
1617 ResourceOwnerRelease(TopTransactionResourceOwner,
1618 RESOURCE_RELEASE_BEFORE_LOCKS,
1621 /* Check we've released all buffer pins */
1622 AtEOXact_Buffers(true);
1624 /* Clean up the relation cache */
1625 AtEOXact_RelationCache(true);
1628 * Make catalog changes visible to all backends. This has to happen after
1629 * relcache references are dropped (see comments for
1630 * AtEOXact_RelationCache), but before locks are released (if anyone is
1631 * waiting for lock on a relation we've modified, we want them to know
1632 * about the catalog change before they start using the relation).
1634 AtEOXact_Inval(true);
1637 * Likewise, dropping of files deleted during the transaction is best done
1638 * after releasing relcache and buffer pins. (This is not strictly
1639 * necessary during commit, since such pins should have been released
1640 * already, but this ordering is definitely critical during abort.)
1642 smgrDoPendingDeletes(true);
1644 AtEOXact_MultiXact();
1646 ResourceOwnerRelease(TopTransactionResourceOwner,
1647 RESOURCE_RELEASE_LOCKS,
1649 ResourceOwnerRelease(TopTransactionResourceOwner,
1650 RESOURCE_RELEASE_AFTER_LOCKS,
1653 /* Check we've released all catcache entries */
1654 AtEOXact_CatCache(true);
1656 AtEOXact_GUC(true, false);
1658 AtEOXact_on_commit_actions(true);
1659 AtEOXact_Namespace(true);
1660 /* smgrcommit already done */
1662 AtEOXact_ComboCid();
1663 AtEOXact_HashTables(true);
1664 pgstat_clear_snapshot();
1665 pgstat_count_xact_commit();
1666 pgstat_report_txn_timestamp(0);
1668 CurrentResourceOwner = NULL;
1669 ResourceOwnerDelete(TopTransactionResourceOwner);
1670 s->curTransactionOwner = NULL;
1671 CurTransactionResourceOwner = NULL;
1672 TopTransactionResourceOwner = NULL;
1676 s->transactionId = InvalidTransactionId;
1677 s->subTransactionId = InvalidSubTransactionId;
1678 s->nestingLevel = 0;
1682 * done with commit processing, set current transaction state back to
1685 s->state = TRANS_DEFAULT;
1687 RESUME_INTERRUPTS();
1692 * PrepareTransaction
1694 * NB: if you change this routine, better look at CommitTransaction too!
1697 PrepareTransaction(void)
1699 TransactionState s = CurrentTransactionState;
1700 TransactionId xid = GetCurrentTransactionId();
1701 GlobalTransaction gxact;
1702 TimestampTz prepared_at;
1704 ShowTransactionState("PrepareTransaction");
1707 * check the current transaction state
1709 if (s->state != TRANS_INPROGRESS)
1710 elog(WARNING, "PrepareTransaction while in %s state",
1711 TransStateAsString(s->state));
1712 Assert(s->parent == NULL);
1715 * Do pre-commit processing (most of this stuff requires database access,
1716 * and in fact could still cause an error...)
1718 * It is possible for PrepareHoldablePortals to invoke functions that
1719 * queue deferred triggers, and it's also possible that triggers create
1720 * holdable cursors. So we have to loop until there's nothing left to do.
1725 * Fire all currently pending deferred triggers.
1727 AfterTriggerFireDeferred();
1730 * Convert any open holdable cursors into static portals. If there
1731 * weren't any, we are done ... otherwise loop back to check if they
1732 * queued deferred triggers. Lather, rinse, repeat.
1734 if (!PrepareHoldablePortals())
1738 /* Now we can shut down the deferred-trigger manager */
1739 AfterTriggerEndXact(true);
1741 /* Close any open regular cursors */
1745 * Let ON COMMIT management do its thing (must happen after closing
1746 * cursors, to avoid dangling-reference problems)
1748 PreCommit_on_commit_actions();
1750 /* close large objects before lower-level cleanup */
1751 AtEOXact_LargeObject(true);
1753 /* NOTIFY and flatfiles will be handled below */
1755 /* Prevent cancel/die interrupt while cleaning up */
1759 * set the current transaction state information appropriately during
1760 * prepare processing
1762 s->state = TRANS_PREPARE;
1764 prepared_at = GetCurrentTimestamp();
1766 /* Tell bufmgr and smgr to prepare for commit */
1770 * Reserve the GID for this transaction. This could fail if the requested
1771 * GID is invalid or already in use.
1773 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1774 GetUserId(), MyDatabaseId);
1778 * Collect data for the 2PC state file. Note that in general, no actual
1779 * state change should happen in the called modules during this step,
1780 * since it's still possible to fail before commit, and in that case we
1781 * want transaction abort to be able to clean up. (In particular, the
1782 * AtPrepare routines may error out if they find cases they cannot
1783 * handle.) State cleanup should happen in the PostPrepare routines
1784 * below. However, some modules can go ahead and clear state here because
1785 * they wouldn't do anything with it during abort anyway.
1787 * Note: because the 2PC state file records will be replayed in the same
1788 * order they are made, the order of these calls has to match the order in
1789 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1790 * PREPARED; in particular, pay attention to whether things should happen
1791 * before or after releasing the transaction's locks.
1793 StartPrepare(gxact);
1796 AtPrepare_UpdateFlatFiles();
1801 * Here is where we really truly prepare.
1803 * We have to record transaction prepares even if we didn't make any
1804 * updates, because the transaction manager might get confused if we lose
1805 * a global transaction.
1810 * Now we clean up backend-internal state and release internal resources.
1813 /* Break the chain of back-links in the XLOG records I output */
1814 MyLastRecPtr.xrecoff = 0;
1815 MyXactMadeXLogEntry = false;
1816 MyXactMadeTempRelUpdate = false;
1819 * Let others know about no transaction in progress by me. This has to be
1820 * done *after* the prepared transaction has been marked valid, else
1821 * someone may think it is unlocked and recyclable.
1824 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1825 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1826 MyProc->xid = InvalidTransactionId;
1827 MyProc->xmin = InvalidTransactionId;
1828 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1830 /* Clear the subtransaction-XID cache too while holding the lock */
1831 MyProc->subxids.nxids = 0;
1832 MyProc->subxids.overflowed = false;
1834 LWLockRelease(ProcArrayLock);
1837 * This is all post-transaction cleanup. Note that if an error is raised
1838 * here, it's too late to abort the transaction. This should be just
1839 * noncritical resource releasing. See notes in CommitTransaction.
1842 CallXactCallbacks(XACT_EVENT_PREPARE);
1844 ResourceOwnerRelease(TopTransactionResourceOwner,
1845 RESOURCE_RELEASE_BEFORE_LOCKS,
1848 /* Check we've released all buffer pins */
1849 AtEOXact_Buffers(true);
1851 /* Clean up the relation cache */
1852 AtEOXact_RelationCache(true);
1854 /* notify and flatfiles don't need a postprepare call */
1856 PostPrepare_Inval();
1860 AtEOXact_MultiXact();
1862 PostPrepare_Locks(xid);
1864 ResourceOwnerRelease(TopTransactionResourceOwner,
1865 RESOURCE_RELEASE_LOCKS,
1867 ResourceOwnerRelease(TopTransactionResourceOwner,
1868 RESOURCE_RELEASE_AFTER_LOCKS,
1871 /* Check we've released all catcache entries */
1872 AtEOXact_CatCache(true);
1874 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1875 AtEOXact_GUC(true, false);
1877 AtEOXact_on_commit_actions(true);
1878 AtEOXact_Namespace(true);
1879 /* smgrcommit already done */
1881 AtEOXact_ComboCid();
1882 AtEOXact_HashTables(true);
1883 pgstat_clear_snapshot();
1885 CurrentResourceOwner = NULL;
1886 ResourceOwnerDelete(TopTransactionResourceOwner);
1887 s->curTransactionOwner = NULL;
1888 CurTransactionResourceOwner = NULL;
1889 TopTransactionResourceOwner = NULL;
1893 s->transactionId = InvalidTransactionId;
1894 s->subTransactionId = InvalidSubTransactionId;
1895 s->nestingLevel = 0;
1899 * done with 1st phase commit processing, set current transaction state
1902 s->state = TRANS_DEFAULT;
1904 RESUME_INTERRUPTS();
1912 AbortTransaction(void)
1914 TransactionState s = CurrentTransactionState;
1916 /* Prevent cancel/die interrupt while cleaning up */
1919 /* Make sure we have a valid memory context and resource owner */
1921 AtAbort_ResourceOwner();
1924 * Release any LW locks we might be holding as quickly as possible.
1925 * (Regular locks, however, must be held till we finish aborting.)
1926 * Releasing LW locks is critical since we might try to grab them again
1927 * while cleaning up!
1931 /* Clean up buffer I/O and buffer context locks, too */
1936 * Also clean up any open wait for lock, since the lock manager will choke
1937 * if we try to wait for another lock before doing this.
1942 * check the current transaction state
1944 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1945 elog(WARNING, "AbortTransaction while in %s state",
1946 TransStateAsString(s->state));
1947 Assert(s->parent == NULL);
1950 * set the current transaction state information appropriately during the
1953 s->state = TRANS_ABORT;
1956 * Reset user id which might have been changed transiently. We cannot use
1957 * s->currentUser, since it may not be set yet; instead rely on internal
1958 * state of miscinit.c.
1960 * (Note: it is not necessary to restore session authorization here
1961 * because that can only be changed via GUC, and GUC will take care of
1962 * rolling it back if need be. However, an error within a SECURITY
1963 * DEFINER function could send control here with the wrong current
1969 * do abort processing
1971 AfterTriggerEndXact(false);
1973 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1975 AtEOXact_UpdateFlatFiles(false);
1978 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1979 * far as assigning an XID to advertise).
1981 if (TransactionIdIsValid(s->transactionId))
1982 RecordTransactionAbort();
1985 * Let others know about no transaction in progress by me. Note that this
1986 * must be done _before_ releasing locks we hold and _after_
1987 * RecordTransactionAbort.
1991 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1992 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1993 MyProc->xid = InvalidTransactionId;
1994 MyProc->xmin = InvalidTransactionId;
1995 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1996 MyProc->inCommit = false; /* be sure this gets cleared */
1998 /* Clear the subtransaction-XID cache too while holding the lock */
1999 MyProc->subxids.nxids = 0;
2000 MyProc->subxids.overflowed = false;
2002 LWLockRelease(ProcArrayLock);
2005 PG_TRACE1(transaction__abort, s->transactionId);
2008 * Post-abort cleanup. See notes in CommitTransaction() concerning
2012 CallXactCallbacks(XACT_EVENT_ABORT);
2014 ResourceOwnerRelease(TopTransactionResourceOwner,
2015 RESOURCE_RELEASE_BEFORE_LOCKS,
2017 AtEOXact_Buffers(false);
2018 AtEOXact_RelationCache(false);
2019 AtEOXact_Inval(false);
2020 smgrDoPendingDeletes(false);
2021 AtEOXact_MultiXact();
2022 ResourceOwnerRelease(TopTransactionResourceOwner,
2023 RESOURCE_RELEASE_LOCKS,
2025 ResourceOwnerRelease(TopTransactionResourceOwner,
2026 RESOURCE_RELEASE_AFTER_LOCKS,
2028 AtEOXact_CatCache(false);
2030 AtEOXact_GUC(false, false);
2031 AtEOXact_SPI(false);
2032 AtEOXact_on_commit_actions(false);
2033 AtEOXact_Namespace(false);
2036 AtEOXact_ComboCid();
2037 AtEOXact_HashTables(false);
2038 pgstat_clear_snapshot();
2039 pgstat_count_xact_rollback();
2040 pgstat_report_txn_timestamp(0);
2043 * State remains TRANS_ABORT until CleanupTransaction().
2045 RESUME_INTERRUPTS();
2049 * CleanupTransaction
2052 CleanupTransaction(void)
2054 TransactionState s = CurrentTransactionState;
2057 * State should still be TRANS_ABORT from AbortTransaction().
2059 if (s->state != TRANS_ABORT)
2060 elog(FATAL, "CleanupTransaction: unexpected state %s",
2061 TransStateAsString(s->state));
2064 * do abort cleanup processing
2066 AtCleanup_Portals(); /* now safe to release portal memory */
2068 CurrentResourceOwner = NULL; /* and resource owner */
2069 if (TopTransactionResourceOwner)
2070 ResourceOwnerDelete(TopTransactionResourceOwner);
2071 s->curTransactionOwner = NULL;
2072 CurTransactionResourceOwner = NULL;
2073 TopTransactionResourceOwner = NULL;
2075 AtCleanup_Memory(); /* and transaction memory */
2077 s->transactionId = InvalidTransactionId;
2078 s->subTransactionId = InvalidSubTransactionId;
2079 s->nestingLevel = 0;
2083 * done with abort processing, set current transaction state back to
2086 s->state = TRANS_DEFAULT;
2090 * StartTransactionCommand
2093 StartTransactionCommand(void)
2095 TransactionState s = CurrentTransactionState;
2097 switch (s->blockState)
2100 * if we aren't in a transaction block, we just do our usual start
2103 case TBLOCK_DEFAULT:
2105 s->blockState = TBLOCK_STARTED;
2109 * We are somewhere in a transaction block or subtransaction and
2110 * about to start a new command. For now we do nothing, but
2111 * someday we may do command-local resource initialization. (Note
2112 * that any needed CommandCounterIncrement was done by the
2113 * previous CommitTransactionCommand.)
2115 case TBLOCK_INPROGRESS:
2116 case TBLOCK_SUBINPROGRESS:
2120 * Here we are in a failed transaction block (one of the commands
2121 * caused an abort) so we do nothing but remain in the abort
2122 * state. Eventually we will get a ROLLBACK command which will
2123 * get us out of this state. (It is up to other code to ensure
2124 * that no commands other than ROLLBACK will be processed in these
2128 case TBLOCK_SUBABORT:
2131 /* These cases are invalid. */
2132 case TBLOCK_STARTED:
2134 case TBLOCK_SUBBEGIN:
2137 case TBLOCK_ABORT_END:
2138 case TBLOCK_SUBABORT_END:
2139 case TBLOCK_ABORT_PENDING:
2140 case TBLOCK_SUBABORT_PENDING:
2141 case TBLOCK_SUBRESTART:
2142 case TBLOCK_SUBABORT_RESTART:
2143 case TBLOCK_PREPARE:
2144 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2145 BlockStateAsString(s->blockState));
2150 * We must switch to CurTransactionContext before returning. This is
2151 * already done if we called StartTransaction, otherwise not.
2153 Assert(CurTransactionContext != NULL);
2154 MemoryContextSwitchTo(CurTransactionContext);
2158 * CommitTransactionCommand
2161 CommitTransactionCommand(void)
2163 TransactionState s = CurrentTransactionState;
2165 switch (s->blockState)
2168 * This shouldn't happen, because it means the previous
2169 * StartTransactionCommand didn't set the STARTED state
2172 case TBLOCK_DEFAULT:
2173 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2174 BlockStateAsString(s->blockState));
2178 * If we aren't in a transaction block, just do our usual
2179 * transaction commit, and return to the idle state.
2181 case TBLOCK_STARTED:
2182 CommitTransaction();
2183 s->blockState = TBLOCK_DEFAULT;
2187 * We are completing a "BEGIN TRANSACTION" command, so we change
2188 * to the "transaction block in progress" state and return. (We
2189 * assume the BEGIN did nothing to the database, so we need no
2190 * CommandCounterIncrement.)
2193 s->blockState = TBLOCK_INPROGRESS;
2197 * This is the case when we have finished executing a command
2198 * someplace within a transaction block. We increment the command
2199 * counter and return.
2201 case TBLOCK_INPROGRESS:
2202 case TBLOCK_SUBINPROGRESS:
2203 CommandCounterIncrement();
2207 * We are completing a "COMMIT" command. Do it and return to the
2211 CommitTransaction();
2212 s->blockState = TBLOCK_DEFAULT;
2216 * Here we are in the middle of a transaction block but one of the
2217 * commands caused an abort so we do nothing but remain in the
2218 * abort state. Eventually we will get a ROLLBACK comand.
2221 case TBLOCK_SUBABORT:
2225 * Here we were in an aborted transaction block and we just got
2226 * the ROLLBACK command from the user, so clean up the
2227 * already-aborted transaction and return to the idle state.
2229 case TBLOCK_ABORT_END:
2230 CleanupTransaction();
2231 s->blockState = TBLOCK_DEFAULT;
2235 * Here we were in a perfectly good transaction block but the user
2236 * told us to ROLLBACK anyway. We have to abort the transaction
2237 * and then clean up.
2239 case TBLOCK_ABORT_PENDING:
2241 CleanupTransaction();
2242 s->blockState = TBLOCK_DEFAULT;
2246 * We are completing a "PREPARE TRANSACTION" command. Do it and
2247 * return to the idle state.
2249 case TBLOCK_PREPARE:
2250 PrepareTransaction();
2251 s->blockState = TBLOCK_DEFAULT;
2255 * We were just issued a SAVEPOINT inside a transaction block.
2256 * Start a subtransaction. (DefineSavepoint already did
2257 * PushTransaction, so as to have someplace to put the SUBBEGIN
2260 case TBLOCK_SUBBEGIN:
2261 StartSubTransaction();
2262 s->blockState = TBLOCK_SUBINPROGRESS;
2266 * We were issued a COMMIT or RELEASE command, so we end the
2267 * current subtransaction and return to the parent transaction.
2268 * The parent might be ended too, so repeat till we are all the
2269 * way out or find an INPROGRESS transaction.
2274 CommitSubTransaction();
2275 s = CurrentTransactionState; /* changed by pop */
2276 } while (s->blockState == TBLOCK_SUBEND);
2277 /* If we had a COMMIT command, finish off the main xact too */
2278 if (s->blockState == TBLOCK_END)
2280 Assert(s->parent == NULL);
2281 CommitTransaction();
2282 s->blockState = TBLOCK_DEFAULT;
2284 else if (s->blockState == TBLOCK_PREPARE)
2286 Assert(s->parent == NULL);
2287 PrepareTransaction();
2288 s->blockState = TBLOCK_DEFAULT;
2292 Assert(s->blockState == TBLOCK_INPROGRESS ||
2293 s->blockState == TBLOCK_SUBINPROGRESS);
2298 * The current already-failed subtransaction is ending due to a
2299 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2300 * examine the parent (which could be in any of several states).
2302 case TBLOCK_SUBABORT_END:
2303 CleanupSubTransaction();
2304 CommitTransactionCommand();
2308 * As above, but it's not dead yet, so abort first.
2310 case TBLOCK_SUBABORT_PENDING:
2311 AbortSubTransaction();
2312 CleanupSubTransaction();
2313 CommitTransactionCommand();
2317 * The current subtransaction is the target of a ROLLBACK TO
2318 * command. Abort and pop it, then start a new subtransaction
2319 * with the same name.
2321 case TBLOCK_SUBRESTART:
2326 /* save name and keep Cleanup from freeing it */
2329 savepointLevel = s->savepointLevel;
2331 AbortSubTransaction();
2332 CleanupSubTransaction();
2334 DefineSavepoint(NULL);
2335 s = CurrentTransactionState; /* changed by push */
2337 s->savepointLevel = savepointLevel;
2339 /* This is the same as TBLOCK_SUBBEGIN case */
2340 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2341 StartSubTransaction();
2342 s->blockState = TBLOCK_SUBINPROGRESS;
2347 * Same as above, but the subtransaction had already failed, so we
2348 * don't need AbortSubTransaction.
2350 case TBLOCK_SUBABORT_RESTART:
2355 /* save name and keep Cleanup from freeing it */
2358 savepointLevel = s->savepointLevel;
2360 CleanupSubTransaction();
2362 DefineSavepoint(NULL);
2363 s = CurrentTransactionState; /* changed by push */
2365 s->savepointLevel = savepointLevel;
2367 /* This is the same as TBLOCK_SUBBEGIN case */
2368 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2369 StartSubTransaction();
2370 s->blockState = TBLOCK_SUBINPROGRESS;
2377 * AbortCurrentTransaction
2380 AbortCurrentTransaction(void)
2382 TransactionState s = CurrentTransactionState;
2384 switch (s->blockState)
2386 case TBLOCK_DEFAULT:
2387 if (s->state == TRANS_DEFAULT)
2389 /* we are idle, so nothing to do */
2394 * We can get here after an error during transaction start
2395 * (state will be TRANS_START). Need to clean up the
2396 * incompletely started transaction. First, adjust the
2397 * low-level state to suppress warning message from
2400 if (s->state == TRANS_START)
2401 s->state = TRANS_INPROGRESS;
2403 CleanupTransaction();
2408 * if we aren't in a transaction block, we just do the basic abort
2409 * & cleanup transaction.
2411 case TBLOCK_STARTED:
2413 CleanupTransaction();
2414 s->blockState = TBLOCK_DEFAULT;
2418 * If we are in TBLOCK_BEGIN it means something screwed up right
2419 * after reading "BEGIN TRANSACTION". We assume that the user
2420 * will interpret the error as meaning the BEGIN failed to get him
2421 * into a transaction block, so we should abort and return to idle
2426 CleanupTransaction();
2427 s->blockState = TBLOCK_DEFAULT;
2431 * We are somewhere in a transaction block and we've gotten a
2432 * failure, so we abort the transaction and set up the persistent
2433 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2435 case TBLOCK_INPROGRESS:
2437 s->blockState = TBLOCK_ABORT;
2438 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2442 * Here, we failed while trying to COMMIT. Clean up the
2443 * transaction and return to idle state (we do not want to stay in
2448 CleanupTransaction();
2449 s->blockState = TBLOCK_DEFAULT;
2453 * Here, we are already in an aborted transaction state and are
2454 * waiting for a ROLLBACK, but for some reason we failed again! So
2455 * we just remain in the abort state.
2458 case TBLOCK_SUBABORT:
2462 * We are in a failed transaction and we got the ROLLBACK command.
2463 * We have already aborted, we just need to cleanup and go to idle
2466 case TBLOCK_ABORT_END:
2467 CleanupTransaction();
2468 s->blockState = TBLOCK_DEFAULT;
2472 * We are in a live transaction and we got a ROLLBACK command.
2473 * Abort, cleanup, go to idle state.
2475 case TBLOCK_ABORT_PENDING:
2477 CleanupTransaction();
2478 s->blockState = TBLOCK_DEFAULT;
2482 * Here, we failed while trying to PREPARE. Clean up the
2483 * transaction and return to idle state (we do not want to stay in
2486 case TBLOCK_PREPARE:
2488 CleanupTransaction();
2489 s->blockState = TBLOCK_DEFAULT;
2493 * We got an error inside a subtransaction. Abort just the
2494 * subtransaction, and go to the persistent SUBABORT state until
2497 case TBLOCK_SUBINPROGRESS:
2498 AbortSubTransaction();
2499 s->blockState = TBLOCK_SUBABORT;
2503 * If we failed while trying to create a subtransaction, clean up
2504 * the broken subtransaction and abort the parent. The same
2505 * applies if we get a failure while ending a subtransaction.
2507 case TBLOCK_SUBBEGIN:
2509 case TBLOCK_SUBABORT_PENDING:
2510 case TBLOCK_SUBRESTART:
2511 AbortSubTransaction();
2512 CleanupSubTransaction();
2513 AbortCurrentTransaction();
2517 * Same as above, except the Abort() was already done.
2519 case TBLOCK_SUBABORT_END:
2520 case TBLOCK_SUBABORT_RESTART:
2521 CleanupSubTransaction();
2522 AbortCurrentTransaction();
2528 * PreventTransactionChain
2530 * This routine is to be called by statements that must not run inside
2531 * a transaction block, typically because they have non-rollback-able
2532 * side effects or do internal commits.
2534 * If we have already started a transaction block, issue an error; also issue
2535 * an error if we appear to be running inside a user-defined function (which
2536 * could issue more commands and possibly cause a failure after the statement
2537 * completes). Subtransactions are verboten too.
2539 * isTopLevel: passed down from ProcessUtility to determine whether we are
2540 * inside a function or multi-query querystring. (We will always fail if
2541 * this is false, but it's convenient to centralize the check here instead of
2542 * making callers do it.)
2543 * stmtType: statement type name, for error messages.
2546 PreventTransactionChain(bool isTopLevel, const char *stmtType)
2549 * xact block already started?
2551 if (IsTransactionBlock())
2553 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2554 /* translator: %s represents an SQL statement name */
2555 errmsg("%s cannot run inside a transaction block",
2561 if (IsSubTransaction())
2563 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2564 /* translator: %s represents an SQL statement name */
2565 errmsg("%s cannot run inside a subtransaction",
2569 * inside a function call?
2573 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2574 /* translator: %s represents an SQL statement name */
2575 errmsg("%s cannot be executed from a function or multi-command string",
2578 /* If we got past IsTransactionBlock test, should be in default state */
2579 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2580 CurrentTransactionState->blockState != TBLOCK_STARTED)
2581 elog(FATAL, "cannot prevent transaction chain");
2586 * RequireTransactionChain
2588 * This routine is to be called by statements that must run inside
2589 * a transaction block, because they have no effects that persist past
2590 * transaction end (and so calling them outside a transaction block
2591 * is presumably an error). DECLARE CURSOR is an example.
2593 * If we appear to be running inside a user-defined function, we do not
2594 * issue an error, since the function could issue more commands that make
2595 * use of the current statement's results. Likewise subtransactions.
2596 * Thus this is an inverse for PreventTransactionChain.
2598 * isTopLevel: passed down from ProcessUtility to determine whether we are
2599 * inside a function.
2600 * stmtType: statement type name, for error messages.
2603 RequireTransactionChain(bool isTopLevel, const char *stmtType)
2606 * xact block already started?
2608 if (IsTransactionBlock())
2614 if (IsSubTransaction())
2618 * inside a function call?
2624 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2625 /* translator: %s represents an SQL statement name */
2626 errmsg("%s can only be used in transaction blocks",
2631 * IsInTransactionChain
2633 * This routine is for statements that need to behave differently inside
2634 * a transaction block than when running as single commands. ANALYZE is
2635 * currently the only example.
2637 * isTopLevel: passed down from ProcessUtility to determine whether we are
2638 * inside a function.
2641 IsInTransactionChain(bool isTopLevel)
2644 * Return true on same conditions that would make PreventTransactionChain
2647 if (IsTransactionBlock())
2650 if (IsSubTransaction())
2656 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2657 CurrentTransactionState->blockState != TBLOCK_STARTED)
2665 * Register or deregister callback functions for start- and end-of-xact
2668 * These functions are intended for use by dynamically loaded modules.
2669 * For built-in modules we generally just hardwire the appropriate calls
2670 * (mainly because it's easier to control the order that way, where needed).
2672 * At transaction end, the callback occurs post-commit or post-abort, so the
2673 * callback functions can only do noncritical cleanup.
2676 RegisterXactCallback(XactCallback callback, void *arg)
2678 XactCallbackItem *item;
2680 item = (XactCallbackItem *)
2681 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2682 item->callback = callback;
2684 item->next = Xact_callbacks;
2685 Xact_callbacks = item;
2689 UnregisterXactCallback(XactCallback callback, void *arg)
2691 XactCallbackItem *item;
2692 XactCallbackItem *prev;
2695 for (item = Xact_callbacks; item; prev = item, item = item->next)
2697 if (item->callback == callback && item->arg == arg)
2700 prev->next = item->next;
2702 Xact_callbacks = item->next;
2710 CallXactCallbacks(XactEvent event)
2712 XactCallbackItem *item;
2714 for (item = Xact_callbacks; item; item = item->next)
2715 (*item->callback) (event, item->arg);
2720 * Register or deregister callback functions for start- and end-of-subxact
2723 * Pretty much same as above, but for subtransaction events.
2725 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2726 * so the callback functions can only do noncritical cleanup. At
2727 * subtransaction start, the callback is called when the subtransaction has
2728 * finished initializing.
2731 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2733 SubXactCallbackItem *item;
2735 item = (SubXactCallbackItem *)
2736 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2737 item->callback = callback;
2739 item->next = SubXact_callbacks;
2740 SubXact_callbacks = item;
2744 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2746 SubXactCallbackItem *item;
2747 SubXactCallbackItem *prev;
2750 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2752 if (item->callback == callback && item->arg == arg)
2755 prev->next = item->next;
2757 SubXact_callbacks = item->next;
2765 CallSubXactCallbacks(SubXactEvent event,
2766 SubTransactionId mySubid,
2767 SubTransactionId parentSubid)
2769 SubXactCallbackItem *item;
2771 for (item = SubXact_callbacks; item; item = item->next)
2772 (*item->callback) (event, mySubid, parentSubid, item->arg);
2776 /* ----------------------------------------------------------------
2777 * transaction block support
2778 * ----------------------------------------------------------------
2782 * BeginTransactionBlock
2783 * This executes a BEGIN command.
2786 BeginTransactionBlock(void)
2788 TransactionState s = CurrentTransactionState;
2790 switch (s->blockState)
2793 * We are not inside a transaction block, so allow one to begin.
2795 case TBLOCK_STARTED:
2796 s->blockState = TBLOCK_BEGIN;
2800 * Already a transaction block in progress.
2802 case TBLOCK_INPROGRESS:
2803 case TBLOCK_SUBINPROGRESS:
2805 case TBLOCK_SUBABORT:
2807 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2808 errmsg("there is already a transaction in progress")));
2811 /* These cases are invalid. */
2812 case TBLOCK_DEFAULT:
2814 case TBLOCK_SUBBEGIN:
2817 case TBLOCK_ABORT_END:
2818 case TBLOCK_SUBABORT_END:
2819 case TBLOCK_ABORT_PENDING:
2820 case TBLOCK_SUBABORT_PENDING:
2821 case TBLOCK_SUBRESTART:
2822 case TBLOCK_SUBABORT_RESTART:
2823 case TBLOCK_PREPARE:
2824 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2825 BlockStateAsString(s->blockState));
2831 * PrepareTransactionBlock
2832 * This executes a PREPARE command.
2834 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2835 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2837 * Note that we don't actually do anything here except change blockState.
2838 * The real work will be done in the upcoming PrepareTransaction().
2839 * We do it this way because it's not convenient to change memory context,
2840 * resource owner, etc while executing inside a Portal.
2843 PrepareTransactionBlock(char *gid)
2848 /* Set up to commit the current transaction */
2849 result = EndTransactionBlock();
2851 /* If successful, change outer tblock state to PREPARE */
2854 s = CurrentTransactionState;
2856 while (s->parent != NULL)
2859 if (s->blockState == TBLOCK_END)
2861 /* Save GID where PrepareTransaction can find it again */
2862 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2864 s->blockState = TBLOCK_PREPARE;
2869 * ignore case where we are not in a transaction;
2870 * EndTransactionBlock already issued a warning.
2872 Assert(s->blockState == TBLOCK_STARTED);
2873 /* Don't send back a PREPARE result tag... */
2882 * EndTransactionBlock
2883 * This executes a COMMIT command.
2885 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2886 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2888 * Note that we don't actually do anything here except change blockState.
2889 * The real work will be done in the upcoming CommitTransactionCommand().
2890 * We do it this way because it's not convenient to change memory context,
2891 * resource owner, etc while executing inside a Portal.
2894 EndTransactionBlock(void)
2896 TransactionState s = CurrentTransactionState;
2897 bool result = false;
2899 switch (s->blockState)
2902 * We are in a transaction block, so tell CommitTransactionCommand
2905 case TBLOCK_INPROGRESS:
2906 s->blockState = TBLOCK_END;
2911 * We are in a failed transaction block. Tell
2912 * CommitTransactionCommand it's time to exit the block.
2915 s->blockState = TBLOCK_ABORT_END;
2919 * We are in a live subtransaction block. Set up to subcommit all
2920 * open subtransactions and then commit the main transaction.
2922 case TBLOCK_SUBINPROGRESS:
2923 while (s->parent != NULL)
2925 if (s->blockState == TBLOCK_SUBINPROGRESS)
2926 s->blockState = TBLOCK_SUBEND;
2928 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2929 BlockStateAsString(s->blockState));
2932 if (s->blockState == TBLOCK_INPROGRESS)
2933 s->blockState = TBLOCK_END;
2935 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2936 BlockStateAsString(s->blockState));
2941 * Here we are inside an aborted subtransaction. Treat the COMMIT
2942 * as ROLLBACK: set up to abort everything and exit the main
2945 case TBLOCK_SUBABORT:
2946 while (s->parent != NULL)
2948 if (s->blockState == TBLOCK_SUBINPROGRESS)
2949 s->blockState = TBLOCK_SUBABORT_PENDING;
2950 else if (s->blockState == TBLOCK_SUBABORT)
2951 s->blockState = TBLOCK_SUBABORT_END;
2953 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2954 BlockStateAsString(s->blockState));
2957 if (s->blockState == TBLOCK_INPROGRESS)
2958 s->blockState = TBLOCK_ABORT_PENDING;
2959 else if (s->blockState == TBLOCK_ABORT)
2960 s->blockState = TBLOCK_ABORT_END;
2962 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2963 BlockStateAsString(s->blockState));
2967 * The user issued COMMIT when not inside a transaction. Issue a
2968 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2969 * CommitTransactionCommand() will then close the transaction and
2970 * put us back into the default state.
2972 case TBLOCK_STARTED:
2974 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2975 errmsg("there is no transaction in progress")));
2979 /* These cases are invalid. */
2980 case TBLOCK_DEFAULT:
2982 case TBLOCK_SUBBEGIN:
2985 case TBLOCK_ABORT_END:
2986 case TBLOCK_SUBABORT_END:
2987 case TBLOCK_ABORT_PENDING:
2988 case TBLOCK_SUBABORT_PENDING:
2989 case TBLOCK_SUBRESTART:
2990 case TBLOCK_SUBABORT_RESTART:
2991 case TBLOCK_PREPARE:
2992 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2993 BlockStateAsString(s->blockState));
3001 * UserAbortTransactionBlock
3002 * This executes a ROLLBACK command.
3004 * As above, we don't actually do anything here except change blockState.
3007 UserAbortTransactionBlock(void)
3009 TransactionState s = CurrentTransactionState;
3011 switch (s->blockState)
3014 * We are inside a transaction block and we got a ROLLBACK command
3015 * from the user, so tell CommitTransactionCommand to abort and
3016 * exit the transaction block.
3018 case TBLOCK_INPROGRESS:
3019 s->blockState = TBLOCK_ABORT_PENDING;
3023 * We are inside a failed transaction block and we got a ROLLBACK
3024 * command from the user. Abort processing is already done, so
3025 * CommitTransactionCommand just has to cleanup and go back to
3029 s->blockState = TBLOCK_ABORT_END;
3033 * We are inside a subtransaction. Mark everything up to top
3034 * level as exitable.
3036 case TBLOCK_SUBINPROGRESS:
3037 case TBLOCK_SUBABORT:
3038 while (s->parent != NULL)
3040 if (s->blockState == TBLOCK_SUBINPROGRESS)
3041 s->blockState = TBLOCK_SUBABORT_PENDING;
3042 else if (s->blockState == TBLOCK_SUBABORT)
3043 s->blockState = TBLOCK_SUBABORT_END;
3045 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3046 BlockStateAsString(s->blockState));
3049 if (s->blockState == TBLOCK_INPROGRESS)
3050 s->blockState = TBLOCK_ABORT_PENDING;
3051 else if (s->blockState == TBLOCK_ABORT)
3052 s->blockState = TBLOCK_ABORT_END;
3054 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3055 BlockStateAsString(s->blockState));
3059 * The user issued ABORT when not inside a transaction. Issue a
3060 * WARNING and go to abort state. The upcoming call to
3061 * CommitTransactionCommand() will then put us back into the
3064 case TBLOCK_STARTED:
3066 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3067 errmsg("there is no transaction in progress")));
3068 s->blockState = TBLOCK_ABORT_PENDING;
3071 /* These cases are invalid. */
3072 case TBLOCK_DEFAULT:
3074 case TBLOCK_SUBBEGIN:
3077 case TBLOCK_ABORT_END:
3078 case TBLOCK_SUBABORT_END:
3079 case TBLOCK_ABORT_PENDING:
3080 case TBLOCK_SUBABORT_PENDING:
3081 case TBLOCK_SUBRESTART:
3082 case TBLOCK_SUBABORT_RESTART:
3083 case TBLOCK_PREPARE:
3084 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3085 BlockStateAsString(s->blockState));
3092 * This executes a SAVEPOINT command.
3095 DefineSavepoint(char *name)
3097 TransactionState s = CurrentTransactionState;
3099 switch (s->blockState)
3101 case TBLOCK_INPROGRESS:
3102 case TBLOCK_SUBINPROGRESS:
3103 /* Normal subtransaction start */
3105 s = CurrentTransactionState; /* changed by push */
3108 * Savepoint names, like the TransactionState block itself, live
3109 * in TopTransactionContext.
3112 s->name = MemoryContextStrdup(TopTransactionContext, name);
3115 /* These cases are invalid. */
3116 case TBLOCK_DEFAULT:
3117 case TBLOCK_STARTED:
3119 case TBLOCK_SUBBEGIN:
3123 case TBLOCK_SUBABORT:
3124 case TBLOCK_ABORT_END:
3125 case TBLOCK_SUBABORT_END:
3126 case TBLOCK_ABORT_PENDING:
3127 case TBLOCK_SUBABORT_PENDING:
3128 case TBLOCK_SUBRESTART:
3129 case TBLOCK_SUBABORT_RESTART:
3130 case TBLOCK_PREPARE:
3131 elog(FATAL, "DefineSavepoint: unexpected state %s",
3132 BlockStateAsString(s->blockState));
3139 * This executes a RELEASE command.
3141 * As above, we don't actually do anything here except change blockState.
3144 ReleaseSavepoint(List *options)
3146 TransactionState s = CurrentTransactionState;
3147 TransactionState target,
3152 switch (s->blockState)
3155 * We can't rollback to a savepoint if there is no savepoint
3158 case TBLOCK_INPROGRESS:
3160 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3161 errmsg("no such savepoint")));
3165 * We are in a non-aborted subtransaction. This is the only valid
3168 case TBLOCK_SUBINPROGRESS:
3171 /* These cases are invalid. */
3172 case TBLOCK_DEFAULT:
3173 case TBLOCK_STARTED:
3175 case TBLOCK_SUBBEGIN:
3179 case TBLOCK_SUBABORT:
3180 case TBLOCK_ABORT_END:
3181 case TBLOCK_SUBABORT_END:
3182 case TBLOCK_ABORT_PENDING:
3183 case TBLOCK_SUBABORT_PENDING:
3184 case TBLOCK_SUBRESTART:
3185 case TBLOCK_SUBABORT_RESTART:
3186 case TBLOCK_PREPARE:
3187 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3188 BlockStateAsString(s->blockState));
3192 foreach(cell, options)
3194 DefElem *elem = lfirst(cell);
3196 if (strcmp(elem->defname, "savepoint_name") == 0)
3197 name = strVal(elem->arg);
3200 Assert(PointerIsValid(name));
3202 for (target = s; PointerIsValid(target); target = target->parent)
3204 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3208 if (!PointerIsValid(target))
3210 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3211 errmsg("no such savepoint")));
3213 /* disallow crossing savepoint level boundaries */
3214 if (target->savepointLevel != s->savepointLevel)
3216 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3217 errmsg("no such savepoint")));
3220 * Mark "commit pending" all subtransactions up to the target
3221 * subtransaction. The actual commits will happen when control gets to
3222 * CommitTransactionCommand.
3224 xact = CurrentTransactionState;
3227 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3228 xact->blockState = TBLOCK_SUBEND;
3231 xact = xact->parent;
3232 Assert(PointerIsValid(xact));
3237 * RollbackToSavepoint
3238 * This executes a ROLLBACK TO <savepoint> command.
3240 * As above, we don't actually do anything here except change blockState.
3243 RollbackToSavepoint(List *options)
3245 TransactionState s = CurrentTransactionState;
3246 TransactionState target,
3251 switch (s->blockState)
3254 * We can't rollback to a savepoint if there is no savepoint
3257 case TBLOCK_INPROGRESS:
3260 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3261 errmsg("no such savepoint")));
3265 * There is at least one savepoint, so proceed.
3267 case TBLOCK_SUBINPROGRESS:
3268 case TBLOCK_SUBABORT:
3271 /* These cases are invalid. */
3272 case TBLOCK_DEFAULT:
3273 case TBLOCK_STARTED:
3275 case TBLOCK_SUBBEGIN:
3278 case TBLOCK_ABORT_END:
3279 case TBLOCK_SUBABORT_END:
3280 case TBLOCK_ABORT_PENDING:
3281 case TBLOCK_SUBABORT_PENDING:
3282 case TBLOCK_SUBRESTART:
3283 case TBLOCK_SUBABORT_RESTART:
3284 case TBLOCK_PREPARE:
3285 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3286 BlockStateAsString(s->blockState));
3290 foreach(cell, options)
3292 DefElem *elem = lfirst(cell);
3294 if (strcmp(elem->defname, "savepoint_name") == 0)
3295 name = strVal(elem->arg);
3298 Assert(PointerIsValid(name));
3300 for (target = s; PointerIsValid(target); target = target->parent)
3302 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3306 if (!PointerIsValid(target))
3308 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3309 errmsg("no such savepoint")));
3311 /* disallow crossing savepoint level boundaries */
3312 if (target->savepointLevel != s->savepointLevel)
3314 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3315 errmsg("no such savepoint")));
3318 * Mark "abort pending" all subtransactions up to the target
3319 * subtransaction. The actual aborts will happen when control gets to
3320 * CommitTransactionCommand.
3322 xact = CurrentTransactionState;
3327 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3328 xact->blockState = TBLOCK_SUBABORT_PENDING;
3329 else if (xact->blockState == TBLOCK_SUBABORT)
3330 xact->blockState = TBLOCK_SUBABORT_END;
3332 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3333 BlockStateAsString(xact->blockState));
3334 xact = xact->parent;
3335 Assert(PointerIsValid(xact));
3338 /* And mark the target as "restart pending" */
3339 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3340 xact->blockState = TBLOCK_SUBRESTART;
3341 else if (xact->blockState == TBLOCK_SUBABORT)
3342 xact->blockState = TBLOCK_SUBABORT_RESTART;
3344 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3345 BlockStateAsString(xact->blockState));
3349 * BeginInternalSubTransaction
3350 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3351 * state, and therefore it can safely be used in a function that might
3352 * be called when not inside a BEGIN block. Also, we automatically
3353 * cycle through CommitTransactionCommand/StartTransactionCommand
3354 * instead of expecting the caller to do it.
3357 BeginInternalSubTransaction(char *name)
3359 TransactionState s = CurrentTransactionState;
3361 switch (s->blockState)
3363 case TBLOCK_STARTED:
3364 case TBLOCK_INPROGRESS:
3365 case TBLOCK_SUBINPROGRESS:
3366 /* Normal subtransaction start */
3368 s = CurrentTransactionState; /* changed by push */
3371 * Savepoint names, like the TransactionState block itself, live
3372 * in TopTransactionContext.
3375 s->name = MemoryContextStrdup(TopTransactionContext, name);
3378 /* These cases are invalid. */
3379 case TBLOCK_DEFAULT:
3381 case TBLOCK_SUBBEGIN:
3385 case TBLOCK_SUBABORT:
3386 case TBLOCK_ABORT_END:
3387 case TBLOCK_SUBABORT_END:
3388 case TBLOCK_ABORT_PENDING:
3389 case TBLOCK_SUBABORT_PENDING:
3390 case TBLOCK_SUBRESTART:
3391 case TBLOCK_SUBABORT_RESTART:
3392 case TBLOCK_PREPARE:
3393 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3394 BlockStateAsString(s->blockState));
3398 CommitTransactionCommand();
3399 StartTransactionCommand();
3403 * ReleaseCurrentSubTransaction
3405 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3406 * savepoint name (if any).
3407 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3410 ReleaseCurrentSubTransaction(void)
3412 TransactionState s = CurrentTransactionState;
3414 if (s->blockState != TBLOCK_SUBINPROGRESS)
3415 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3416 BlockStateAsString(s->blockState));
3417 Assert(s->state == TRANS_INPROGRESS);
3418 MemoryContextSwitchTo(CurTransactionContext);
3419 CommitSubTransaction();
3420 s = CurrentTransactionState; /* changed by pop */
3421 Assert(s->state == TRANS_INPROGRESS);
3425 * RollbackAndReleaseCurrentSubTransaction
3427 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3428 * of its savepoint name (if any).
3429 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3432 RollbackAndReleaseCurrentSubTransaction(void)
3434 TransactionState s = CurrentTransactionState;
3436 switch (s->blockState)
3438 /* Must be in a subtransaction */
3439 case TBLOCK_SUBINPROGRESS:
3440 case TBLOCK_SUBABORT:
3443 /* These cases are invalid. */
3444 case TBLOCK_DEFAULT:
3445 case TBLOCK_STARTED:
3447 case TBLOCK_SUBBEGIN:
3448 case TBLOCK_INPROGRESS:
3452 case TBLOCK_ABORT_END:
3453 case TBLOCK_SUBABORT_END:
3454 case TBLOCK_ABORT_PENDING:
3455 case TBLOCK_SUBABORT_PENDING:
3456 case TBLOCK_SUBRESTART:
3457 case TBLOCK_SUBABORT_RESTART:
3458 case TBLOCK_PREPARE:
3459 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3460 BlockStateAsString(s->blockState));
3465 * Abort the current subtransaction, if needed.
3467 if (s->blockState == TBLOCK_SUBINPROGRESS)
3468 AbortSubTransaction();
3470 /* And clean it up, too */
3471 CleanupSubTransaction();
3473 s = CurrentTransactionState; /* changed by pop */
3474 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3475 s->blockState == TBLOCK_INPROGRESS ||
3476 s->blockState == TBLOCK_STARTED);
3480 * AbortOutOfAnyTransaction
3482 * This routine is provided for error recovery purposes. It aborts any
3483 * active transaction or transaction block, leaving the system in a known
3487 AbortOutOfAnyTransaction(void)
3489 TransactionState s = CurrentTransactionState;
3492 * Get out of any transaction or nested transaction
3496 switch (s->blockState)
3498 case TBLOCK_DEFAULT:
3499 /* Not in a transaction, do nothing */
3501 case TBLOCK_STARTED:
3503 case TBLOCK_INPROGRESS:
3505 case TBLOCK_ABORT_PENDING:
3506 case TBLOCK_PREPARE:
3507 /* In a transaction, so clean up */
3509 CleanupTransaction();
3510 s->blockState = TBLOCK_DEFAULT;
3513 case TBLOCK_ABORT_END:
3514 /* AbortTransaction already done, still need Cleanup */
3515 CleanupTransaction();
3516 s->blockState = TBLOCK_DEFAULT;
3520 * In a subtransaction, so clean it up and abort parent too
3522 case TBLOCK_SUBBEGIN:
3523 case TBLOCK_SUBINPROGRESS:
3525 case TBLOCK_SUBABORT_PENDING:
3526 case TBLOCK_SUBRESTART:
3527 AbortSubTransaction();
3528 CleanupSubTransaction();
3529 s = CurrentTransactionState; /* changed by pop */
3532 case TBLOCK_SUBABORT:
3533 case TBLOCK_SUBABORT_END:
3534 case TBLOCK_SUBABORT_RESTART:
3535 /* As above, but AbortSubTransaction already done */
3536 CleanupSubTransaction();
3537 s = CurrentTransactionState; /* changed by pop */
3540 } while (s->blockState != TBLOCK_DEFAULT);
3542 /* Should be out of all subxacts now */
3543 Assert(s->parent == NULL);
3547 * IsTransactionBlock --- are we within a transaction block?
3550 IsTransactionBlock(void)
3552 TransactionState s = CurrentTransactionState;
3554 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3561 * IsTransactionOrTransactionBlock --- are we within either a transaction
3562 * or a transaction block? (The backend is only really "idle" when this
3565 * This should match up with IsTransactionBlock and IsTransactionState.
3568 IsTransactionOrTransactionBlock(void)
3570 TransactionState s = CurrentTransactionState;
3572 if (s->blockState == TBLOCK_DEFAULT)
3579 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3582 TransactionBlockStatusCode(void)
3584 TransactionState s = CurrentTransactionState;
3586 switch (s->blockState)
3588 case TBLOCK_DEFAULT:
3589 case TBLOCK_STARTED:
3590 return 'I'; /* idle --- not in transaction */
3592 case TBLOCK_SUBBEGIN:
3593 case TBLOCK_INPROGRESS:
3594 case TBLOCK_SUBINPROGRESS:
3597 case TBLOCK_PREPARE:
3598 return 'T'; /* in transaction */
3600 case TBLOCK_SUBABORT:
3601 case TBLOCK_ABORT_END:
3602 case TBLOCK_SUBABORT_END:
3603 case TBLOCK_ABORT_PENDING:
3604 case TBLOCK_SUBABORT_PENDING:
3605 case TBLOCK_SUBRESTART:
3606 case TBLOCK_SUBABORT_RESTART:
3607 return 'E'; /* in failed transaction */
3610 /* should never get here */
3611 elog(FATAL, "invalid transaction block state: %s",
3612 BlockStateAsString(s->blockState));
3613 return 0; /* keep compiler quiet */
3620 IsSubTransaction(void)
3622 TransactionState s = CurrentTransactionState;
3624 if (s->nestingLevel >= 2)
3631 * StartSubTransaction
3633 * If you're wondering why this is separate from PushTransaction: it's because
3634 * we can't conveniently do this stuff right inside DefineSavepoint. The
3635 * SAVEPOINT utility command will be executed inside a Portal, and if we
3636 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3637 * the Portal will undo those settings. So we make DefineSavepoint just
3638 * push a dummy transaction block, and when control returns to the main
3639 * idle loop, CommitTransactionCommand will be called, and we'll come here
3640 * to finish starting the subtransaction.
3643 StartSubTransaction(void)
3645 TransactionState s = CurrentTransactionState;
3647 if (s->state != TRANS_DEFAULT)
3648 elog(WARNING, "StartSubTransaction while in %s state",
3649 TransStateAsString(s->state));
3651 s->state = TRANS_START;
3654 * Initialize subsystems for new subtransaction
3656 * must initialize resource-management stuff first
3658 AtSubStart_Memory();
3659 AtSubStart_ResourceOwner();
3661 AtSubStart_Notify();
3662 AfterTriggerBeginSubXact();
3664 s->state = TRANS_INPROGRESS;
3667 * Call start-of-subxact callbacks
3669 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3670 s->parent->subTransactionId);
3672 ShowTransactionState("StartSubTransaction");
3676 * CommitSubTransaction
3678 * The caller has to make sure to always reassign CurrentTransactionState
3679 * if it has a local pointer to it after calling this function.
3682 CommitSubTransaction(void)
3684 TransactionState s = CurrentTransactionState;
3686 ShowTransactionState("CommitSubTransaction");
3688 if (s->state != TRANS_INPROGRESS)
3689 elog(WARNING, "CommitSubTransaction while in %s state",
3690 TransStateAsString(s->state));
3692 /* Pre-commit processing goes here -- nothing to do at the moment */
3694 s->state = TRANS_COMMIT;
3696 /* Must CCI to ensure commands of subtransaction are seen as done */
3697 CommandCounterIncrement();
3699 /* Mark subtransaction as subcommitted */
3700 if (TransactionIdIsValid(s->transactionId))
3702 RecordSubTransactionCommit();
3703 AtSubCommit_childXids();
3706 /* Post-commit cleanup */
3707 AfterTriggerEndSubXact(true);
3708 AtSubCommit_Portals(s->subTransactionId,
3709 s->parent->subTransactionId,
3710 s->parent->curTransactionOwner);
3711 AtEOSubXact_LargeObject(true, s->subTransactionId,
3712 s->parent->subTransactionId);
3713 AtSubCommit_Notify();
3714 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3715 s->parent->subTransactionId);
3717 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3718 s->parent->subTransactionId);
3720 ResourceOwnerRelease(s->curTransactionOwner,
3721 RESOURCE_RELEASE_BEFORE_LOCKS,
3723 AtEOSubXact_RelationCache(true, s->subTransactionId,
3724 s->parent->subTransactionId);
3725 AtEOSubXact_Inval(true);
3729 * The only lock we actually release here is the subtransaction XID lock.
3730 * The rest just get transferred to the parent resource owner.
3732 CurrentResourceOwner = s->curTransactionOwner;
3733 if (TransactionIdIsValid(s->transactionId))
3734 XactLockTableDelete(s->transactionId);
3736 ResourceOwnerRelease(s->curTransactionOwner,
3737 RESOURCE_RELEASE_LOCKS,
3739 ResourceOwnerRelease(s->curTransactionOwner,
3740 RESOURCE_RELEASE_AFTER_LOCKS,
3743 AtEOXact_GUC(true, true);
3744 AtEOSubXact_SPI(true, s->subTransactionId);
3745 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3746 s->parent->subTransactionId);
3747 AtEOSubXact_Namespace(true, s->subTransactionId,
3748 s->parent->subTransactionId);
3749 AtEOSubXact_Files(true, s->subTransactionId,
3750 s->parent->subTransactionId);
3751 AtEOSubXact_HashTables(true, s->nestingLevel);
3754 * We need to restore the upper transaction's read-only state, in case the
3755 * upper is read-write while the child is read-only; GUC will incorrectly
3756 * think it should leave the child state in place.
3758 XactReadOnly = s->prevXactReadOnly;
3760 CurrentResourceOwner = s->parent->curTransactionOwner;
3761 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3762 ResourceOwnerDelete(s->curTransactionOwner);
3763 s->curTransactionOwner = NULL;
3765 AtSubCommit_Memory();
3767 s->state = TRANS_DEFAULT;
3773 * AbortSubTransaction
3776 AbortSubTransaction(void)
3778 TransactionState s = CurrentTransactionState;
3780 /* Prevent cancel/die interrupt while cleaning up */
3783 /* Make sure we have a valid memory context and resource owner */
3784 AtSubAbort_Memory();
3785 AtSubAbort_ResourceOwner();
3788 * Release any LW locks we might be holding as quickly as possible.
3789 * (Regular locks, however, must be held till we finish aborting.)
3790 * Releasing LW locks is critical since we might try to grab them again
3791 * while cleaning up!
3793 * FIXME This may be incorrect --- Are there some locks we should keep?
3794 * Buffer locks, for example? I don't think so but I'm not sure.
3804 * check the current transaction state
3806 ShowTransactionState("AbortSubTransaction");
3808 if (s->state != TRANS_INPROGRESS)
3809 elog(WARNING, "AbortSubTransaction while in %s state",
3810 TransStateAsString(s->state));
3812 s->state = TRANS_ABORT;
3815 * We can skip all this stuff if the subxact failed before creating a
3818 if (s->curTransactionOwner)
3820 AfterTriggerEndSubXact(false);
3821 AtSubAbort_Portals(s->subTransactionId,
3822 s->parent->subTransactionId,
3823 s->parent->curTransactionOwner);
3824 AtEOSubXact_LargeObject(false, s->subTransactionId,
3825 s->parent->subTransactionId);
3826 AtSubAbort_Notify();
3827 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3828 s->parent->subTransactionId);
3830 /* Advertise the fact that we aborted in pg_clog. */
3831 if (TransactionIdIsValid(s->transactionId))
3833 RecordSubTransactionAbort();
3834 AtSubAbort_childXids();
3837 /* Post-abort cleanup */
3838 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3839 s->parent->subTransactionId);
3841 ResourceOwnerRelease(s->curTransactionOwner,
3842 RESOURCE_RELEASE_BEFORE_LOCKS,
3844 AtEOSubXact_RelationCache(false, s->subTransactionId,
3845 s->parent->subTransactionId);
3846 AtEOSubXact_Inval(false);
3848 ResourceOwnerRelease(s->curTransactionOwner,
3849 RESOURCE_RELEASE_LOCKS,
3851 ResourceOwnerRelease(s->curTransactionOwner,
3852 RESOURCE_RELEASE_AFTER_LOCKS,
3855 AtEOXact_GUC(false, true);
3856 AtEOSubXact_SPI(false, s->subTransactionId);
3857 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3858 s->parent->subTransactionId);
3859 AtEOSubXact_Namespace(false, s->subTransactionId,
3860 s->parent->subTransactionId);
3861 AtEOSubXact_Files(false, s->subTransactionId,
3862 s->parent->subTransactionId);
3863 AtEOSubXact_HashTables(false, s->nestingLevel);
3867 * Reset user id which might have been changed transiently. Here we want
3868 * to restore to the userid that was current at subxact entry. (As in
3869 * AbortTransaction, we need not worry about the session userid.)
3871 * Must do this after AtEOXact_GUC to handle the case where we entered the
3872 * subxact inside a SECURITY DEFINER function (hence current and session
3873 * userids were different) and then session auth was changed inside the
3874 * subxact. GUC will reset both current and session userids to the
3875 * entry-time session userid. This is right in every other scenario so it
3876 * seems simplest to let GUC do that and fix it here.
3878 SetUserId(s->currentUser);
3881 * Restore the upper transaction's read-only state, too. This should be
3882 * redundant with GUC's cleanup but we may as well do it for consistency
3883 * with the commit case.
3885 XactReadOnly = s->prevXactReadOnly;
3887 RESUME_INTERRUPTS();
3891 * CleanupSubTransaction
3893 * The caller has to make sure to always reassign CurrentTransactionState
3894 * if it has a local pointer to it after calling this function.
3897 CleanupSubTransaction(void)
3899 TransactionState s = CurrentTransactionState;
3901 ShowTransactionState("CleanupSubTransaction");
3903 if (s->state != TRANS_ABORT)
3904 elog(WARNING, "CleanupSubTransaction while in %s state",
3905 TransStateAsString(s->state));
3907 AtSubCleanup_Portals(s->subTransactionId);
3909 CurrentResourceOwner = s->parent->curTransactionOwner;
3910 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3911 if (s->curTransactionOwner)
3912 ResourceOwnerDelete(s->curTransactionOwner);
3913 s->curTransactionOwner = NULL;
3915 AtSubCleanup_Memory();
3917 s->state = TRANS_DEFAULT;
3924 * Create transaction state stack entry for a subtransaction
3926 * The caller has to make sure to always reassign CurrentTransactionState
3927 * if it has a local pointer to it after calling this function.
3930 PushTransaction(void)
3932 TransactionState p = CurrentTransactionState;
3937 * At present, GetUserId cannot fail, but let's not assume that. Get the
3938 * ID before entering the critical code sequence.
3940 currentUser = GetUserId();
3943 * We keep subtransaction state nodes in TopTransactionContext.
3945 s = (TransactionState)
3946 MemoryContextAllocZero(TopTransactionContext,
3947 sizeof(TransactionStateData));
3950 * Assign a subtransaction ID, watching out for counter wraparound.
3952 currentSubTransactionId += 1;
3953 if (currentSubTransactionId == InvalidSubTransactionId)
3955 currentSubTransactionId -= 1;
3958 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3959 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3963 * We can now stack a minimally valid subtransaction without fear of
3966 s->transactionId = InvalidTransactionId; /* until assigned */
3967 s->subTransactionId = currentSubTransactionId;
3969 s->nestingLevel = p->nestingLevel + 1;
3970 s->savepointLevel = p->savepointLevel;
3971 s->state = TRANS_DEFAULT;
3972 s->blockState = TBLOCK_SUBBEGIN;
3973 s->currentUser = currentUser;
3974 s->prevXactReadOnly = XactReadOnly;
3976 CurrentTransactionState = s;
3979 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3980 * with the subtransaction from here on out; in particular they should not
3981 * assume that it necessarily has a transaction context, resource owner,
3988 * Pop back to parent transaction state
3990 * The caller has to make sure to always reassign CurrentTransactionState
3991 * if it has a local pointer to it after calling this function.
3994 PopTransaction(void)
3996 TransactionState s = CurrentTransactionState;
3998 if (s->state != TRANS_DEFAULT)
3999 elog(WARNING, "PopTransaction while in %s state",
4000 TransStateAsString(s->state));
4002 if (s->parent == NULL)
4003 elog(FATAL, "PopTransaction with no parent");
4005 CurrentTransactionState = s->parent;
4007 /* Let's just make sure CurTransactionContext is good */
4008 CurTransactionContext = s->parent->curTransactionContext;
4009 MemoryContextSwitchTo(CurTransactionContext);
4011 /* Ditto for ResourceOwner links */
4012 CurTransactionResourceOwner = s->parent->curTransactionOwner;
4013 CurrentResourceOwner = s->parent->curTransactionOwner;
4015 /* Free the old child structure */
4022 * ShowTransactionState
4026 ShowTransactionState(const char *str)
4028 /* skip work if message will definitely not be printed */
4029 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
4031 elog(DEBUG3, "%s", str);
4032 ShowTransactionStateRec(CurrentTransactionState);
4037 * ShowTransactionStateRec
4038 * Recursive subroutine for ShowTransactionState
4041 ShowTransactionStateRec(TransactionState s)
4044 ShowTransactionStateRec(s->parent);
4046 /* use ereport to suppress computation if msg will not be printed */
4048 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
4049 PointerIsValid(s->name) ? s->name : "unnamed",
4050 BlockStateAsString(s->blockState),
4051 TransStateAsString(s->state),
4052 (unsigned int) s->transactionId,
4053 (unsigned int) s->subTransactionId,
4054 (unsigned int) currentCommandId,
4056 nodeToString(s->childXids))));
4060 * BlockStateAsString
4064 BlockStateAsString(TBlockState blockState)
4068 case TBLOCK_DEFAULT:
4070 case TBLOCK_STARTED:
4074 case TBLOCK_INPROGRESS:
4075 return "INPROGRESS";
4080 case TBLOCK_ABORT_END:
4082 case TBLOCK_ABORT_PENDING:
4083 return "ABORT PEND";
4084 case TBLOCK_PREPARE:
4086 case TBLOCK_SUBBEGIN:
4088 case TBLOCK_SUBINPROGRESS:
4089 return "SUB INPROGRS";
4092 case TBLOCK_SUBABORT:
4094 case TBLOCK_SUBABORT_END:
4095 return "SUB ABORT END";
4096 case TBLOCK_SUBABORT_PENDING:
4097 return "SUB ABRT PEND";
4098 case TBLOCK_SUBRESTART:
4099 return "SUB RESTART";
4100 case TBLOCK_SUBABORT_RESTART:
4101 return "SUB AB RESTRT";
4103 return "UNRECOGNIZED";
4107 * TransStateAsString
4111 TransStateAsString(TransState state)
4119 case TRANS_INPROGRESS:
4128 return "UNRECOGNIZED";
4132 * xactGetCommittedChildren
4134 * Gets the list of committed children of the current transaction. The return
4135 * value is the number of child transactions. *children is set to point to a
4136 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4140 xactGetCommittedChildren(TransactionId **ptr)
4142 TransactionState s = CurrentTransactionState;
4144 TransactionId *children;
4147 nchildren = list_length(s->childXids);
4154 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4157 foreach(p, s->childXids)
4159 TransactionId child = lfirst_xid(p);
4161 *children++ = child;
4168 * XLOG support routines
4172 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4174 TransactionId *sub_xids;
4175 TransactionId max_xid;
4178 TransactionIdCommit(xid);
4180 /* Mark committed subtransactions as committed */
4181 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4182 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4184 /* Make sure nextXid is beyond any XID mentioned in the record */
4186 for (i = 0; i < xlrec->nsubxacts; i++)
4188 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4189 max_xid = sub_xids[i];
4191 if (TransactionIdFollowsOrEquals(max_xid,
4192 ShmemVariableCache->nextXid))
4194 ShmemVariableCache->nextXid = max_xid;
4195 TransactionIdAdvance(ShmemVariableCache->nextXid);
4198 /* Make sure files supposed to be dropped are dropped */
4199 for (i = 0; i < xlrec->nrels; i++)
4201 XLogDropRelation(xlrec->xnodes[i]);
4202 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4207 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4209 TransactionId *sub_xids;
4210 TransactionId max_xid;
4213 TransactionIdAbort(xid);
4215 /* Mark subtransactions as aborted */
4216 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4217 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4219 /* Make sure nextXid is beyond any XID mentioned in the record */
4221 for (i = 0; i < xlrec->nsubxacts; i++)
4223 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4224 max_xid = sub_xids[i];
4226 if (TransactionIdFollowsOrEquals(max_xid,
4227 ShmemVariableCache->nextXid))
4229 ShmemVariableCache->nextXid = max_xid;
4230 TransactionIdAdvance(ShmemVariableCache->nextXid);
4233 /* Make sure files supposed to be dropped are dropped */
4234 for (i = 0; i < xlrec->nrels; i++)
4236 XLogDropRelation(xlrec->xnodes[i]);
4237 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4242 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4244 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4246 if (info == XLOG_XACT_COMMIT)
4248 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4250 xact_redo_commit(xlrec, record->xl_xid);
4252 else if (info == XLOG_XACT_ABORT)
4254 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4256 xact_redo_abort(xlrec, record->xl_xid);
4258 else if (info == XLOG_XACT_PREPARE)
4260 /* the record contents are exactly the 2PC file */
4261 RecreateTwoPhaseFile(record->xl_xid,
4262 XLogRecGetData(record), record->xl_len);
4264 else if (info == XLOG_XACT_COMMIT_PREPARED)
4266 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4268 xact_redo_commit(&xlrec->crec, xlrec->xid);
4269 RemoveTwoPhaseFile(xlrec->xid, false);
4271 else if (info == XLOG_XACT_ABORT_PREPARED)
4273 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4275 xact_redo_abort(&xlrec->arec, xlrec->xid);
4276 RemoveTwoPhaseFile(xlrec->xid, false);
4279 elog(PANIC, "xact_redo: unknown op code %u", info);
4283 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4287 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4288 if (xlrec->nrels > 0)
4290 appendStringInfo(buf, "; rels:");
4291 for (i = 0; i < xlrec->nrels; i++)
4293 RelFileNode rnode = xlrec->xnodes[i];
4295 appendStringInfo(buf, " %u/%u/%u",
4296 rnode.spcNode, rnode.dbNode, rnode.relNode);
4299 if (xlrec->nsubxacts > 0)
4301 TransactionId *xacts = (TransactionId *)
4302 &xlrec->xnodes[xlrec->nrels];
4304 appendStringInfo(buf, "; subxacts:");
4305 for (i = 0; i < xlrec->nsubxacts; i++)
4306 appendStringInfo(buf, " %u", xacts[i]);
4311 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4315 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4316 if (xlrec->nrels > 0)
4318 appendStringInfo(buf, "; rels:");
4319 for (i = 0; i < xlrec->nrels; i++)
4321 RelFileNode rnode = xlrec->xnodes[i];
4323 appendStringInfo(buf, " %u/%u/%u",
4324 rnode.spcNode, rnode.dbNode, rnode.relNode);
4327 if (xlrec->nsubxacts > 0)
4329 TransactionId *xacts = (TransactionId *)
4330 &xlrec->xnodes[xlrec->nrels];
4332 appendStringInfo(buf, "; subxacts:");
4333 for (i = 0; i < xlrec->nsubxacts; i++)
4334 appendStringInfo(buf, " %u", xacts[i]);
4339 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4341 uint8 info = xl_info & ~XLR_INFO_MASK;
4343 if (info == XLOG_XACT_COMMIT)
4345 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4347 appendStringInfo(buf, "commit: ");
4348 xact_desc_commit(buf, xlrec);
4350 else if (info == XLOG_XACT_ABORT)
4352 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4354 appendStringInfo(buf, "abort: ");
4355 xact_desc_abort(buf, xlrec);
4357 else if (info == XLOG_XACT_PREPARE)
4359 appendStringInfo(buf, "prepare");
4361 else if (info == XLOG_XACT_COMMIT_PREPARED)
4363 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4365 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4366 xact_desc_commit(buf, &xlrec->crec);
4368 else if (info == XLOG_XACT_ABORT_PREPARED)
4370 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4372 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4373 xact_desc_abort(buf, &xlrec->arec);
4376 appendStringInfo(buf, "UNKNOWN");