1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.207 2005/06/19 20:00:38 tgl Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/twophase.h"
26 #include "access/xact.h"
27 #include "catalog/heap.h"
28 #include "catalog/index.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
36 #include "storage/fd.h"
37 #include "storage/proc.h"
38 #include "storage/procarray.h"
39 #include "storage/smgr.h"
40 #include "utils/flatfiles.h"
41 #include "utils/guc.h"
42 #include "utils/inval.h"
43 #include "utils/memutils.h"
44 #include "utils/portal.h"
45 #include "utils/relcache.h"
46 #include "utils/resowner.h"
51 * User-tweakable parameters
53 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
56 bool DefaultXactReadOnly = false;
59 int CommitDelay = 0; /* precommit delay in microseconds */
60 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
64 * transaction states - transaction state from server perspective
66 typedef enum TransState
77 * transaction block states - transaction state of client queries
79 * Note: the subtransaction states are used only for non-topmost
80 * transactions; the others appear only in the topmost transaction.
82 typedef enum TBlockState
84 /* not-in-transaction-block states */
85 TBLOCK_DEFAULT, /* idle */
86 TBLOCK_STARTED, /* running single-query transaction */
88 /* transaction block states */
89 TBLOCK_BEGIN, /* starting transaction block */
90 TBLOCK_INPROGRESS, /* live transaction */
91 TBLOCK_END, /* COMMIT received */
92 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
93 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
94 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
95 TBLOCK_PREPARE, /* live xact, PREPARE received */
97 /* subtransaction states */
98 TBLOCK_SUBBEGIN, /* starting a subtransaction */
99 TBLOCK_SUBINPROGRESS, /* live subtransaction */
100 TBLOCK_SUBEND, /* RELEASE received */
101 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
102 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
103 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
104 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
105 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
109 * transaction state structure
111 typedef struct TransactionStateData
113 TransactionId transactionId; /* my XID, or Invalid if none */
114 SubTransactionId subTransactionId; /* my subxact ID */
115 char *name; /* savepoint name, if any */
116 int savepointLevel; /* savepoint level */
117 TransState state; /* low-level state */
118 TBlockState blockState; /* high-level state */
119 int nestingLevel; /* nest depth */
120 MemoryContext curTransactionContext; /* my xact-lifetime
122 ResourceOwner curTransactionOwner; /* my query resources */
123 List *childXids; /* subcommitted child XIDs */
124 AclId currentUser; /* subxact start current_user */
125 bool prevXactReadOnly; /* entry-time xact r/o state */
126 struct TransactionStateData *parent; /* back link to parent */
127 } TransactionStateData;
129 typedef TransactionStateData *TransactionState;
132 * childXids is currently implemented as an integer List, relying on the
133 * assumption that TransactionIds are no wider than int. We use these
134 * macros to provide some isolation in case that changes in the future.
136 #define lfirst_xid(lc) ((TransactionId) lfirst_int(lc))
137 #define lappend_xid(list, datum) lappend_int(list, (int) (datum))
140 * CurrentTransactionState always points to the current transaction state
141 * block. It will point to TopTransactionStateData when not in a
142 * transaction at all, or when in a top-level transaction.
144 static TransactionStateData TopTransactionStateData = {
145 0, /* transaction id */
146 0, /* subtransaction id */
147 NULL, /* savepoint name */
148 0, /* savepoint level */
149 TRANS_DEFAULT, /* transaction state */
150 TBLOCK_DEFAULT, /* transaction block state from the client
152 0, /* nesting level */
153 NULL, /* cur transaction context */
154 NULL, /* cur transaction resource owner */
155 NIL, /* subcommitted child Xids */
156 0, /* entry-time current userid */
157 false, /* entry-time xact r/o state */
158 NULL /* link to parent state block */
161 static TransactionState CurrentTransactionState = &TopTransactionStateData;
164 * The subtransaction ID and command ID assignment counters are global
165 * to a whole transaction, so we do not keep them in the state stack.
167 static SubTransactionId currentSubTransactionId;
168 static CommandId currentCommandId;
171 * These vars hold the value of now(), ie, the transaction start time.
172 * This does not change as we enter and exit subtransactions, so we don't
173 * keep it inside the TransactionState stack.
175 static AbsoluteTime xactStartTime; /* integer part */
176 static int xactStartTimeUsec; /* microsecond part */
179 * GID to be used for preparing the current transaction. This is also
180 * global to a whole transaction, so we don't keep it in the state stack.
182 static char *prepareGID;
186 * List of add-on start- and end-of-xact callbacks
188 typedef struct XactCallbackItem
190 struct XactCallbackItem *next;
191 XactCallback callback;
195 static XactCallbackItem *Xact_callbacks = NULL;
198 * List of add-on start- and end-of-subxact callbacks
200 typedef struct SubXactCallbackItem
202 struct SubXactCallbackItem *next;
203 SubXactCallback callback;
205 } SubXactCallbackItem;
207 static SubXactCallbackItem *SubXact_callbacks = NULL;
210 /* local function prototypes */
211 static void AssignSubTransactionId(TransactionState s);
212 static void AbortTransaction(void);
213 static void AtAbort_Memory(void);
214 static void AtCleanup_Memory(void);
215 static void AtAbort_ResourceOwner(void);
216 static void AtCommit_LocalCache(void);
217 static void AtCommit_Memory(void);
218 static void AtStart_Cache(void);
219 static void AtStart_Memory(void);
220 static void AtStart_ResourceOwner(void);
221 static void CallXactCallbacks(XactEvent event);
222 static void CallSubXactCallbacks(SubXactEvent event,
223 SubTransactionId mySubid,
224 SubTransactionId parentSubid);
225 static void CleanupTransaction(void);
226 static void CommitTransaction(void);
227 static void RecordTransactionAbort(void);
228 static void StartTransaction(void);
230 static void RecordSubTransactionCommit(void);
231 static void StartSubTransaction(void);
232 static void CommitSubTransaction(void);
233 static void AbortSubTransaction(void);
234 static void CleanupSubTransaction(void);
235 static void PushTransaction(void);
236 static void PopTransaction(void);
238 static void AtSubAbort_Memory(void);
239 static void AtSubCleanup_Memory(void);
240 static void AtSubAbort_ResourceOwner(void);
241 static void AtSubCommit_Memory(void);
242 static void AtSubStart_Memory(void);
243 static void AtSubStart_ResourceOwner(void);
245 static void ShowTransactionState(const char *str);
246 static void ShowTransactionStateRec(TransactionState state);
247 static const char *BlockStateAsString(TBlockState blockState);
248 static const char *TransStateAsString(TransState state);
251 /* ----------------------------------------------------------------
252 * transaction state accessors
253 * ----------------------------------------------------------------
259 * This returns true if we are currently running a query
260 * within an executing transaction.
263 IsTransactionState(void)
265 TransactionState s = CurrentTransactionState;
273 case TRANS_INPROGRESS:
284 * Shouldn't get here, but lint is not happy without this...
290 * IsAbortedTransactionBlockState
292 * This returns true if we are currently running a query
293 * within an aborted transaction block.
296 IsAbortedTransactionBlockState(void)
298 TransactionState s = CurrentTransactionState;
300 if (s->blockState == TBLOCK_ABORT ||
301 s->blockState == TBLOCK_SUBABORT)
309 * GetTopTransactionId
311 * Get the ID of the main transaction, even if we are currently inside
315 GetTopTransactionId(void)
317 return TopTransactionStateData.transactionId;
322 * GetCurrentTransactionId
324 * We do not assign XIDs to subtransactions until/unless this is called.
325 * When we do assign an XID to a subtransaction, recursively make sure
326 * its parent has one as well (this maintains the invariant that a child
327 * transaction has an XID following its parent's).
330 GetCurrentTransactionId(void)
332 TransactionState s = CurrentTransactionState;
334 if (!TransactionIdIsValid(s->transactionId))
335 AssignSubTransactionId(s);
337 return s->transactionId;
341 AssignSubTransactionId(TransactionState s)
343 ResourceOwner currentOwner;
345 Assert(s->parent != NULL);
346 Assert(s->state == TRANS_INPROGRESS);
347 if (!TransactionIdIsValid(s->parent->transactionId))
348 AssignSubTransactionId(s->parent);
351 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
353 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere
354 * in shared storage other than PG_PROC; because if there's no room for
355 * it in PG_PROC, the subtrans entry is needed to ensure that other
356 * backends see the Xid as "running". See GetNewTransactionId.
358 s->transactionId = GetNewTransactionId(true);
360 SubTransSetParent(s->transactionId, s->parent->transactionId);
363 * Acquire lock on the transaction XID. (We assume this cannot block.)
364 * We have to be sure that the lock is assigned to the transaction's
367 currentOwner = CurrentResourceOwner;
370 CurrentResourceOwner = s->curTransactionOwner;
372 XactLockTableInsert(s->transactionId);
376 /* Ensure CurrentResourceOwner is restored on error */
377 CurrentResourceOwner = currentOwner;
381 CurrentResourceOwner = currentOwner;
386 * GetCurrentTransactionIdIfAny
388 * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
389 * if we are currently not in a transaction, or in a transaction or
390 * subtransaction that has not yet assigned itself an XID.
393 GetCurrentTransactionIdIfAny(void)
395 TransactionState s = CurrentTransactionState;
397 return s->transactionId;
402 * GetCurrentSubTransactionId
405 GetCurrentSubTransactionId(void)
407 TransactionState s = CurrentTransactionState;
409 return s->subTransactionId;
414 * GetCurrentCommandId
417 GetCurrentCommandId(void)
419 /* this is global to a transaction, not subtransaction-local */
420 return currentCommandId;
425 * GetCurrentTransactionStartTime
428 GetCurrentTransactionStartTime(void)
430 return xactStartTime;
435 * GetCurrentTransactionStartTimeUsec
438 GetCurrentTransactionStartTimeUsec(int *msec)
440 *msec = xactStartTimeUsec;
441 return xactStartTime;
446 * GetCurrentTransactionNestLevel
448 * Note: this will return zero when not inside any transaction, one when
449 * inside a top-level transaction, etc.
452 GetCurrentTransactionNestLevel(void)
454 TransactionState s = CurrentTransactionState;
456 return s->nestingLevel;
461 * TransactionIdIsCurrentTransactionId
464 TransactionIdIsCurrentTransactionId(TransactionId xid)
469 * We always say that BootstrapTransactionId is "not my transaction ID"
470 * even when it is (ie, during bootstrap). Along with the fact that
471 * transam.c always treats BootstrapTransactionId as already committed,
472 * this causes the tqual.c routines to see all tuples as committed,
473 * which is what we need during bootstrap. (Bootstrap mode only inserts
474 * tuples, it never updates or deletes them, so all tuples can be presumed
477 if (xid == BootstrapTransactionId)
481 * We will return true for the Xid of the current subtransaction, any
482 * of its subcommitted children, any of its parents, or any of their
483 * previously subcommitted children. However, a transaction being
484 * aborted is no longer "current", even though it may still have an
485 * entry on the state stack.
487 for (s = CurrentTransactionState; s != NULL; s = s->parent)
491 if (s->state == TRANS_ABORT)
493 if (!TransactionIdIsValid(s->transactionId))
494 continue; /* it can't have any child XIDs either */
495 if (TransactionIdEquals(xid, s->transactionId))
497 foreach(cell, s->childXids)
499 if (TransactionIdEquals(xid, lfirst_xid(cell)))
509 * CommandCounterIncrement
512 CommandCounterIncrement(void)
514 currentCommandId += 1;
515 if (currentCommandId == FirstCommandId) /* check for overflow */
517 currentCommandId -= 1;
519 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
520 errmsg("cannot have more than 2^32-1 commands in a transaction")));
523 /* Propagate new command ID into static snapshots, if set */
524 if (SerializableSnapshot)
525 SerializableSnapshot->curcid = currentCommandId;
527 LatestSnapshot->curcid = currentCommandId;
530 * make cache changes visible to me.
532 AtCommit_LocalCache();
537 /* ----------------------------------------------------------------
538 * StartTransaction stuff
539 * ----------------------------------------------------------------
548 AcceptInvalidationMessages();
557 TransactionState s = CurrentTransactionState;
560 * We shouldn't have a transaction context already.
562 Assert(TopTransactionContext == NULL);
565 * Create a toplevel context for the transaction.
567 TopTransactionContext =
568 AllocSetContextCreate(TopMemoryContext,
569 "TopTransactionContext",
570 ALLOCSET_DEFAULT_MINSIZE,
571 ALLOCSET_DEFAULT_INITSIZE,
572 ALLOCSET_DEFAULT_MAXSIZE);
575 * In a top-level transaction, CurTransactionContext is the same as
576 * TopTransactionContext.
578 CurTransactionContext = TopTransactionContext;
579 s->curTransactionContext = CurTransactionContext;
581 /* Make the CurTransactionContext active. */
582 MemoryContextSwitchTo(CurTransactionContext);
586 * AtStart_ResourceOwner
589 AtStart_ResourceOwner(void)
591 TransactionState s = CurrentTransactionState;
594 * We shouldn't have a transaction resource owner already.
596 Assert(TopTransactionResourceOwner == NULL);
599 * Create a toplevel resource owner for the transaction.
601 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
603 TopTransactionResourceOwner = s->curTransactionOwner;
604 CurTransactionResourceOwner = s->curTransactionOwner;
605 CurrentResourceOwner = s->curTransactionOwner;
608 /* ----------------------------------------------------------------
609 * StartSubTransaction stuff
610 * ----------------------------------------------------------------
617 AtSubStart_Memory(void)
619 TransactionState s = CurrentTransactionState;
621 Assert(CurTransactionContext != NULL);
624 * Create a CurTransactionContext, which will be used to hold data
625 * that survives subtransaction commit but disappears on
626 * subtransaction abort. We make it a child of the immediate parent's
627 * CurTransactionContext.
629 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
630 "CurTransactionContext",
631 ALLOCSET_DEFAULT_MINSIZE,
632 ALLOCSET_DEFAULT_INITSIZE,
633 ALLOCSET_DEFAULT_MAXSIZE);
634 s->curTransactionContext = CurTransactionContext;
636 /* Make the CurTransactionContext active. */
637 MemoryContextSwitchTo(CurTransactionContext);
641 * AtSubStart_ResourceOwner
644 AtSubStart_ResourceOwner(void)
646 TransactionState s = CurrentTransactionState;
648 Assert(s->parent != NULL);
651 * Create a resource owner for the subtransaction. We make it a child
652 * of the immediate parent's resource owner.
654 s->curTransactionOwner =
655 ResourceOwnerCreate(s->parent->curTransactionOwner,
658 CurTransactionResourceOwner = s->curTransactionOwner;
659 CurrentResourceOwner = s->curTransactionOwner;
662 /* ----------------------------------------------------------------
663 * CommitTransaction stuff
664 * ----------------------------------------------------------------
668 * RecordTransactionCommit
671 RecordTransactionCommit(void)
676 TransactionId *children;
678 /* Get data needed for commit record */
679 nrels = smgrGetPendingDeletes(true, &rels);
680 nchildren = xactGetCommittedChildren(&children);
683 * If we made neither any XLOG entries nor any temp-rel updates, and
684 * have no files to be deleted, we can omit recording the transaction
685 * commit at all. (This test includes the effects of subtransactions,
686 * so the presence of committed subxacts need not alone force a
689 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
691 TransactionId xid = GetCurrentTransactionId();
695 /* Tell bufmgr and smgr to prepare for commit */
698 START_CRIT_SECTION();
701 * If our transaction made any transaction-controlled XLOG
702 * entries, we need to lock out checkpoint start between writing
703 * our XLOG record and updating pg_clog. Otherwise it is possible
704 * for the checkpoint to set REDO after the XLOG record but fail
705 * to flush the pg_clog update to disk, leading to loss of the
706 * transaction commit if we crash a little later. Slightly klugy
707 * fix for problem discovered 2004-08-10.
709 * (If it made no transaction-controlled XLOG entries, its XID
710 * appears nowhere in permanent storage, so no one else will ever
711 * care if it committed; so it doesn't matter if we lose the
714 * Note we only need a shared lock.
716 madeTCentries = (MyLastRecPtr.xrecoff != 0);
718 LWLockAcquire(CheckpointStartLock, LW_SHARED);
721 * We only need to log the commit in XLOG if the transaction made
722 * any transaction-controlled XLOG entries or will delete files.
724 if (madeTCentries || nrels > 0)
726 XLogRecData rdata[3];
728 xl_xact_commit xlrec;
730 xlrec.xtime = time(NULL);
732 xlrec.nsubxacts = nchildren;
733 rdata[0].data = (char *) (&xlrec);
734 rdata[0].len = MinSizeOfXactCommit;
735 rdata[0].buffer = InvalidBuffer;
736 /* dump rels to delete */
739 rdata[0].next = &(rdata[1]);
740 rdata[1].data = (char *) rels;
741 rdata[1].len = nrels * sizeof(RelFileNode);
742 rdata[1].buffer = InvalidBuffer;
745 /* dump committed child Xids */
748 rdata[lastrdata].next = &(rdata[2]);
749 rdata[2].data = (char *) children;
750 rdata[2].len = nchildren * sizeof(TransactionId);
751 rdata[2].buffer = InvalidBuffer;
754 rdata[lastrdata].next = NULL;
756 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
760 /* Just flush through last record written by me */
761 recptr = ProcLastRecEnd;
765 * We must flush our XLOG entries to disk if we made any XLOG
766 * entries, whether in or out of transaction control. For
767 * example, if we reported a nextval() result to the client, this
768 * ensures that any XLOG record generated by nextval will hit the
769 * disk before we report the transaction committed.
771 * Note: if we generated a commit record above, MyXactMadeXLogEntry
772 * will certainly be set now.
774 if (MyXactMadeXLogEntry)
777 * Sleep before flush! So we can flush more than one commit
778 * records per single fsync. (The idea is some other backend
779 * may do the XLogFlush while we're sleeping. This needs work
780 * still, because on most Unixen, the minimum select() delay
781 * is 10msec or more, which is way too long.)
783 * We do not sleep if enableFsync is not turned on, nor if there
784 * are fewer than CommitSiblings other backends with active
787 if (CommitDelay > 0 && enableFsync &&
788 CountActiveBackends() >= CommitSiblings)
789 pg_usleep(CommitDelay);
795 * We must mark the transaction committed in clog if its XID
796 * appears either in permanent rels or in local temporary rels. We
797 * test this by seeing if we made transaction-controlled entries
798 * *OR* local-rel tuple updates. Note that if we made only the
799 * latter, we have not emitted an XLOG record for our commit, and
800 * so in the event of a crash the clog update might be lost. This
801 * is okay because no one else will ever care whether we
804 if (madeTCentries || MyXactMadeTempRelUpdate)
806 TransactionIdCommit(xid);
807 /* to avoid race conditions, the parent must commit first */
808 TransactionIdCommitTree(nchildren, children);
811 /* Unlock checkpoint lock if we acquired it */
813 LWLockRelease(CheckpointStartLock);
818 /* Break the chain of back-links in the XLOG records I output */
819 MyLastRecPtr.xrecoff = 0;
820 MyXactMadeXLogEntry = false;
821 MyXactMadeTempRelUpdate = false;
823 /* And clean up local data */
832 * AtCommit_LocalCache
835 AtCommit_LocalCache(void)
838 * Make catalog changes visible to me for the next command.
840 CommandEndInvalidationMessages();
847 AtCommit_Memory(void)
850 * Now that we're "out" of a transaction, have the system allocate
851 * things in the top memory context instead of per-transaction
854 MemoryContextSwitchTo(TopMemoryContext);
857 * Release all transaction-local memory.
859 Assert(TopTransactionContext != NULL);
860 MemoryContextDelete(TopTransactionContext);
861 TopTransactionContext = NULL;
862 CurTransactionContext = NULL;
863 CurrentTransactionState->curTransactionContext = NULL;
866 /* ----------------------------------------------------------------
867 * CommitSubTransaction stuff
868 * ----------------------------------------------------------------
875 AtSubCommit_Memory(void)
877 TransactionState s = CurrentTransactionState;
879 Assert(s->parent != NULL);
881 /* Return to parent transaction level's memory context. */
882 CurTransactionContext = s->parent->curTransactionContext;
883 MemoryContextSwitchTo(CurTransactionContext);
886 * Ordinarily we cannot throw away the child's CurTransactionContext,
887 * since the data it contains will be needed at upper commit. However,
888 * if there isn't actually anything in it, we can throw it away. This
889 * avoids a small memory leak in the common case of "trivial" subxacts.
891 if (MemoryContextIsEmpty(s->curTransactionContext))
893 MemoryContextDelete(s->curTransactionContext);
894 s->curTransactionContext = NULL;
899 * AtSubCommit_childXids
901 * Pass my own XID and my child XIDs up to my parent as committed children.
904 AtSubCommit_childXids(void)
906 TransactionState s = CurrentTransactionState;
907 MemoryContext old_cxt;
909 Assert(s->parent != NULL);
912 * We keep the child-XID lists in TopTransactionContext; this avoids
913 * setting up child-transaction contexts for what might be just a few
914 * bytes of grandchild XIDs.
916 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
918 s->parent->childXids = lappend_xid(s->parent->childXids,
921 if (s->childXids != NIL)
923 s->parent->childXids = list_concat(s->parent->childXids,
926 * list_concat doesn't free the list header for the second list;
927 * do so here to avoid memory leakage (kluge)
933 MemoryContextSwitchTo(old_cxt);
937 * RecordSubTransactionCommit
940 RecordSubTransactionCommit(void)
943 * We do not log the subcommit in XLOG; it doesn't matter until the
944 * top-level transaction commits.
946 * We must mark the subtransaction subcommitted in clog if its XID
947 * appears either in permanent rels or in local temporary rels. We
948 * test this by seeing if we made transaction-controlled entries *OR*
949 * local-rel tuple updates. (The test here actually covers the entire
950 * transaction tree so far, so it may mark subtransactions that don't
951 * really need it, but it's probably not worth being tenser. Note that
952 * if a prior subtransaction dirtied these variables, then
953 * RecordTransactionCommit will have to do the full pushup anyway...)
955 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
957 TransactionId xid = GetCurrentTransactionId();
959 /* XXX does this really need to be a critical section? */
960 START_CRIT_SECTION();
962 /* Record subtransaction subcommit */
963 TransactionIdSubCommit(xid);
969 /* ----------------------------------------------------------------
970 * AbortTransaction stuff
971 * ----------------------------------------------------------------
975 * RecordTransactionAbort
978 RecordTransactionAbort(void)
983 TransactionId *children;
985 /* Get data needed for abort record */
986 nrels = smgrGetPendingDeletes(false, &rels);
987 nchildren = xactGetCommittedChildren(&children);
990 * If we made neither any transaction-controlled XLOG entries nor any
991 * temp-rel updates, and are not going to delete any files, we can
992 * omit recording the transaction abort at all. No one will ever care
993 * that it aborted. (These tests cover our whole transaction tree.)
995 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
997 TransactionId xid = GetCurrentTransactionId();
1000 * Catch the scenario where we aborted partway through
1001 * RecordTransactionCommit ...
1003 if (TransactionIdDidCommit(xid))
1004 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1006 START_CRIT_SECTION();
1009 * We only need to log the abort in XLOG if the transaction made
1010 * any transaction-controlled XLOG entries or will delete files.
1011 * (If it made no transaction-controlled XLOG entries, its XID
1012 * appears nowhere in permanent storage, so no one else will ever
1013 * care if it committed.)
1015 * We do not flush XLOG to disk unless deleting files, since the
1016 * default assumption after a crash would be that we aborted,
1017 * anyway. For the same reason, we don't need to worry about
1018 * interlocking against checkpoint start.
1020 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1022 XLogRecData rdata[3];
1024 xl_xact_abort xlrec;
1027 xlrec.xtime = time(NULL);
1028 xlrec.nrels = nrels;
1029 xlrec.nsubxacts = nchildren;
1030 rdata[0].data = (char *) (&xlrec);
1031 rdata[0].len = MinSizeOfXactAbort;
1032 rdata[0].buffer = InvalidBuffer;
1033 /* dump rels to delete */
1036 rdata[0].next = &(rdata[1]);
1037 rdata[1].data = (char *) rels;
1038 rdata[1].len = nrels * sizeof(RelFileNode);
1039 rdata[1].buffer = InvalidBuffer;
1042 /* dump committed child Xids */
1045 rdata[lastrdata].next = &(rdata[2]);
1046 rdata[2].data = (char *) children;
1047 rdata[2].len = nchildren * sizeof(TransactionId);
1048 rdata[2].buffer = InvalidBuffer;
1051 rdata[lastrdata].next = NULL;
1053 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1055 /* Must flush if we are deleting files... */
1061 * Mark the transaction aborted in clog. This is not absolutely
1062 * necessary but we may as well do it while we are here.
1064 * The ordering here isn't critical but it seems best to mark the
1065 * parent first. This assures an atomic transition of all the
1066 * subtransactions to aborted state from the point of view of
1067 * concurrent TransactionIdDidAbort calls.
1069 TransactionIdAbort(xid);
1070 TransactionIdAbortTree(nchildren, children);
1075 /* Break the chain of back-links in the XLOG records I output */
1076 MyLastRecPtr.xrecoff = 0;
1077 MyXactMadeXLogEntry = false;
1078 MyXactMadeTempRelUpdate = false;
1080 /* And clean up local data */
1091 AtAbort_Memory(void)
1094 * Make sure we are in a valid context (not a child of
1095 * TopTransactionContext...). Note that it is possible for this code
1096 * to be called when we aren't in a transaction at all; go directly to
1097 * TopMemoryContext in that case.
1099 if (TopTransactionContext != NULL)
1101 MemoryContextSwitchTo(TopTransactionContext);
1104 * We do not want to destroy the transaction's global state yet,
1105 * so we can't free any memory here.
1109 MemoryContextSwitchTo(TopMemoryContext);
1116 AtSubAbort_Memory(void)
1118 Assert(TopTransactionContext != NULL);
1120 MemoryContextSwitchTo(TopTransactionContext);
1125 * AtAbort_ResourceOwner
1128 AtAbort_ResourceOwner(void)
1131 * Make sure we have a valid ResourceOwner, if possible (else it
1132 * will be NULL, which is OK)
1134 CurrentResourceOwner = TopTransactionResourceOwner;
1138 * AtSubAbort_ResourceOwner
1141 AtSubAbort_ResourceOwner(void)
1143 TransactionState s = CurrentTransactionState;
1145 /* Make sure we have a valid ResourceOwner */
1146 CurrentResourceOwner = s->curTransactionOwner;
1151 * AtSubAbort_childXids
1154 AtSubAbort_childXids(void)
1156 TransactionState s = CurrentTransactionState;
1159 * We keep the child-XID lists in TopTransactionContext (see
1160 * AtSubCommit_childXids). This means we'd better free the list
1161 * explicitly at abort to avoid leakage.
1163 list_free(s->childXids);
1168 * RecordSubTransactionAbort
1171 RecordSubTransactionAbort(void)
1175 TransactionId xid = GetCurrentTransactionId();
1177 TransactionId *children;
1179 /* Get data needed for abort record */
1180 nrels = smgrGetPendingDeletes(false, &rels);
1181 nchildren = xactGetCommittedChildren(&children);
1184 * If we made neither any transaction-controlled XLOG entries nor any
1185 * temp-rel updates, and are not going to delete any files, we can
1186 * omit recording the transaction abort at all. No one will ever care
1187 * that it aborted. (These tests cover our whole transaction tree,
1188 * and therefore may mark subxacts that don't really need it, but it's
1189 * probably not worth being tenser.)
1191 * In this case we needn't worry about marking subcommitted children as
1192 * aborted, because they didn't mark themselves as subcommitted in the
1193 * first place; see the optimization in RecordSubTransactionCommit.
1195 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1197 START_CRIT_SECTION();
1200 * We only need to log the abort in XLOG if the transaction made
1201 * any transaction-controlled XLOG entries or will delete files.
1203 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1205 XLogRecData rdata[3];
1207 xl_xact_abort xlrec;
1210 xlrec.xtime = time(NULL);
1211 xlrec.nrels = nrels;
1212 xlrec.nsubxacts = nchildren;
1213 rdata[0].data = (char *) (&xlrec);
1214 rdata[0].len = MinSizeOfXactAbort;
1215 rdata[0].buffer = InvalidBuffer;
1216 /* dump rels to delete */
1219 rdata[0].next = &(rdata[1]);
1220 rdata[1].data = (char *) rels;
1221 rdata[1].len = nrels * sizeof(RelFileNode);
1222 rdata[1].buffer = InvalidBuffer;
1225 /* dump committed child Xids */
1228 rdata[lastrdata].next = &(rdata[2]);
1229 rdata[2].data = (char *) children;
1230 rdata[2].len = nchildren * sizeof(TransactionId);
1231 rdata[2].buffer = InvalidBuffer;
1234 rdata[lastrdata].next = NULL;
1236 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1238 /* Must flush if we are deleting files... */
1244 * Mark the transaction aborted in clog. This is not absolutely
1245 * necessary but XactLockTableWait makes use of it to avoid waiting
1246 * for already-aborted subtransactions.
1248 TransactionIdAbort(xid);
1249 TransactionIdAbortTree(nchildren, children);
1255 * We can immediately remove failed XIDs from PGPROC's cache of
1256 * running child XIDs. It's easiest to do it here while we have the
1257 * child XID array at hand, even though in the main-transaction case
1258 * the equivalent work happens just after return from
1259 * RecordTransactionAbort.
1261 XidCacheRemoveRunningXids(xid, nchildren, children);
1263 /* And clean up local data */
1270 /* ----------------------------------------------------------------
1271 * CleanupTransaction stuff
1272 * ----------------------------------------------------------------
1279 AtCleanup_Memory(void)
1282 * Now that we're "out" of a transaction, have the system allocate
1283 * things in the top memory context instead of per-transaction
1286 MemoryContextSwitchTo(TopMemoryContext);
1288 Assert(CurrentTransactionState->parent == NULL);
1291 * Release all transaction-local memory.
1293 if (TopTransactionContext != NULL)
1294 MemoryContextDelete(TopTransactionContext);
1295 TopTransactionContext = NULL;
1296 CurTransactionContext = NULL;
1297 CurrentTransactionState->curTransactionContext = NULL;
1301 /* ----------------------------------------------------------------
1302 * CleanupSubTransaction stuff
1303 * ----------------------------------------------------------------
1307 * AtSubCleanup_Memory
1310 AtSubCleanup_Memory(void)
1312 TransactionState s = CurrentTransactionState;
1314 Assert(s->parent != NULL);
1316 /* Make sure we're not in an about-to-be-deleted context */
1317 MemoryContextSwitchTo(s->parent->curTransactionContext);
1318 CurTransactionContext = s->parent->curTransactionContext;
1321 * Delete the subxact local memory contexts. Its CurTransactionContext
1322 * can go too (note this also kills CurTransactionContexts from any
1323 * children of the subxact).
1325 if (s->curTransactionContext)
1326 MemoryContextDelete(s->curTransactionContext);
1327 s->curTransactionContext = NULL;
1330 /* ----------------------------------------------------------------
1331 * interface routines
1332 * ----------------------------------------------------------------
1339 StartTransaction(void)
1344 * Let's just make sure the state stack is empty
1346 s = &TopTransactionStateData;
1347 CurrentTransactionState = s;
1350 * check the current transaction state
1352 if (s->state != TRANS_DEFAULT)
1353 elog(WARNING, "StartTransaction while in %s state",
1354 TransStateAsString(s->state));
1357 * set the current transaction state information appropriately during
1360 s->state = TRANS_START;
1361 s->transactionId = InvalidTransactionId; /* until assigned */
1364 * Make sure we've freed any old snapshot, and reset xact state
1368 XactIsoLevel = DefaultXactIsoLevel;
1369 XactReadOnly = DefaultXactReadOnly;
1372 * reinitialize within-transaction counters
1374 s->subTransactionId = TopSubTransactionId;
1375 currentSubTransactionId = TopSubTransactionId;
1376 currentCommandId = FirstCommandId;
1379 * must initialize resource-management stuff first
1382 AtStart_ResourceOwner();
1385 * generate a new transaction id
1387 s->transactionId = GetNewTransactionId(false);
1389 XactLockTableInsert(s->transactionId);
1394 xactStartTime = GetCurrentAbsoluteTimeUsec(&(xactStartTimeUsec));
1397 * initialize current transaction state fields
1399 s->nestingLevel = 1;
1403 * You might expect to see "s->currentUser = GetUserId();" here, but
1404 * you won't because it doesn't work during startup; the userid isn't
1405 * set yet during a backend's first transaction start. We only use
1406 * the currentUser field in sub-transaction state structs.
1408 * prevXactReadOnly is also valid only in sub-transactions.
1412 * initialize other subsystems for new transaction
1416 AfterTriggerBeginXact();
1419 * done with start processing, set current transaction state to "in
1422 s->state = TRANS_INPROGRESS;
1424 ShowTransactionState("StartTransaction");
1431 * NB: if you change this routine, better look at PrepareTransaction too!
1434 CommitTransaction(void)
1436 TransactionState s = CurrentTransactionState;
1438 ShowTransactionState("CommitTransaction");
1441 * check the current transaction state
1443 if (s->state != TRANS_INPROGRESS)
1444 elog(WARNING, "CommitTransaction while in %s state",
1445 TransStateAsString(s->state));
1446 Assert(s->parent == NULL);
1449 * Do pre-commit processing (most of this stuff requires database
1450 * access, and in fact could still cause an error...)
1452 * It is possible for CommitHoldablePortals to invoke functions that
1453 * queue deferred triggers, and it's also possible that triggers create
1454 * holdable cursors. So we have to loop until there's nothing left to
1460 * Fire all currently pending deferred triggers.
1462 AfterTriggerFireDeferred();
1465 * Convert any open holdable cursors into static portals. If there
1466 * weren't any, we are done ... otherwise loop back to check if they
1467 * queued deferred triggers. Lather, rinse, repeat.
1469 if (!CommitHoldablePortals())
1473 /* Now we can shut down the deferred-trigger manager */
1474 AfterTriggerEndXact(true);
1476 /* Close any open regular cursors */
1480 * Let ON COMMIT management do its thing (must happen after closing
1481 * cursors, to avoid dangling-reference problems)
1483 PreCommit_on_commit_actions();
1485 /* close large objects before lower-level cleanup */
1486 AtEOXact_LargeObject(true);
1488 /* NOTIFY commit must come before lower-level cleanup */
1491 /* Update flat files if we changed pg_database, pg_shadow or pg_group */
1492 /* This should be the last step before commit */
1493 AtEOXact_UpdateFlatFiles(true);
1495 /* Prevent cancel/die interrupt while cleaning up */
1499 * set the current transaction state information appropriately during
1500 * the abort processing
1502 s->state = TRANS_COMMIT;
1505 * Here is where we really truly commit.
1507 RecordTransactionCommit();
1510 * Let others know about no transaction in progress by me. Note that
1511 * this must be done _before_ releasing locks we hold and _after_
1512 * RecordTransactionCommit.
1514 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1515 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1516 * xid 1 is doing commit while xid 2 gets snapshot.
1517 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1518 * xid 0 as running as well, or it will be able to see two tuple versions
1519 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1522 * Note: MyProc may be null during bootstrap.
1527 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1528 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1529 MyProc->xid = InvalidTransactionId;
1530 MyProc->xmin = InvalidTransactionId;
1532 /* Clear the subtransaction-XID cache too while holding the lock */
1533 MyProc->subxids.nxids = 0;
1534 MyProc->subxids.overflowed = false;
1536 LWLockRelease(ProcArrayLock);
1540 * This is all post-commit cleanup. Note that if an error is raised
1541 * here, it's too late to abort the transaction. This should be just
1542 * noncritical resource releasing.
1544 * The ordering of operations is not entirely random. The idea is:
1545 * release resources visible to other backends (eg, files, buffer
1546 * pins); then release locks; then release backend-local resources. We
1547 * want to release locks at the point where any backend waiting for us
1548 * will see our transaction as being fully cleaned up.
1550 * Resources that can be associated with individual queries are handled
1551 * by the ResourceOwner mechanism. The other calls here are for
1552 * backend-wide state.
1555 CallXactCallbacks(XACT_EVENT_COMMIT);
1557 ResourceOwnerRelease(TopTransactionResourceOwner,
1558 RESOURCE_RELEASE_BEFORE_LOCKS,
1561 /* Check we've released all buffer pins */
1562 AtEOXact_Buffers(true);
1565 * Make catalog changes visible to all backends. This has to happen
1566 * after relcache references are dropped (see comments for
1567 * AtEOXact_RelationCache), but before locks are released (if anyone
1568 * is waiting for lock on a relation we've modified, we want them to
1569 * know about the catalog change before they start using the
1572 AtEOXact_Inval(true);
1575 * Likewise, dropping of files deleted during the transaction is best done
1576 * after releasing relcache and buffer pins. (This is not strictly
1577 * necessary during commit, since such pins should have been released
1578 * already, but this ordering is definitely critical during abort.)
1580 smgrDoPendingDeletes(true);
1582 AtEOXact_MultiXact();
1584 ResourceOwnerRelease(TopTransactionResourceOwner,
1585 RESOURCE_RELEASE_LOCKS,
1587 ResourceOwnerRelease(TopTransactionResourceOwner,
1588 RESOURCE_RELEASE_AFTER_LOCKS,
1591 AtEOXact_GUC(true, false);
1593 AtEOXact_on_commit_actions(true);
1594 AtEOXact_Namespace(true);
1595 /* smgrcommit already done */
1597 pgstat_count_xact_commit();
1599 CurrentResourceOwner = NULL;
1600 ResourceOwnerDelete(TopTransactionResourceOwner);
1601 s->curTransactionOwner = NULL;
1602 CurTransactionResourceOwner = NULL;
1603 TopTransactionResourceOwner = NULL;
1607 s->transactionId = InvalidTransactionId;
1608 s->subTransactionId = InvalidSubTransactionId;
1609 s->nestingLevel = 0;
1613 * done with commit processing, set current transaction state back to
1616 s->state = TRANS_DEFAULT;
1618 RESUME_INTERRUPTS();
1623 * PrepareTransaction
1625 * NB: if you change this routine, better look at CommitTransaction too!
1628 PrepareTransaction(void)
1630 TransactionState s = CurrentTransactionState;
1631 TransactionId xid = GetCurrentTransactionId();
1632 GlobalTransaction gxact;
1633 TimestampTz prepared_at;
1634 AbsoluteTime PreparedSec; /* integer part */
1635 int PreparedUSec; /* microsecond part */
1637 ShowTransactionState("PrepareTransaction");
1640 * check the current transaction state
1642 if (s->state != TRANS_INPROGRESS)
1643 elog(WARNING, "PrepareTransaction while in %s state",
1644 TransStateAsString(s->state));
1645 Assert(s->parent == NULL);
1648 * Do pre-commit processing (most of this stuff requires database
1649 * access, and in fact could still cause an error...)
1651 * It is possible for PrepareHoldablePortals to invoke functions that
1652 * queue deferred triggers, and it's also possible that triggers create
1653 * holdable cursors. So we have to loop until there's nothing left to
1659 * Fire all currently pending deferred triggers.
1661 AfterTriggerFireDeferred();
1664 * Convert any open holdable cursors into static portals. If there
1665 * weren't any, we are done ... otherwise loop back to check if they
1666 * queued deferred triggers. Lather, rinse, repeat.
1668 if (!PrepareHoldablePortals())
1672 /* Now we can shut down the deferred-trigger manager */
1673 AfterTriggerEndXact(true);
1675 /* Close any open regular cursors */
1679 * Let ON COMMIT management do its thing (must happen after closing
1680 * cursors, to avoid dangling-reference problems)
1682 PreCommit_on_commit_actions();
1684 /* close large objects before lower-level cleanup */
1685 AtEOXact_LargeObject(true);
1687 /* NOTIFY and flatfiles will be handled below */
1689 /* Prevent cancel/die interrupt while cleaning up */
1693 * set the current transaction state information appropriately during
1696 s->state = TRANS_PREPARE;
1698 PreparedSec = GetCurrentAbsoluteTimeUsec(&PreparedUSec);
1699 prepared_at = AbsoluteTimeUsecToTimestampTz(PreparedSec, PreparedUSec);
1701 /* Tell bufmgr and smgr to prepare for commit */
1705 * Reserve the GID for this transaction. This could fail if the
1706 * requested GID is invalid or already in use.
1708 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1709 GetUserId(), MyDatabaseId);
1713 * Collect data for the 2PC state file. Note that in general, no actual
1714 * state change should happen in the called modules during this step,
1715 * since it's still possible to fail before commit, and in that case we
1716 * want transaction abort to be able to clean up. (In particular, the
1717 * AtPrepare routines may error out if they find cases they cannot
1718 * handle.) State cleanup should happen in the PostPrepare routines
1719 * below. However, some modules can go ahead and clear state here
1720 * because they wouldn't do anything with it during abort anyway.
1722 * Note: because the 2PC state file records will be replayed in the same
1723 * order they are made, the order of these calls has to match the order
1724 * in which we want things to happen during COMMIT PREPARED or
1725 * ROLLBACK PREPARED; in particular, pay attention to whether things
1726 * should happen before or after releasing the transaction's locks.
1728 StartPrepare(gxact);
1731 AtPrepare_UpdateFlatFiles();
1736 * Here is where we really truly prepare.
1738 * We have to record transaction prepares even if we didn't
1739 * make any updates, because the transaction manager might
1740 * get confused if we lose a global transaction.
1745 * Now we clean up backend-internal state and release internal
1749 /* Break the chain of back-links in the XLOG records I output */
1750 MyLastRecPtr.xrecoff = 0;
1751 MyXactMadeXLogEntry = false;
1752 MyXactMadeTempRelUpdate = false;
1755 * Let others know about no transaction in progress by me. This has
1756 * to be done *after* the prepared transaction has been marked valid,
1757 * else someone may think it is unlocked and recyclable.
1760 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1761 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1762 MyProc->xid = InvalidTransactionId;
1763 MyProc->xmin = InvalidTransactionId;
1765 /* Clear the subtransaction-XID cache too while holding the lock */
1766 MyProc->subxids.nxids = 0;
1767 MyProc->subxids.overflowed = false;
1769 LWLockRelease(ProcArrayLock);
1772 * This is all post-transaction cleanup. Note that if an error is raised
1773 * here, it's too late to abort the transaction. This should be just
1774 * noncritical resource releasing. See notes in CommitTransaction.
1777 CallXactCallbacks(XACT_EVENT_PREPARE);
1779 ResourceOwnerRelease(TopTransactionResourceOwner,
1780 RESOURCE_RELEASE_BEFORE_LOCKS,
1783 /* Check we've released all buffer pins */
1784 AtEOXact_Buffers(true);
1786 /* notify and flatfiles don't need a postprepare call */
1788 PostPrepare_Inval();
1792 AtEOXact_MultiXact();
1794 PostPrepare_Locks(xid);
1796 ResourceOwnerRelease(TopTransactionResourceOwner,
1797 RESOURCE_RELEASE_LOCKS,
1799 ResourceOwnerRelease(TopTransactionResourceOwner,
1800 RESOURCE_RELEASE_AFTER_LOCKS,
1803 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1804 AtEOXact_GUC(true, false);
1806 AtEOXact_on_commit_actions(true);
1807 AtEOXact_Namespace(true);
1808 /* smgrcommit already done */
1811 CurrentResourceOwner = NULL;
1812 ResourceOwnerDelete(TopTransactionResourceOwner);
1813 s->curTransactionOwner = NULL;
1814 CurTransactionResourceOwner = NULL;
1815 TopTransactionResourceOwner = NULL;
1819 s->transactionId = InvalidTransactionId;
1820 s->subTransactionId = InvalidSubTransactionId;
1821 s->nestingLevel = 0;
1825 * done with 1st phase commit processing, set current transaction
1826 * state back to default
1828 s->state = TRANS_DEFAULT;
1830 RESUME_INTERRUPTS();
1838 AbortTransaction(void)
1840 TransactionState s = CurrentTransactionState;
1842 /* Prevent cancel/die interrupt while cleaning up */
1846 * Release any LW locks we might be holding as quickly as possible.
1847 * (Regular locks, however, must be held till we finish aborting.)
1848 * Releasing LW locks is critical since we might try to grab them
1849 * again while cleaning up!
1853 /* Clean up buffer I/O and buffer context locks, too */
1858 * Also clean up any open wait for lock, since the lock manager will
1859 * choke if we try to wait for another lock before doing this.
1864 * check the current transaction state
1866 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1867 elog(WARNING, "AbortTransaction while in %s state",
1868 TransStateAsString(s->state));
1869 Assert(s->parent == NULL);
1872 * set the current transaction state information appropriately during
1873 * the abort processing
1875 s->state = TRANS_ABORT;
1877 /* Make sure we have a valid memory context and resource owner */
1879 AtAbort_ResourceOwner();
1882 * Reset user id which might have been changed transiently. We cannot
1883 * use s->currentUser, but must get the session userid from
1886 * (Note: it is not necessary to restore session authorization here
1887 * because that can only be changed via GUC, and GUC will take care of
1888 * rolling it back if need be. However, an error within a SECURITY
1889 * DEFINER function could send control here with the wrong current
1892 SetUserId(GetSessionUserId());
1895 * do abort processing
1897 AfterTriggerEndXact(false);
1899 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1901 AtEOXact_UpdateFlatFiles(false);
1904 * Advertise the fact that we aborted in pg_clog (assuming that we
1905 * got as far as assigning an XID to advertise).
1907 if (TransactionIdIsValid(s->transactionId))
1908 RecordTransactionAbort();
1911 * Let others know about no transaction in progress by me. Note that
1912 * this must be done _before_ releasing locks we hold and _after_
1913 * RecordTransactionAbort.
1917 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1918 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1919 MyProc->xid = InvalidTransactionId;
1920 MyProc->xmin = InvalidTransactionId;
1922 /* Clear the subtransaction-XID cache too while holding the lock */
1923 MyProc->subxids.nxids = 0;
1924 MyProc->subxids.overflowed = false;
1926 LWLockRelease(ProcArrayLock);
1930 * Post-abort cleanup. See notes in CommitTransaction() concerning
1934 CallXactCallbacks(XACT_EVENT_ABORT);
1936 ResourceOwnerRelease(TopTransactionResourceOwner,
1937 RESOURCE_RELEASE_BEFORE_LOCKS,
1939 AtEOXact_Buffers(false);
1940 AtEOXact_Inval(false);
1941 smgrDoPendingDeletes(false);
1942 AtEOXact_MultiXact();
1943 ResourceOwnerRelease(TopTransactionResourceOwner,
1944 RESOURCE_RELEASE_LOCKS,
1946 ResourceOwnerRelease(TopTransactionResourceOwner,
1947 RESOURCE_RELEASE_AFTER_LOCKS,
1950 AtEOXact_GUC(false, false);
1951 AtEOXact_SPI(false);
1952 AtEOXact_on_commit_actions(false);
1953 AtEOXact_Namespace(false);
1956 pgstat_count_xact_rollback();
1959 * State remains TRANS_ABORT until CleanupTransaction().
1961 RESUME_INTERRUPTS();
1965 * CleanupTransaction
1968 CleanupTransaction(void)
1970 TransactionState s = CurrentTransactionState;
1973 * State should still be TRANS_ABORT from AbortTransaction().
1975 if (s->state != TRANS_ABORT)
1976 elog(FATAL, "CleanupTransaction: unexpected state %s",
1977 TransStateAsString(s->state));
1980 * do abort cleanup processing
1982 AtCleanup_Portals(); /* now safe to release portal memory */
1984 CurrentResourceOwner = NULL; /* and resource owner */
1985 if (TopTransactionResourceOwner)
1986 ResourceOwnerDelete(TopTransactionResourceOwner);
1987 s->curTransactionOwner = NULL;
1988 CurTransactionResourceOwner = NULL;
1989 TopTransactionResourceOwner = NULL;
1991 AtCleanup_Memory(); /* and transaction memory */
1993 s->transactionId = InvalidTransactionId;
1994 s->subTransactionId = InvalidSubTransactionId;
1995 s->nestingLevel = 0;
1999 * done with abort processing, set current transaction state back to
2002 s->state = TRANS_DEFAULT;
2006 * StartTransactionCommand
2009 StartTransactionCommand(void)
2011 TransactionState s = CurrentTransactionState;
2013 switch (s->blockState)
2016 * if we aren't in a transaction block, we just do our usual
2017 * start transaction.
2019 case TBLOCK_DEFAULT:
2021 s->blockState = TBLOCK_STARTED;
2025 * We are somewhere in a transaction block or subtransaction
2026 * and about to start a new command. For now we do nothing,
2027 * but someday we may do command-local resource initialization.
2028 * (Note that any needed CommandCounterIncrement was done by
2029 * the previous CommitTransactionCommand.)
2031 case TBLOCK_INPROGRESS:
2032 case TBLOCK_SUBINPROGRESS:
2036 * Here we are in a failed transaction block (one of
2037 * the commands caused an abort) so we do nothing but remain in
2038 * the abort state. Eventually we will get a ROLLBACK command
2039 * which will get us out of this state. (It is up to other
2040 * code to ensure that no commands other than ROLLBACK will be
2041 * processed in these states.)
2044 case TBLOCK_SUBABORT:
2047 /* These cases are invalid. */
2048 case TBLOCK_STARTED:
2050 case TBLOCK_SUBBEGIN:
2053 case TBLOCK_ABORT_END:
2054 case TBLOCK_SUBABORT_END:
2055 case TBLOCK_ABORT_PENDING:
2056 case TBLOCK_SUBABORT_PENDING:
2057 case TBLOCK_SUBRESTART:
2058 case TBLOCK_SUBABORT_RESTART:
2059 case TBLOCK_PREPARE:
2060 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2061 BlockStateAsString(s->blockState));
2066 * We must switch to CurTransactionContext before returning. This is
2067 * already done if we called StartTransaction, otherwise not.
2069 Assert(CurTransactionContext != NULL);
2070 MemoryContextSwitchTo(CurTransactionContext);
2074 * CommitTransactionCommand
2077 CommitTransactionCommand(void)
2079 TransactionState s = CurrentTransactionState;
2081 switch (s->blockState)
2084 * This shouldn't happen, because it means the previous
2085 * StartTransactionCommand didn't set the STARTED state
2088 case TBLOCK_DEFAULT:
2089 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2090 BlockStateAsString(s->blockState));
2094 * If we aren't in a transaction block, just do our usual
2095 * transaction commit, and return to the idle state.
2097 case TBLOCK_STARTED:
2098 CommitTransaction();
2099 s->blockState = TBLOCK_DEFAULT;
2103 * We are completing a "BEGIN TRANSACTION" command, so we
2104 * change to the "transaction block in progress" state and
2105 * return. (We assume the BEGIN did nothing to the database,
2106 * so we need no CommandCounterIncrement.)
2109 s->blockState = TBLOCK_INPROGRESS;
2113 * This is the case when we have finished executing a command
2114 * someplace within a transaction block. We increment the
2115 * command counter and return.
2117 case TBLOCK_INPROGRESS:
2118 case TBLOCK_SUBINPROGRESS:
2119 CommandCounterIncrement();
2123 * We are completing a "COMMIT" command. Do it and return to
2127 CommitTransaction();
2128 s->blockState = TBLOCK_DEFAULT;
2132 * Here we are in the middle of a transaction block but one of
2133 * the commands caused an abort so we do nothing but remain in
2134 * the abort state. Eventually we will get a ROLLBACK comand.
2137 case TBLOCK_SUBABORT:
2141 * Here we were in an aborted transaction block and we just
2142 * got the ROLLBACK command from the user, so clean up the
2143 * already-aborted transaction and return to the idle state.
2145 case TBLOCK_ABORT_END:
2146 CleanupTransaction();
2147 s->blockState = TBLOCK_DEFAULT;
2151 * Here we were in a perfectly good transaction block but the
2152 * user told us to ROLLBACK anyway. We have to abort the
2153 * transaction and then clean up.
2155 case TBLOCK_ABORT_PENDING:
2157 CleanupTransaction();
2158 s->blockState = TBLOCK_DEFAULT;
2162 * We are completing a "PREPARE TRANSACTION" command. Do it and
2163 * return to the idle state.
2165 case TBLOCK_PREPARE:
2166 PrepareTransaction();
2167 s->blockState = TBLOCK_DEFAULT;
2171 * We were just issued a SAVEPOINT inside a transaction block.
2172 * Start a subtransaction. (DefineSavepoint already did
2173 * PushTransaction, so as to have someplace to put the
2176 case TBLOCK_SUBBEGIN:
2177 StartSubTransaction();
2178 s->blockState = TBLOCK_SUBINPROGRESS;
2182 * We were issued a COMMIT or RELEASE command, so we end the
2183 * current subtransaction and return to the parent transaction.
2184 * The parent might be ended too, so repeat till we are all the
2185 * way out or find an INPROGRESS transaction.
2190 CommitSubTransaction();
2191 s = CurrentTransactionState; /* changed by pop */
2192 } while (s->blockState == TBLOCK_SUBEND);
2193 /* If we had a COMMIT command, finish off the main xact too */
2194 if (s->blockState == TBLOCK_END)
2196 Assert(s->parent == NULL);
2197 CommitTransaction();
2198 s->blockState = TBLOCK_DEFAULT;
2200 else if (s->blockState == TBLOCK_PREPARE)
2202 Assert(s->parent == NULL);
2203 PrepareTransaction();
2204 s->blockState = TBLOCK_DEFAULT;
2208 Assert(s->blockState == TBLOCK_INPROGRESS ||
2209 s->blockState == TBLOCK_SUBINPROGRESS);
2214 * The current already-failed subtransaction is ending due to a
2215 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2216 * examine the parent (which could be in any of several states).
2218 case TBLOCK_SUBABORT_END:
2219 CleanupSubTransaction();
2220 CommitTransactionCommand();
2224 * As above, but it's not dead yet, so abort first.
2226 case TBLOCK_SUBABORT_PENDING:
2227 AbortSubTransaction();
2228 CleanupSubTransaction();
2229 CommitTransactionCommand();
2233 * The current subtransaction is the target of a ROLLBACK TO
2234 * command. Abort and pop it, then start a new subtransaction
2235 * with the same name.
2237 case TBLOCK_SUBRESTART:
2242 /* save name and keep Cleanup from freeing it */
2245 savepointLevel = s->savepointLevel;
2247 AbortSubTransaction();
2248 CleanupSubTransaction();
2250 DefineSavepoint(NULL);
2251 s = CurrentTransactionState; /* changed by push */
2253 s->savepointLevel = savepointLevel;
2255 /* This is the same as TBLOCK_SUBBEGIN case */
2256 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2257 StartSubTransaction();
2258 s->blockState = TBLOCK_SUBINPROGRESS;
2263 * Same as above, but the subtransaction had already failed,
2264 * so we don't need AbortSubTransaction.
2266 case TBLOCK_SUBABORT_RESTART:
2271 /* save name and keep Cleanup from freeing it */
2274 savepointLevel = s->savepointLevel;
2276 CleanupSubTransaction();
2278 DefineSavepoint(NULL);
2279 s = CurrentTransactionState; /* changed by push */
2281 s->savepointLevel = savepointLevel;
2283 /* This is the same as TBLOCK_SUBBEGIN case */
2284 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2285 StartSubTransaction();
2286 s->blockState = TBLOCK_SUBINPROGRESS;
2293 * AbortCurrentTransaction
2296 AbortCurrentTransaction(void)
2298 TransactionState s = CurrentTransactionState;
2300 switch (s->blockState)
2302 case TBLOCK_DEFAULT:
2303 if (s->state == TRANS_DEFAULT)
2305 /* we are idle, so nothing to do */
2310 * We can get here after an error during transaction start
2311 * (state will be TRANS_START). Need to clean up the
2312 * incompletely started transaction. First, adjust the
2313 * low-level state to suppress warning message from
2316 if (s->state == TRANS_START)
2317 s->state = TRANS_INPROGRESS;
2319 CleanupTransaction();
2324 * if we aren't in a transaction block, we just do the basic
2325 * abort & cleanup transaction.
2327 case TBLOCK_STARTED:
2329 CleanupTransaction();
2330 s->blockState = TBLOCK_DEFAULT;
2334 * If we are in TBLOCK_BEGIN it means something screwed up
2335 * right after reading "BEGIN TRANSACTION". We assume that
2336 * the user will interpret the error as meaning the BEGIN
2337 * failed to get him into a transaction block, so we should
2338 * abort and return to idle state.
2342 CleanupTransaction();
2343 s->blockState = TBLOCK_DEFAULT;
2347 * We are somewhere in a transaction block and we've gotten a
2348 * failure, so we abort the transaction and set up the persistent
2349 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2351 case TBLOCK_INPROGRESS:
2353 s->blockState = TBLOCK_ABORT;
2354 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2358 * Here, we failed while trying to COMMIT. Clean up the
2359 * transaction and return to idle state (we do not want to
2360 * stay in the transaction).
2364 CleanupTransaction();
2365 s->blockState = TBLOCK_DEFAULT;
2369 * Here, we are already in an aborted transaction state and
2370 * are waiting for a ROLLBACK, but for some reason we failed
2371 * again! So we just remain in the abort state.
2374 case TBLOCK_SUBABORT:
2378 * We are in a failed transaction and we got the ROLLBACK command.
2379 * We have already aborted, we just need to cleanup and go to
2382 case TBLOCK_ABORT_END:
2383 CleanupTransaction();
2384 s->blockState = TBLOCK_DEFAULT;
2388 * We are in a live transaction and we got a ROLLBACK command.
2389 * Abort, cleanup, go to idle state.
2391 case TBLOCK_ABORT_PENDING:
2393 CleanupTransaction();
2394 s->blockState = TBLOCK_DEFAULT;
2398 * Here, we failed while trying to PREPARE. Clean up the
2399 * transaction and return to idle state (we do not want to
2400 * stay in the transaction).
2402 case TBLOCK_PREPARE:
2404 CleanupTransaction();
2405 s->blockState = TBLOCK_DEFAULT;
2409 * We got an error inside a subtransaction. Abort just the
2410 * subtransaction, and go to the persistent SUBABORT state
2411 * until we get ROLLBACK.
2413 case TBLOCK_SUBINPROGRESS:
2414 AbortSubTransaction();
2415 s->blockState = TBLOCK_SUBABORT;
2419 * If we failed while trying to create a subtransaction, clean up
2420 * the broken subtransaction and abort the parent. The same
2421 * applies if we get a failure while ending a subtransaction.
2423 case TBLOCK_SUBBEGIN:
2425 case TBLOCK_SUBABORT_PENDING:
2426 case TBLOCK_SUBRESTART:
2427 AbortSubTransaction();
2428 CleanupSubTransaction();
2429 AbortCurrentTransaction();
2433 * Same as above, except the Abort() was already done.
2435 case TBLOCK_SUBABORT_END:
2436 case TBLOCK_SUBABORT_RESTART:
2437 CleanupSubTransaction();
2438 AbortCurrentTransaction();
2444 * PreventTransactionChain
2446 * This routine is to be called by statements that must not run inside
2447 * a transaction block, typically because they have non-rollback-able
2448 * side effects or do internal commits.
2450 * If we have already started a transaction block, issue an error; also issue
2451 * an error if we appear to be running inside a user-defined function (which
2452 * could issue more commands and possibly cause a failure after the statement
2453 * completes). Subtransactions are verboten too.
2455 * stmtNode: pointer to parameter block for statement; this is used in
2456 * a very klugy way to determine whether we are inside a function.
2457 * stmtType: statement type name for error messages.
2460 PreventTransactionChain(void *stmtNode, const char *stmtType)
2463 * xact block already started?
2465 if (IsTransactionBlock())
2467 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2468 /* translator: %s represents an SQL statement name */
2469 errmsg("%s cannot run inside a transaction block",
2475 if (IsSubTransaction())
2477 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2478 /* translator: %s represents an SQL statement name */
2479 errmsg("%s cannot run inside a subtransaction",
2483 * Are we inside a function call? If the statement's parameter block
2484 * was allocated in QueryContext, assume it is an interactive command.
2485 * Otherwise assume it is coming from a function.
2487 if (!MemoryContextContains(QueryContext, stmtNode))
2489 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2490 /* translator: %s represents an SQL statement name */
2491 errmsg("%s cannot be executed from a function", stmtType)));
2493 /* If we got past IsTransactionBlock test, should be in default state */
2494 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2495 CurrentTransactionState->blockState != TBLOCK_STARTED)
2496 elog(FATAL, "cannot prevent transaction chain");
2501 * RequireTransactionChain
2503 * This routine is to be called by statements that must run inside
2504 * a transaction block, because they have no effects that persist past
2505 * transaction end (and so calling them outside a transaction block
2506 * is presumably an error). DECLARE CURSOR is an example.
2508 * If we appear to be running inside a user-defined function, we do not
2509 * issue an error, since the function could issue more commands that make
2510 * use of the current statement's results. Likewise subtransactions.
2511 * Thus this is an inverse for PreventTransactionChain.
2513 * stmtNode: pointer to parameter block for statement; this is used in
2514 * a very klugy way to determine whether we are inside a function.
2515 * stmtType: statement type name for error messages.
2518 RequireTransactionChain(void *stmtNode, const char *stmtType)
2521 * xact block already started?
2523 if (IsTransactionBlock())
2529 if (IsSubTransaction())
2533 * Are we inside a function call? If the statement's parameter block
2534 * was allocated in QueryContext, assume it is an interactive command.
2535 * Otherwise assume it is coming from a function.
2537 if (!MemoryContextContains(QueryContext, stmtNode))
2540 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2541 /* translator: %s represents an SQL statement name */
2542 errmsg("%s may only be used in transaction blocks",
2547 * IsInTransactionChain
2549 * This routine is for statements that need to behave differently inside
2550 * a transaction block than when running as single commands. ANALYZE is
2551 * currently the only example.
2553 * stmtNode: pointer to parameter block for statement; this is used in
2554 * a very klugy way to determine whether we are inside a function.
2557 IsInTransactionChain(void *stmtNode)
2560 * Return true on same conditions that would make
2561 * PreventTransactionChain error out
2563 if (IsTransactionBlock())
2566 if (IsSubTransaction())
2569 if (!MemoryContextContains(QueryContext, stmtNode))
2572 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2573 CurrentTransactionState->blockState != TBLOCK_STARTED)
2581 * Register or deregister callback functions for start- and end-of-xact
2584 * These functions are intended for use by dynamically loaded modules.
2585 * For built-in modules we generally just hardwire the appropriate calls
2586 * (mainly because it's easier to control the order that way, where needed).
2588 * At transaction end, the callback occurs post-commit or post-abort, so the
2589 * callback functions can only do noncritical cleanup.
2592 RegisterXactCallback(XactCallback callback, void *arg)
2594 XactCallbackItem *item;
2596 item = (XactCallbackItem *)
2597 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2598 item->callback = callback;
2600 item->next = Xact_callbacks;
2601 Xact_callbacks = item;
2605 UnregisterXactCallback(XactCallback callback, void *arg)
2607 XactCallbackItem *item;
2608 XactCallbackItem *prev;
2611 for (item = Xact_callbacks; item; prev = item, item = item->next)
2613 if (item->callback == callback && item->arg == arg)
2616 prev->next = item->next;
2618 Xact_callbacks = item->next;
2626 CallXactCallbacks(XactEvent event)
2628 XactCallbackItem *item;
2630 for (item = Xact_callbacks; item; item = item->next)
2631 (*item->callback) (event, item->arg);
2636 * Register or deregister callback functions for start- and end-of-subxact
2639 * Pretty much same as above, but for subtransaction events.
2641 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2642 * so the callback functions can only do noncritical cleanup. At
2643 * subtransaction start, the callback is called when the subtransaction has
2644 * finished initializing.
2647 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2649 SubXactCallbackItem *item;
2651 item = (SubXactCallbackItem *)
2652 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2653 item->callback = callback;
2655 item->next = SubXact_callbacks;
2656 SubXact_callbacks = item;
2660 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2662 SubXactCallbackItem *item;
2663 SubXactCallbackItem *prev;
2666 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2668 if (item->callback == callback && item->arg == arg)
2671 prev->next = item->next;
2673 SubXact_callbacks = item->next;
2681 CallSubXactCallbacks(SubXactEvent event,
2682 SubTransactionId mySubid,
2683 SubTransactionId parentSubid)
2685 SubXactCallbackItem *item;
2687 for (item = SubXact_callbacks; item; item = item->next)
2688 (*item->callback) (event, mySubid, parentSubid, item->arg);
2692 /* ----------------------------------------------------------------
2693 * transaction block support
2694 * ----------------------------------------------------------------
2698 * BeginTransactionBlock
2699 * This executes a BEGIN command.
2702 BeginTransactionBlock(void)
2704 TransactionState s = CurrentTransactionState;
2706 switch (s->blockState)
2709 * We are not inside a transaction block, so allow one to
2712 case TBLOCK_STARTED:
2713 s->blockState = TBLOCK_BEGIN;
2717 * Already a transaction block in progress.
2719 case TBLOCK_INPROGRESS:
2720 case TBLOCK_SUBINPROGRESS:
2722 case TBLOCK_SUBABORT:
2724 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2725 errmsg("there is already a transaction in progress")));
2728 /* These cases are invalid. */
2729 case TBLOCK_DEFAULT:
2731 case TBLOCK_SUBBEGIN:
2734 case TBLOCK_ABORT_END:
2735 case TBLOCK_SUBABORT_END:
2736 case TBLOCK_ABORT_PENDING:
2737 case TBLOCK_SUBABORT_PENDING:
2738 case TBLOCK_SUBRESTART:
2739 case TBLOCK_SUBABORT_RESTART:
2740 case TBLOCK_PREPARE:
2741 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2742 BlockStateAsString(s->blockState));
2748 * PrepareTransactionBlock
2749 * This executes a PREPARE command.
2751 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2752 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2754 * Note that we don't actually do anything here except change blockState.
2755 * The real work will be done in the upcoming PrepareTransaction().
2756 * We do it this way because it's not convenient to change memory context,
2757 * resource owner, etc while executing inside a Portal.
2760 PrepareTransactionBlock(char *gid)
2765 /* Set up to commit the current transaction */
2766 result = EndTransactionBlock();
2768 /* If successful, change outer tblock state to PREPARE */
2771 s = CurrentTransactionState;
2773 while (s->parent != NULL)
2776 if (s->blockState == TBLOCK_END)
2778 /* Save GID where PrepareTransaction can find it again */
2779 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2781 s->blockState = TBLOCK_PREPARE;
2786 * ignore case where we are not in a transaction;
2787 * EndTransactionBlock already issued a warning.
2789 Assert(s->blockState == TBLOCK_STARTED);
2790 /* Don't send back a PREPARE result tag... */
2799 * EndTransactionBlock
2800 * This executes a COMMIT command.
2802 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2803 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2805 * Note that we don't actually do anything here except change blockState.
2806 * The real work will be done in the upcoming CommitTransactionCommand().
2807 * We do it this way because it's not convenient to change memory context,
2808 * resource owner, etc while executing inside a Portal.
2811 EndTransactionBlock(void)
2813 TransactionState s = CurrentTransactionState;
2814 bool result = false;
2816 switch (s->blockState)
2819 * We are in a transaction block, so tell CommitTransactionCommand
2822 case TBLOCK_INPROGRESS:
2823 s->blockState = TBLOCK_END;
2828 * We are in a failed transaction block. Tell
2829 * CommitTransactionCommand it's time to exit the block.
2832 s->blockState = TBLOCK_ABORT_END;
2836 * We are in a live subtransaction block. Set up to subcommit
2837 * all open subtransactions and then commit the main transaction.
2839 case TBLOCK_SUBINPROGRESS:
2840 while (s->parent != NULL)
2842 if (s->blockState == TBLOCK_SUBINPROGRESS)
2843 s->blockState = TBLOCK_SUBEND;
2845 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2846 BlockStateAsString(s->blockState));
2849 if (s->blockState == TBLOCK_INPROGRESS)
2850 s->blockState = TBLOCK_END;
2852 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2853 BlockStateAsString(s->blockState));
2858 * Here we are inside an aborted subtransaction. Treat the
2859 * COMMIT as ROLLBACK: set up to abort everything and exit
2860 * the main transaction.
2862 case TBLOCK_SUBABORT:
2863 while (s->parent != NULL)
2865 if (s->blockState == TBLOCK_SUBINPROGRESS)
2866 s->blockState = TBLOCK_SUBABORT_PENDING;
2867 else if (s->blockState == TBLOCK_SUBABORT)
2868 s->blockState = TBLOCK_SUBABORT_END;
2870 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2871 BlockStateAsString(s->blockState));
2874 if (s->blockState == TBLOCK_INPROGRESS)
2875 s->blockState = TBLOCK_ABORT_PENDING;
2876 else if (s->blockState == TBLOCK_ABORT)
2877 s->blockState = TBLOCK_ABORT_END;
2879 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2880 BlockStateAsString(s->blockState));
2884 * The user issued COMMIT when not inside a transaction. Issue a
2885 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2886 * CommitTransactionCommand() will then close the transaction and
2887 * put us back into the default state.
2889 case TBLOCK_STARTED:
2891 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2892 errmsg("there is no transaction in progress")));
2896 /* These cases are invalid. */
2897 case TBLOCK_DEFAULT:
2899 case TBLOCK_SUBBEGIN:
2902 case TBLOCK_ABORT_END:
2903 case TBLOCK_SUBABORT_END:
2904 case TBLOCK_ABORT_PENDING:
2905 case TBLOCK_SUBABORT_PENDING:
2906 case TBLOCK_SUBRESTART:
2907 case TBLOCK_SUBABORT_RESTART:
2908 case TBLOCK_PREPARE:
2909 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2910 BlockStateAsString(s->blockState));
2918 * UserAbortTransactionBlock
2919 * This executes a ROLLBACK command.
2921 * As above, we don't actually do anything here except change blockState.
2924 UserAbortTransactionBlock(void)
2926 TransactionState s = CurrentTransactionState;
2928 switch (s->blockState)
2931 * We are inside a transaction block and we got a ROLLBACK
2932 * command from the user, so tell CommitTransactionCommand
2933 * to abort and exit the transaction block.
2935 case TBLOCK_INPROGRESS:
2936 s->blockState = TBLOCK_ABORT_PENDING;
2940 * We are inside a failed transaction block and we got a ROLLBACK
2941 * command from the user. Abort processing is already done,
2942 * so CommitTransactionCommand just has to cleanup and go back
2946 s->blockState = TBLOCK_ABORT_END;
2950 * We are inside a subtransaction. Mark everything
2951 * up to top level as exitable.
2953 case TBLOCK_SUBINPROGRESS:
2954 case TBLOCK_SUBABORT:
2955 while (s->parent != NULL)
2957 if (s->blockState == TBLOCK_SUBINPROGRESS)
2958 s->blockState = TBLOCK_SUBABORT_PENDING;
2959 else if (s->blockState == TBLOCK_SUBABORT)
2960 s->blockState = TBLOCK_SUBABORT_END;
2962 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2963 BlockStateAsString(s->blockState));
2966 if (s->blockState == TBLOCK_INPROGRESS)
2967 s->blockState = TBLOCK_ABORT_PENDING;
2968 else if (s->blockState == TBLOCK_ABORT)
2969 s->blockState = TBLOCK_ABORT_END;
2971 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2972 BlockStateAsString(s->blockState));
2976 * The user issued ABORT when not inside a transaction. Issue
2977 * a WARNING and go to abort state. The upcoming call to
2978 * CommitTransactionCommand() will then put us back into the
2981 case TBLOCK_STARTED:
2983 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2984 errmsg("there is no transaction in progress")));
2985 s->blockState = TBLOCK_ABORT_PENDING;
2988 /* These cases are invalid. */
2989 case TBLOCK_DEFAULT:
2991 case TBLOCK_SUBBEGIN:
2994 case TBLOCK_ABORT_END:
2995 case TBLOCK_SUBABORT_END:
2996 case TBLOCK_ABORT_PENDING:
2997 case TBLOCK_SUBABORT_PENDING:
2998 case TBLOCK_SUBRESTART:
2999 case TBLOCK_SUBABORT_RESTART:
3000 case TBLOCK_PREPARE:
3001 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3002 BlockStateAsString(s->blockState));
3009 * This executes a SAVEPOINT command.
3012 DefineSavepoint(char *name)
3014 TransactionState s = CurrentTransactionState;
3016 switch (s->blockState)
3018 case TBLOCK_INPROGRESS:
3019 case TBLOCK_SUBINPROGRESS:
3020 /* Normal subtransaction start */
3022 s = CurrentTransactionState; /* changed by push */
3025 * Savepoint names, like the TransactionState block itself,
3026 * live in TopTransactionContext.
3029 s->name = MemoryContextStrdup(TopTransactionContext, name);
3032 /* These cases are invalid. */
3033 case TBLOCK_DEFAULT:
3034 case TBLOCK_STARTED:
3036 case TBLOCK_SUBBEGIN:
3040 case TBLOCK_SUBABORT:
3041 case TBLOCK_ABORT_END:
3042 case TBLOCK_SUBABORT_END:
3043 case TBLOCK_ABORT_PENDING:
3044 case TBLOCK_SUBABORT_PENDING:
3045 case TBLOCK_SUBRESTART:
3046 case TBLOCK_SUBABORT_RESTART:
3047 case TBLOCK_PREPARE:
3048 elog(FATAL, "DefineSavepoint: unexpected state %s",
3049 BlockStateAsString(s->blockState));
3056 * This executes a RELEASE command.
3058 * As above, we don't actually do anything here except change blockState.
3061 ReleaseSavepoint(List *options)
3063 TransactionState s = CurrentTransactionState;
3064 TransactionState target,
3069 switch (s->blockState)
3072 * We can't rollback to a savepoint if there is no savepoint
3075 case TBLOCK_INPROGRESS:
3077 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3078 errmsg("no such savepoint")));
3082 * We are in a non-aborted subtransaction. This is the only
3085 case TBLOCK_SUBINPROGRESS:
3088 /* These cases are invalid. */
3089 case TBLOCK_DEFAULT:
3090 case TBLOCK_STARTED:
3092 case TBLOCK_SUBBEGIN:
3096 case TBLOCK_SUBABORT:
3097 case TBLOCK_ABORT_END:
3098 case TBLOCK_SUBABORT_END:
3099 case TBLOCK_ABORT_PENDING:
3100 case TBLOCK_SUBABORT_PENDING:
3101 case TBLOCK_SUBRESTART:
3102 case TBLOCK_SUBABORT_RESTART:
3103 case TBLOCK_PREPARE:
3104 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3105 BlockStateAsString(s->blockState));
3109 foreach(cell, options)
3111 DefElem *elem = lfirst(cell);
3113 if (strcmp(elem->defname, "savepoint_name") == 0)
3114 name = strVal(elem->arg);
3117 Assert(PointerIsValid(name));
3119 for (target = s; PointerIsValid(target); target = target->parent)
3121 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3125 if (!PointerIsValid(target))
3127 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3128 errmsg("no such savepoint")));
3130 /* disallow crossing savepoint level boundaries */
3131 if (target->savepointLevel != s->savepointLevel)
3133 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3134 errmsg("no such savepoint")));
3137 * Mark "commit pending" all subtransactions up to the target
3138 * subtransaction. The actual commits will happen when control gets
3139 * to CommitTransactionCommand.
3141 xact = CurrentTransactionState;
3144 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3145 xact->blockState = TBLOCK_SUBEND;
3148 xact = xact->parent;
3149 Assert(PointerIsValid(xact));
3154 * RollbackToSavepoint
3155 * This executes a ROLLBACK TO <savepoint> command.
3157 * As above, we don't actually do anything here except change blockState.
3160 RollbackToSavepoint(List *options)
3162 TransactionState s = CurrentTransactionState;
3163 TransactionState target,
3168 switch (s->blockState)
3171 * We can't rollback to a savepoint if there is no savepoint
3174 case TBLOCK_INPROGRESS:
3177 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3178 errmsg("no such savepoint")));
3182 * There is at least one savepoint, so proceed.
3184 case TBLOCK_SUBINPROGRESS:
3185 case TBLOCK_SUBABORT:
3188 /* These cases are invalid. */
3189 case TBLOCK_DEFAULT:
3190 case TBLOCK_STARTED:
3192 case TBLOCK_SUBBEGIN:
3195 case TBLOCK_ABORT_END:
3196 case TBLOCK_SUBABORT_END:
3197 case TBLOCK_ABORT_PENDING:
3198 case TBLOCK_SUBABORT_PENDING:
3199 case TBLOCK_SUBRESTART:
3200 case TBLOCK_SUBABORT_RESTART:
3201 case TBLOCK_PREPARE:
3202 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3203 BlockStateAsString(s->blockState));
3207 foreach(cell, options)
3209 DefElem *elem = lfirst(cell);
3211 if (strcmp(elem->defname, "savepoint_name") == 0)
3212 name = strVal(elem->arg);
3215 Assert(PointerIsValid(name));
3217 for (target = s; PointerIsValid(target); target = target->parent)
3219 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3223 if (!PointerIsValid(target))
3225 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3226 errmsg("no such savepoint")));
3228 /* disallow crossing savepoint level boundaries */
3229 if (target->savepointLevel != s->savepointLevel)
3231 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3232 errmsg("no such savepoint")));
3235 * Mark "abort pending" all subtransactions up to the target
3236 * subtransaction. The actual aborts will happen when control gets
3237 * to CommitTransactionCommand.
3239 xact = CurrentTransactionState;
3244 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3245 xact->blockState = TBLOCK_SUBABORT_PENDING;
3246 else if (xact->blockState == TBLOCK_SUBABORT)
3247 xact->blockState = TBLOCK_SUBABORT_END;
3249 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3250 BlockStateAsString(xact->blockState));
3251 xact = xact->parent;
3252 Assert(PointerIsValid(xact));
3255 /* And mark the target as "restart pending" */
3256 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3257 xact->blockState = TBLOCK_SUBRESTART;
3258 else if (xact->blockState == TBLOCK_SUBABORT)
3259 xact->blockState = TBLOCK_SUBABORT_RESTART;
3261 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3262 BlockStateAsString(xact->blockState));
3266 * BeginInternalSubTransaction
3267 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3268 * state, and therefore it can safely be used in a function that might
3269 * be called when not inside a BEGIN block. Also, we automatically
3270 * cycle through CommitTransactionCommand/StartTransactionCommand
3271 * instead of expecting the caller to do it.
3274 BeginInternalSubTransaction(char *name)
3276 TransactionState s = CurrentTransactionState;
3278 switch (s->blockState)
3280 case TBLOCK_STARTED:
3281 case TBLOCK_INPROGRESS:
3282 case TBLOCK_SUBINPROGRESS:
3283 /* Normal subtransaction start */
3285 s = CurrentTransactionState; /* changed by push */
3288 * Savepoint names, like the TransactionState block itself,
3289 * live in TopTransactionContext.
3292 s->name = MemoryContextStrdup(TopTransactionContext, name);
3295 /* These cases are invalid. */
3296 case TBLOCK_DEFAULT:
3298 case TBLOCK_SUBBEGIN:
3302 case TBLOCK_SUBABORT:
3303 case TBLOCK_ABORT_END:
3304 case TBLOCK_SUBABORT_END:
3305 case TBLOCK_ABORT_PENDING:
3306 case TBLOCK_SUBABORT_PENDING:
3307 case TBLOCK_SUBRESTART:
3308 case TBLOCK_SUBABORT_RESTART:
3309 case TBLOCK_PREPARE:
3310 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3311 BlockStateAsString(s->blockState));
3315 CommitTransactionCommand();
3316 StartTransactionCommand();
3320 * ReleaseCurrentSubTransaction
3322 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3323 * savepoint name (if any).
3324 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3327 ReleaseCurrentSubTransaction(void)
3329 TransactionState s = CurrentTransactionState;
3331 if (s->blockState != TBLOCK_SUBINPROGRESS)
3332 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3333 BlockStateAsString(s->blockState));
3334 Assert(s->state == TRANS_INPROGRESS);
3335 MemoryContextSwitchTo(CurTransactionContext);
3336 CommitSubTransaction();
3337 s = CurrentTransactionState; /* changed by pop */
3338 Assert(s->state == TRANS_INPROGRESS);
3342 * RollbackAndReleaseCurrentSubTransaction
3344 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3345 * of its savepoint name (if any).
3346 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3349 RollbackAndReleaseCurrentSubTransaction(void)
3351 TransactionState s = CurrentTransactionState;
3353 switch (s->blockState)
3355 /* Must be in a subtransaction */
3356 case TBLOCK_SUBINPROGRESS:
3357 case TBLOCK_SUBABORT:
3360 /* These cases are invalid. */
3361 case TBLOCK_DEFAULT:
3362 case TBLOCK_STARTED:
3364 case TBLOCK_SUBBEGIN:
3365 case TBLOCK_INPROGRESS:
3369 case TBLOCK_ABORT_END:
3370 case TBLOCK_SUBABORT_END:
3371 case TBLOCK_ABORT_PENDING:
3372 case TBLOCK_SUBABORT_PENDING:
3373 case TBLOCK_SUBRESTART:
3374 case TBLOCK_SUBABORT_RESTART:
3375 case TBLOCK_PREPARE:
3376 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3377 BlockStateAsString(s->blockState));
3382 * Abort the current subtransaction, if needed.
3384 if (s->blockState == TBLOCK_SUBINPROGRESS)
3385 AbortSubTransaction();
3387 /* And clean it up, too */
3388 CleanupSubTransaction();
3390 s = CurrentTransactionState; /* changed by pop */
3391 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3392 s->blockState == TBLOCK_INPROGRESS ||
3393 s->blockState == TBLOCK_STARTED);
3397 * AbortOutOfAnyTransaction
3399 * This routine is provided for error recovery purposes. It aborts any
3400 * active transaction or transaction block, leaving the system in a known
3404 AbortOutOfAnyTransaction(void)
3406 TransactionState s = CurrentTransactionState;
3409 * Get out of any transaction or nested transaction
3413 switch (s->blockState)
3415 case TBLOCK_DEFAULT:
3416 /* Not in a transaction, do nothing */
3418 case TBLOCK_STARTED:
3420 case TBLOCK_INPROGRESS:
3422 case TBLOCK_ABORT_PENDING:
3423 case TBLOCK_PREPARE:
3424 /* In a transaction, so clean up */
3426 CleanupTransaction();
3427 s->blockState = TBLOCK_DEFAULT;
3430 case TBLOCK_ABORT_END:
3431 /* AbortTransaction already done, still need Cleanup */
3432 CleanupTransaction();
3433 s->blockState = TBLOCK_DEFAULT;
3437 * In a subtransaction, so clean it up and abort parent
3440 case TBLOCK_SUBBEGIN:
3441 case TBLOCK_SUBINPROGRESS:
3443 case TBLOCK_SUBABORT_PENDING:
3444 case TBLOCK_SUBRESTART:
3445 AbortSubTransaction();
3446 CleanupSubTransaction();
3447 s = CurrentTransactionState; /* changed by pop */
3450 case TBLOCK_SUBABORT:
3451 case TBLOCK_SUBABORT_END:
3452 case TBLOCK_SUBABORT_RESTART:
3453 /* As above, but AbortSubTransaction already done */
3454 CleanupSubTransaction();
3455 s = CurrentTransactionState; /* changed by pop */
3458 } while (s->blockState != TBLOCK_DEFAULT);
3460 /* Should be out of all subxacts now */
3461 Assert(s->parent == NULL);
3465 * IsTransactionBlock --- are we within a transaction block?
3468 IsTransactionBlock(void)
3470 TransactionState s = CurrentTransactionState;
3472 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3479 * IsTransactionOrTransactionBlock --- are we within either a transaction
3480 * or a transaction block? (The backend is only really "idle" when this
3483 * This should match up with IsTransactionBlock and IsTransactionState.
3486 IsTransactionOrTransactionBlock(void)
3488 TransactionState s = CurrentTransactionState;
3490 if (s->blockState == TBLOCK_DEFAULT)
3497 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3500 TransactionBlockStatusCode(void)
3502 TransactionState s = CurrentTransactionState;
3504 switch (s->blockState)
3506 case TBLOCK_DEFAULT:
3507 case TBLOCK_STARTED:
3508 return 'I'; /* idle --- not in transaction */
3510 case TBLOCK_SUBBEGIN:
3511 case TBLOCK_INPROGRESS:
3512 case TBLOCK_SUBINPROGRESS:
3515 case TBLOCK_PREPARE:
3516 return 'T'; /* in transaction */
3518 case TBLOCK_SUBABORT:
3519 case TBLOCK_ABORT_END:
3520 case TBLOCK_SUBABORT_END:
3521 case TBLOCK_ABORT_PENDING:
3522 case TBLOCK_SUBABORT_PENDING:
3523 case TBLOCK_SUBRESTART:
3524 case TBLOCK_SUBABORT_RESTART:
3525 return 'E'; /* in failed transaction */
3528 /* should never get here */
3529 elog(FATAL, "invalid transaction block state: %s",
3530 BlockStateAsString(s->blockState));
3531 return 0; /* keep compiler quiet */
3538 IsSubTransaction(void)
3540 TransactionState s = CurrentTransactionState;
3542 if (s->nestingLevel >= 2)
3549 * StartSubTransaction
3551 * If you're wondering why this is separate from PushTransaction: it's because
3552 * we can't conveniently do this stuff right inside DefineSavepoint. The
3553 * SAVEPOINT utility command will be executed inside a Portal, and if we
3554 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3555 * the Portal will undo those settings. So we make DefineSavepoint just
3556 * push a dummy transaction block, and when control returns to the main
3557 * idle loop, CommitTransactionCommand will be called, and we'll come here
3558 * to finish starting the subtransaction.
3561 StartSubTransaction(void)
3563 TransactionState s = CurrentTransactionState;
3565 if (s->state != TRANS_DEFAULT)
3566 elog(WARNING, "StartSubTransaction while in %s state",
3567 TransStateAsString(s->state));
3569 s->state = TRANS_START;
3572 * Initialize subsystems for new subtransaction
3574 * must initialize resource-management stuff first
3576 AtSubStart_Memory();
3577 AtSubStart_ResourceOwner();
3579 AtSubStart_Notify();
3580 AfterTriggerBeginSubXact();
3582 s->state = TRANS_INPROGRESS;
3585 * Call start-of-subxact callbacks
3587 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3588 s->parent->subTransactionId);
3590 ShowTransactionState("StartSubTransaction");
3594 * CommitSubTransaction
3596 * The caller has to make sure to always reassign CurrentTransactionState
3597 * if it has a local pointer to it after calling this function.
3600 CommitSubTransaction(void)
3602 TransactionState s = CurrentTransactionState;
3604 ShowTransactionState("CommitSubTransaction");
3606 if (s->state != TRANS_INPROGRESS)
3607 elog(WARNING, "CommitSubTransaction while in %s state",
3608 TransStateAsString(s->state));
3610 /* Pre-commit processing goes here -- nothing to do at the moment */
3612 s->state = TRANS_COMMIT;
3614 /* Must CCI to ensure commands of subtransaction are seen as done */
3615 CommandCounterIncrement();
3617 /* Mark subtransaction as subcommitted */
3618 if (TransactionIdIsValid(s->transactionId))
3620 RecordSubTransactionCommit();
3621 AtSubCommit_childXids();
3624 /* Post-commit cleanup */
3625 AfterTriggerEndSubXact(true);
3626 AtSubCommit_Portals(s->subTransactionId,
3627 s->parent->subTransactionId,
3628 s->parent->curTransactionOwner);
3629 AtEOSubXact_LargeObject(true, s->subTransactionId,
3630 s->parent->subTransactionId);
3631 AtSubCommit_Notify();
3632 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3633 s->parent->subTransactionId);
3635 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3636 s->parent->subTransactionId);
3638 ResourceOwnerRelease(s->curTransactionOwner,
3639 RESOURCE_RELEASE_BEFORE_LOCKS,
3641 AtEOSubXact_RelationCache(true, s->subTransactionId,
3642 s->parent->subTransactionId);
3643 AtEOSubXact_Inval(true);
3647 * The only lock we actually release here is the subtransaction XID lock.
3648 * The rest just get transferred to the parent resource owner.
3650 CurrentResourceOwner = s->curTransactionOwner;
3651 if (TransactionIdIsValid(s->transactionId))
3652 XactLockTableDelete(s->transactionId);
3654 ResourceOwnerRelease(s->curTransactionOwner,
3655 RESOURCE_RELEASE_LOCKS,
3657 ResourceOwnerRelease(s->curTransactionOwner,
3658 RESOURCE_RELEASE_AFTER_LOCKS,
3661 AtEOXact_GUC(true, true);
3662 AtEOSubXact_SPI(true, s->subTransactionId);
3663 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3664 s->parent->subTransactionId);
3665 AtEOSubXact_Namespace(true, s->subTransactionId,
3666 s->parent->subTransactionId);
3667 AtEOSubXact_Files(true, s->subTransactionId,
3668 s->parent->subTransactionId);
3671 * We need to restore the upper transaction's read-only state, in case
3672 * the upper is read-write while the child is read-only; GUC will
3673 * incorrectly think it should leave the child state in place.
3675 XactReadOnly = s->prevXactReadOnly;
3677 CurrentResourceOwner = s->parent->curTransactionOwner;
3678 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3679 ResourceOwnerDelete(s->curTransactionOwner);
3680 s->curTransactionOwner = NULL;
3682 AtSubCommit_Memory();
3684 s->state = TRANS_DEFAULT;
3690 * AbortSubTransaction
3693 AbortSubTransaction(void)
3695 TransactionState s = CurrentTransactionState;
3697 ShowTransactionState("AbortSubTransaction");
3699 if (s->state != TRANS_INPROGRESS)
3700 elog(WARNING, "AbortSubTransaction while in %s state",
3701 TransStateAsString(s->state));
3705 s->state = TRANS_ABORT;
3708 * Release any LW locks we might be holding as quickly as possible.
3709 * (Regular locks, however, must be held till we finish aborting.)
3710 * Releasing LW locks is critical since we might try to grab them
3711 * again while cleaning up!
3713 * FIXME This may be incorrect --- Are there some locks we should keep?
3714 * Buffer locks, for example? I don't think so but I'm not sure.
3724 * do abort processing
3726 AtSubAbort_Memory();
3727 AtSubAbort_ResourceOwner();
3730 * We can skip all this stuff if the subxact failed before creating
3731 * a ResourceOwner...
3733 if (s->curTransactionOwner)
3735 AfterTriggerEndSubXact(false);
3736 AtSubAbort_Portals(s->subTransactionId,
3737 s->parent->subTransactionId,
3738 s->parent->curTransactionOwner);
3739 AtEOSubXact_LargeObject(false, s->subTransactionId,
3740 s->parent->subTransactionId);
3741 AtSubAbort_Notify();
3742 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3743 s->parent->subTransactionId);
3745 /* Advertise the fact that we aborted in pg_clog. */
3746 if (TransactionIdIsValid(s->transactionId))
3748 RecordSubTransactionAbort();
3749 AtSubAbort_childXids();
3752 /* Post-abort cleanup */
3753 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3754 s->parent->subTransactionId);
3756 ResourceOwnerRelease(s->curTransactionOwner,
3757 RESOURCE_RELEASE_BEFORE_LOCKS,
3759 AtEOSubXact_RelationCache(false, s->subTransactionId,
3760 s->parent->subTransactionId);
3761 AtEOSubXact_Inval(false);
3763 ResourceOwnerRelease(s->curTransactionOwner,
3764 RESOURCE_RELEASE_LOCKS,
3766 ResourceOwnerRelease(s->curTransactionOwner,
3767 RESOURCE_RELEASE_AFTER_LOCKS,
3770 AtEOXact_GUC(false, true);
3771 AtEOSubXact_SPI(false, s->subTransactionId);
3772 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3773 s->parent->subTransactionId);
3774 AtEOSubXact_Namespace(false, s->subTransactionId,
3775 s->parent->subTransactionId);
3776 AtEOSubXact_Files(false, s->subTransactionId,
3777 s->parent->subTransactionId);
3781 * Reset user id which might have been changed transiently. Here we
3782 * want to restore to the userid that was current at subxact entry.
3783 * (As in AbortTransaction, we need not worry about the session
3786 * Must do this after AtEOXact_GUC to handle the case where we entered
3787 * the subxact inside a SECURITY DEFINER function (hence current and
3788 * session userids were different) and then session auth was changed
3789 * inside the subxact. GUC will reset both current and session
3790 * userids to the entry-time session userid. This is right in every
3791 * other scenario so it seems simplest to let GUC do that and fix it
3794 SetUserId(s->currentUser);
3797 * Restore the upper transaction's read-only state, too. This should
3798 * be redundant with GUC's cleanup but we may as well do it for
3799 * consistency with the commit case.
3801 XactReadOnly = s->prevXactReadOnly;
3803 RESUME_INTERRUPTS();
3807 * CleanupSubTransaction
3809 * The caller has to make sure to always reassign CurrentTransactionState
3810 * if it has a local pointer to it after calling this function.
3813 CleanupSubTransaction(void)
3815 TransactionState s = CurrentTransactionState;
3817 ShowTransactionState("CleanupSubTransaction");
3819 if (s->state != TRANS_ABORT)
3820 elog(WARNING, "CleanupSubTransaction while in %s state",
3821 TransStateAsString(s->state));
3823 AtSubCleanup_Portals(s->subTransactionId);
3825 CurrentResourceOwner = s->parent->curTransactionOwner;
3826 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3827 if (s->curTransactionOwner)
3828 ResourceOwnerDelete(s->curTransactionOwner);
3829 s->curTransactionOwner = NULL;
3831 AtSubCleanup_Memory();
3833 s->state = TRANS_DEFAULT;
3840 * Create transaction state stack entry for a subtransaction
3842 * The caller has to make sure to always reassign CurrentTransactionState
3843 * if it has a local pointer to it after calling this function.
3846 PushTransaction(void)
3848 TransactionState p = CurrentTransactionState;
3853 * At present, GetUserId cannot fail, but let's not assume that. Get
3854 * the ID before entering the critical code sequence.
3856 currentUser = GetUserId();
3859 * We keep subtransaction state nodes in TopTransactionContext.
3861 s = (TransactionState)
3862 MemoryContextAllocZero(TopTransactionContext,
3863 sizeof(TransactionStateData));
3865 * Assign a subtransaction ID, watching out for counter wraparound.
3867 currentSubTransactionId += 1;
3868 if (currentSubTransactionId == InvalidSubTransactionId)
3870 currentSubTransactionId -= 1;
3873 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3874 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3877 * We can now stack a minimally valid subtransaction without fear of
3880 s->transactionId = InvalidTransactionId; /* until assigned */
3881 s->subTransactionId = currentSubTransactionId;
3883 s->nestingLevel = p->nestingLevel + 1;
3884 s->savepointLevel = p->savepointLevel;
3885 s->state = TRANS_DEFAULT;
3886 s->blockState = TBLOCK_SUBBEGIN;
3887 s->currentUser = currentUser;
3888 s->prevXactReadOnly = XactReadOnly;
3890 CurrentTransactionState = s;
3893 * AbortSubTransaction and CleanupSubTransaction have to be able to
3894 * cope with the subtransaction from here on out; in particular they
3895 * should not assume that it necessarily has a transaction context,
3896 * resource owner, or XID.
3902 * Pop back to parent transaction state
3904 * The caller has to make sure to always reassign CurrentTransactionState
3905 * if it has a local pointer to it after calling this function.
3908 PopTransaction(void)
3910 TransactionState s = CurrentTransactionState;
3912 if (s->state != TRANS_DEFAULT)
3913 elog(WARNING, "PopTransaction while in %s state",
3914 TransStateAsString(s->state));
3916 if (s->parent == NULL)
3917 elog(FATAL, "PopTransaction with no parent");
3919 CurrentTransactionState = s->parent;
3921 /* Let's just make sure CurTransactionContext is good */
3922 CurTransactionContext = s->parent->curTransactionContext;
3923 MemoryContextSwitchTo(CurTransactionContext);
3925 /* Ditto for ResourceOwner links */
3926 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3927 CurrentResourceOwner = s->parent->curTransactionOwner;
3929 /* Free the old child structure */
3936 * ShowTransactionState
3940 ShowTransactionState(const char *str)
3942 /* skip work if message will definitely not be printed */
3943 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3945 elog(DEBUG3, "%s", str);
3946 ShowTransactionStateRec(CurrentTransactionState);
3951 * ShowTransactionStateRec
3952 * Recursive subroutine for ShowTransactionState
3955 ShowTransactionStateRec(TransactionState s)
3958 ShowTransactionStateRec(s->parent);
3960 /* use ereport to suppress computation if msg will not be printed */
3962 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3963 PointerIsValid(s->name) ? s->name : "unnamed",
3964 BlockStateAsString(s->blockState),
3965 TransStateAsString(s->state),
3966 (unsigned int) s->transactionId,
3967 (unsigned int) s->subTransactionId,
3968 (unsigned int) currentCommandId,
3970 nodeToString(s->childXids))));
3974 * BlockStateAsString
3978 BlockStateAsString(TBlockState blockState)
3982 case TBLOCK_DEFAULT:
3984 case TBLOCK_STARTED:
3988 case TBLOCK_INPROGRESS:
3989 return "INPROGRESS";
3994 case TBLOCK_ABORT_END:
3996 case TBLOCK_ABORT_PENDING:
3997 return "ABORT PEND";
3998 case TBLOCK_PREPARE:
4000 case TBLOCK_SUBBEGIN:
4002 case TBLOCK_SUBINPROGRESS:
4003 return "SUB INPROGRS";
4006 case TBLOCK_SUBABORT:
4008 case TBLOCK_SUBABORT_END:
4009 return "SUB ABORT END";
4010 case TBLOCK_SUBABORT_PENDING:
4011 return "SUB ABRT PEND";
4012 case TBLOCK_SUBRESTART:
4013 return "SUB RESTART";
4014 case TBLOCK_SUBABORT_RESTART:
4015 return "SUB AB RESTRT";
4017 return "UNRECOGNIZED";
4021 * TransStateAsString
4025 TransStateAsString(TransState state)
4033 case TRANS_INPROGRESS:
4042 return "UNRECOGNIZED";
4046 * xactGetCommittedChildren
4048 * Gets the list of committed children of the current transaction. The return
4049 * value is the number of child transactions. *children is set to point to a
4050 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4054 xactGetCommittedChildren(TransactionId **ptr)
4056 TransactionState s = CurrentTransactionState;
4058 TransactionId *children;
4061 nchildren = list_length(s->childXids);
4068 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4071 foreach(p, s->childXids)
4073 TransactionId child = lfirst_xid(p);
4075 *children++ = child;
4082 * XLOG support routines
4086 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4088 TransactionId *sub_xids;
4089 TransactionId max_xid;
4092 TransactionIdCommit(xid);
4094 /* Mark committed subtransactions as committed */
4095 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4096 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4098 /* Make sure nextXid is beyond any XID mentioned in the record */
4100 for (i = 0; i < xlrec->nsubxacts; i++)
4102 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4103 max_xid = sub_xids[i];
4105 if (TransactionIdFollowsOrEquals(max_xid,
4106 ShmemVariableCache->nextXid))
4108 ShmemVariableCache->nextXid = max_xid;
4109 TransactionIdAdvance(ShmemVariableCache->nextXid);
4112 /* Make sure files supposed to be dropped are dropped */
4113 for (i = 0; i < xlrec->nrels; i++)
4115 XLogCloseRelation(xlrec->xnodes[i]);
4116 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4121 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4123 TransactionId *sub_xids;
4124 TransactionId max_xid;
4127 TransactionIdAbort(xid);
4129 /* Mark subtransactions as aborted */
4130 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4131 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4133 /* Make sure nextXid is beyond any XID mentioned in the record */
4135 for (i = 0; i < xlrec->nsubxacts; i++)
4137 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4138 max_xid = sub_xids[i];
4140 if (TransactionIdFollowsOrEquals(max_xid,
4141 ShmemVariableCache->nextXid))
4143 ShmemVariableCache->nextXid = max_xid;
4144 TransactionIdAdvance(ShmemVariableCache->nextXid);
4147 /* Make sure files supposed to be dropped are dropped */
4148 for (i = 0; i < xlrec->nrels; i++)
4150 XLogCloseRelation(xlrec->xnodes[i]);
4151 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4156 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4158 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4160 if (info == XLOG_XACT_COMMIT)
4162 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4164 xact_redo_commit(xlrec, record->xl_xid);
4166 else if (info == XLOG_XACT_ABORT)
4168 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4170 xact_redo_abort(xlrec, record->xl_xid);
4172 else if (info == XLOG_XACT_PREPARE)
4174 /* the record contents are exactly the 2PC file */
4175 RecreateTwoPhaseFile(record->xl_xid,
4176 XLogRecGetData(record), record->xl_len);
4178 else if (info == XLOG_XACT_COMMIT_PREPARED)
4180 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4182 xact_redo_commit(&xlrec->crec, xlrec->xid);
4183 RemoveTwoPhaseFile(xlrec->xid, false);
4185 else if (info == XLOG_XACT_ABORT_PREPARED)
4187 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4189 xact_redo_abort(&xlrec->arec, xlrec->xid);
4190 RemoveTwoPhaseFile(xlrec->xid, false);
4193 elog(PANIC, "xact_redo: unknown op code %u", info);
4197 xact_desc_commit(char *buf, xl_xact_commit *xlrec)
4199 struct tm *tm = localtime(&xlrec->xtime);
4202 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4203 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4204 tm->tm_hour, tm->tm_min, tm->tm_sec);
4205 if (xlrec->nrels > 0)
4207 sprintf(buf + strlen(buf), "; rels:");
4208 for (i = 0; i < xlrec->nrels; i++)
4210 RelFileNode rnode = xlrec->xnodes[i];
4212 sprintf(buf + strlen(buf), " %u/%u/%u",
4213 rnode.spcNode, rnode.dbNode, rnode.relNode);
4216 if (xlrec->nsubxacts > 0)
4218 TransactionId *xacts = (TransactionId *)
4219 &xlrec->xnodes[xlrec->nrels];
4221 sprintf(buf + strlen(buf), "; subxacts:");
4222 for (i = 0; i < xlrec->nsubxacts; i++)
4223 sprintf(buf + strlen(buf), " %u", xacts[i]);
4228 xact_desc_abort(char *buf, xl_xact_abort *xlrec)
4230 struct tm *tm = localtime(&xlrec->xtime);
4233 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4234 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4235 tm->tm_hour, tm->tm_min, tm->tm_sec);
4236 if (xlrec->nrels > 0)
4238 sprintf(buf + strlen(buf), "; rels:");
4239 for (i = 0; i < xlrec->nrels; i++)
4241 RelFileNode rnode = xlrec->xnodes[i];
4243 sprintf(buf + strlen(buf), " %u/%u/%u",
4244 rnode.spcNode, rnode.dbNode, rnode.relNode);
4247 if (xlrec->nsubxacts > 0)
4249 TransactionId *xacts = (TransactionId *)
4250 &xlrec->xnodes[xlrec->nrels];
4252 sprintf(buf + strlen(buf), "; subxacts:");
4253 for (i = 0; i < xlrec->nsubxacts; i++)
4254 sprintf(buf + strlen(buf), " %u", xacts[i]);
4259 xact_desc(char *buf, uint8 xl_info, char *rec)
4261 uint8 info = xl_info & ~XLR_INFO_MASK;
4263 if (info == XLOG_XACT_COMMIT)
4265 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4267 strcat(buf, "commit: ");
4268 xact_desc_commit(buf, xlrec);
4270 else if (info == XLOG_XACT_ABORT)
4272 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4274 strcat(buf, "abort: ");
4275 xact_desc_abort(buf, xlrec);
4277 else if (info == XLOG_XACT_PREPARE)
4279 strcat(buf, "prepare");
4281 else if (info == XLOG_XACT_COMMIT_PREPARED)
4283 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4285 sprintf(buf + strlen(buf), "commit %u: ", xlrec->xid);
4286 xact_desc_commit(buf, &xlrec->crec);
4288 else if (info == XLOG_XACT_ABORT_PREPARED)
4290 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4292 sprintf(buf + strlen(buf), "abort %u: ", xlrec->xid);
4293 xact_desc_abort(buf, &xlrec->arec);
4296 strcat(buf, "UNKNOWN");