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.215 2005/10/15 02:49:09 momjian 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 context */
121 ResourceOwner curTransactionOwner; /* my query resources */
122 List *childXids; /* subcommitted child XIDs */
123 Oid currentUser; /* subxact start current_user */
124 bool prevXactReadOnly; /* entry-time xact r/o state */
125 struct TransactionStateData *parent; /* back link to parent */
126 } TransactionStateData;
128 typedef TransactionStateData *TransactionState;
131 * childXids is currently implemented as an Oid List, relying on the
132 * assumption that TransactionIds are no wider than Oid. We use these
133 * macros to provide some isolation in case that changes in the future.
135 #define lfirst_xid(lc) ((TransactionId) lfirst_oid(lc))
136 #define lappend_xid(list, datum) lappend_oid(list, (Oid) (datum))
139 * CurrentTransactionState always points to the current transaction state
140 * block. It will point to TopTransactionStateData when not in a
141 * transaction at all, or when in a top-level transaction.
143 static TransactionStateData TopTransactionStateData = {
144 0, /* transaction id */
145 0, /* subtransaction id */
146 NULL, /* savepoint name */
147 0, /* savepoint level */
148 TRANS_DEFAULT, /* transaction state */
149 TBLOCK_DEFAULT, /* transaction block state from the client
151 0, /* nesting level */
152 NULL, /* cur transaction context */
153 NULL, /* cur transaction resource owner */
154 NIL, /* subcommitted child Xids */
155 0, /* entry-time current userid */
156 false, /* entry-time xact r/o state */
157 NULL /* link to parent state block */
160 static TransactionState CurrentTransactionState = &TopTransactionStateData;
163 * The subtransaction ID and command ID assignment counters are global
164 * to a whole transaction, so we do not keep them in the state stack.
166 static SubTransactionId currentSubTransactionId;
167 static CommandId currentCommandId;
170 * This is the value of now(), ie, the transaction start time.
171 * This does not change as we enter and exit subtransactions, so we don't
172 * keep it inside the TransactionState stack.
174 static TimestampTz xactStartTimestamp;
177 * GID to be used for preparing the current transaction. This is also
178 * global to a whole transaction, so we don't keep it in the state stack.
180 static char *prepareGID;
184 * List of add-on start- and end-of-xact callbacks
186 typedef struct XactCallbackItem
188 struct XactCallbackItem *next;
189 XactCallback callback;
193 static XactCallbackItem *Xact_callbacks = NULL;
196 * List of add-on start- and end-of-subxact callbacks
198 typedef struct SubXactCallbackItem
200 struct SubXactCallbackItem *next;
201 SubXactCallback callback;
203 } SubXactCallbackItem;
205 static SubXactCallbackItem *SubXact_callbacks = NULL;
208 /* local function prototypes */
209 static void AssignSubTransactionId(TransactionState s);
210 static void AbortTransaction(void);
211 static void AtAbort_Memory(void);
212 static void AtCleanup_Memory(void);
213 static void AtAbort_ResourceOwner(void);
214 static void AtCommit_LocalCache(void);
215 static void AtCommit_Memory(void);
216 static void AtStart_Cache(void);
217 static void AtStart_Memory(void);
218 static void AtStart_ResourceOwner(void);
219 static void CallXactCallbacks(XactEvent event);
220 static void CallSubXactCallbacks(SubXactEvent event,
221 SubTransactionId mySubid,
222 SubTransactionId parentSubid);
223 static void CleanupTransaction(void);
224 static void CommitTransaction(void);
225 static void RecordTransactionAbort(void);
226 static void StartTransaction(void);
228 static void RecordSubTransactionCommit(void);
229 static void StartSubTransaction(void);
230 static void CommitSubTransaction(void);
231 static void AbortSubTransaction(void);
232 static void CleanupSubTransaction(void);
233 static void PushTransaction(void);
234 static void PopTransaction(void);
236 static void AtSubAbort_Memory(void);
237 static void AtSubCleanup_Memory(void);
238 static void AtSubAbort_ResourceOwner(void);
239 static void AtSubCommit_Memory(void);
240 static void AtSubStart_Memory(void);
241 static void AtSubStart_ResourceOwner(void);
243 static void ShowTransactionState(const char *str);
244 static void ShowTransactionStateRec(TransactionState state);
245 static const char *BlockStateAsString(TBlockState blockState);
246 static const char *TransStateAsString(TransState state);
249 /* ----------------------------------------------------------------
250 * transaction state accessors
251 * ----------------------------------------------------------------
257 * This returns true if we are currently running a query
258 * within an executing transaction.
261 IsTransactionState(void)
263 TransactionState s = CurrentTransactionState;
271 case TRANS_INPROGRESS:
282 * Shouldn't get here, but lint is not happy without this...
288 * IsAbortedTransactionBlockState
290 * This returns true if we are currently running a query
291 * within an aborted transaction block.
294 IsAbortedTransactionBlockState(void)
296 TransactionState s = CurrentTransactionState;
298 if (s->blockState == TBLOCK_ABORT ||
299 s->blockState == TBLOCK_SUBABORT)
307 * GetTopTransactionId
309 * Get the ID of the main transaction, even if we are currently inside
313 GetTopTransactionId(void)
315 return TopTransactionStateData.transactionId;
320 * GetCurrentTransactionId
322 * We do not assign XIDs to subtransactions until/unless this is called.
323 * When we do assign an XID to a subtransaction, recursively make sure
324 * its parent has one as well (this maintains the invariant that a child
325 * transaction has an XID following its parent's).
328 GetCurrentTransactionId(void)
330 TransactionState s = CurrentTransactionState;
332 if (!TransactionIdIsValid(s->transactionId))
333 AssignSubTransactionId(s);
335 return s->transactionId;
339 AssignSubTransactionId(TransactionState s)
341 ResourceOwner currentOwner;
343 Assert(s->parent != NULL);
344 Assert(s->state == TRANS_INPROGRESS);
345 if (!TransactionIdIsValid(s->parent->transactionId))
346 AssignSubTransactionId(s->parent);
349 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
351 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
352 * shared storage other than PG_PROC; because if there's no room for it in
353 * PG_PROC, the subtrans entry is needed to ensure that other backends see
354 * the Xid as "running". See GetNewTransactionId.
356 s->transactionId = GetNewTransactionId(true);
358 SubTransSetParent(s->transactionId, s->parent->transactionId);
361 * Acquire lock on the transaction XID. (We assume this cannot block.) We
362 * have to be sure that the lock is assigned to the transaction's
365 currentOwner = CurrentResourceOwner;
368 CurrentResourceOwner = s->curTransactionOwner;
370 XactLockTableInsert(s->transactionId);
374 /* Ensure CurrentResourceOwner is restored on error */
375 CurrentResourceOwner = currentOwner;
379 CurrentResourceOwner = currentOwner;
384 * GetCurrentTransactionIdIfAny
386 * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
387 * if we are currently not in a transaction, or in a transaction or
388 * subtransaction that has not yet assigned itself an XID.
391 GetCurrentTransactionIdIfAny(void)
393 TransactionState s = CurrentTransactionState;
395 return s->transactionId;
400 * GetCurrentSubTransactionId
403 GetCurrentSubTransactionId(void)
405 TransactionState s = CurrentTransactionState;
407 return s->subTransactionId;
412 * GetCurrentCommandId
415 GetCurrentCommandId(void)
417 /* this is global to a transaction, not subtransaction-local */
418 return currentCommandId;
422 * GetCurrentTransactionStartTimestamp
425 GetCurrentTransactionStartTimestamp(void)
427 return xactStartTimestamp;
431 * GetCurrentTransactionNestLevel
433 * Note: this will return zero when not inside any transaction, one when
434 * inside a top-level transaction, etc.
437 GetCurrentTransactionNestLevel(void)
439 TransactionState s = CurrentTransactionState;
441 return s->nestingLevel;
446 * TransactionIdIsCurrentTransactionId
449 TransactionIdIsCurrentTransactionId(TransactionId xid)
454 * We always say that BootstrapTransactionId is "not my transaction ID"
455 * even when it is (ie, during bootstrap). Along with the fact that
456 * transam.c always treats BootstrapTransactionId as already committed,
457 * this causes the tqual.c routines to see all tuples as committed, which
458 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
459 * it never updates or deletes them, so all tuples can be presumed good
462 if (xid == BootstrapTransactionId)
466 * We will return true for the Xid of the current subtransaction, any of
467 * its subcommitted children, any of its parents, or any of their
468 * previously subcommitted children. However, a transaction being aborted
469 * is no longer "current", even though it may still have an entry on the
472 for (s = CurrentTransactionState; s != NULL; s = s->parent)
476 if (s->state == TRANS_ABORT)
478 if (!TransactionIdIsValid(s->transactionId))
479 continue; /* it can't have any child XIDs either */
480 if (TransactionIdEquals(xid, s->transactionId))
482 foreach(cell, s->childXids)
484 if (TransactionIdEquals(xid, lfirst_xid(cell)))
494 * CommandCounterIncrement
497 CommandCounterIncrement(void)
499 currentCommandId += 1;
500 if (currentCommandId == FirstCommandId) /* check for overflow */
502 currentCommandId -= 1;
504 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
505 errmsg("cannot have more than 2^32-1 commands in a transaction")));
508 /* Propagate new command ID into static snapshots, if set */
509 if (SerializableSnapshot)
510 SerializableSnapshot->curcid = currentCommandId;
512 LatestSnapshot->curcid = currentCommandId;
515 * make cache changes visible to me.
517 AtCommit_LocalCache();
522 /* ----------------------------------------------------------------
523 * StartTransaction stuff
524 * ----------------------------------------------------------------
533 AcceptInvalidationMessages();
542 TransactionState s = CurrentTransactionState;
545 * We shouldn't have a transaction context already.
547 Assert(TopTransactionContext == NULL);
550 * Create a toplevel context for the transaction.
552 TopTransactionContext =
553 AllocSetContextCreate(TopMemoryContext,
554 "TopTransactionContext",
555 ALLOCSET_DEFAULT_MINSIZE,
556 ALLOCSET_DEFAULT_INITSIZE,
557 ALLOCSET_DEFAULT_MAXSIZE);
560 * In a top-level transaction, CurTransactionContext is the same as
561 * TopTransactionContext.
563 CurTransactionContext = TopTransactionContext;
564 s->curTransactionContext = CurTransactionContext;
566 /* Make the CurTransactionContext active. */
567 MemoryContextSwitchTo(CurTransactionContext);
571 * AtStart_ResourceOwner
574 AtStart_ResourceOwner(void)
576 TransactionState s = CurrentTransactionState;
579 * We shouldn't have a transaction resource owner already.
581 Assert(TopTransactionResourceOwner == NULL);
584 * Create a toplevel resource owner for the transaction.
586 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
588 TopTransactionResourceOwner = s->curTransactionOwner;
589 CurTransactionResourceOwner = s->curTransactionOwner;
590 CurrentResourceOwner = s->curTransactionOwner;
593 /* ----------------------------------------------------------------
594 * StartSubTransaction stuff
595 * ----------------------------------------------------------------
602 AtSubStart_Memory(void)
604 TransactionState s = CurrentTransactionState;
606 Assert(CurTransactionContext != NULL);
609 * Create a CurTransactionContext, which will be used to hold data that
610 * survives subtransaction commit but disappears on subtransaction abort.
611 * We make it a child of the immediate parent's CurTransactionContext.
613 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
614 "CurTransactionContext",
615 ALLOCSET_DEFAULT_MINSIZE,
616 ALLOCSET_DEFAULT_INITSIZE,
617 ALLOCSET_DEFAULT_MAXSIZE);
618 s->curTransactionContext = CurTransactionContext;
620 /* Make the CurTransactionContext active. */
621 MemoryContextSwitchTo(CurTransactionContext);
625 * AtSubStart_ResourceOwner
628 AtSubStart_ResourceOwner(void)
630 TransactionState s = CurrentTransactionState;
632 Assert(s->parent != NULL);
635 * Create a resource owner for the subtransaction. We make it a child of
636 * the immediate parent's resource owner.
638 s->curTransactionOwner =
639 ResourceOwnerCreate(s->parent->curTransactionOwner,
642 CurTransactionResourceOwner = s->curTransactionOwner;
643 CurrentResourceOwner = s->curTransactionOwner;
646 /* ----------------------------------------------------------------
647 * CommitTransaction stuff
648 * ----------------------------------------------------------------
652 * RecordTransactionCommit
655 RecordTransactionCommit(void)
660 TransactionId *children;
662 /* Get data needed for commit record */
663 nrels = smgrGetPendingDeletes(true, &rels);
664 nchildren = xactGetCommittedChildren(&children);
667 * If we made neither any XLOG entries nor any temp-rel updates, and have
668 * no files to be deleted, we can omit recording the transaction commit at
669 * all. (This test includes the effects of subtransactions, so the
670 * presence of committed subxacts need not alone force a write.)
672 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
674 TransactionId xid = GetCurrentTransactionId();
678 /* Tell bufmgr and smgr to prepare for commit */
681 START_CRIT_SECTION();
684 * If our transaction made any transaction-controlled XLOG entries, we
685 * need to lock out checkpoint start between writing our XLOG record
686 * and updating pg_clog. Otherwise it is possible for the checkpoint
687 * to set REDO after the XLOG record but fail to flush the pg_clog
688 * update to disk, leading to loss of the transaction commit if we
689 * crash a little later. Slightly klugy fix for problem discovered
692 * (If it made no transaction-controlled XLOG entries, its XID appears
693 * nowhere in permanent storage, so no one else will ever care if it
694 * committed; so it doesn't matter if we lose the commit flag.)
696 * Note we only need a shared lock.
698 madeTCentries = (MyLastRecPtr.xrecoff != 0);
700 LWLockAcquire(CheckpointStartLock, LW_SHARED);
703 * We only need to log the commit in XLOG if the transaction made any
704 * transaction-controlled XLOG entries or will delete files.
706 if (madeTCentries || nrels > 0)
708 XLogRecData rdata[3];
710 xl_xact_commit xlrec;
712 xlrec.xtime = time(NULL);
714 xlrec.nsubxacts = nchildren;
715 rdata[0].data = (char *) (&xlrec);
716 rdata[0].len = MinSizeOfXactCommit;
717 rdata[0].buffer = InvalidBuffer;
718 /* dump rels to delete */
721 rdata[0].next = &(rdata[1]);
722 rdata[1].data = (char *) rels;
723 rdata[1].len = nrels * sizeof(RelFileNode);
724 rdata[1].buffer = InvalidBuffer;
727 /* dump committed child Xids */
730 rdata[lastrdata].next = &(rdata[2]);
731 rdata[2].data = (char *) children;
732 rdata[2].len = nchildren * sizeof(TransactionId);
733 rdata[2].buffer = InvalidBuffer;
736 rdata[lastrdata].next = NULL;
738 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
742 /* Just flush through last record written by me */
743 recptr = ProcLastRecEnd;
747 * We must flush our XLOG entries to disk if we made any XLOG entries,
748 * whether in or out of transaction control. For example, if we
749 * reported a nextval() result to the client, this ensures that any
750 * XLOG record generated by nextval will hit the disk before we report
751 * the transaction committed.
753 * Note: if we generated a commit record above, MyXactMadeXLogEntry will
754 * certainly be set now.
756 if (MyXactMadeXLogEntry)
759 * Sleep before flush! So we can flush more than one commit
760 * records per single fsync. (The idea is some other backend may
761 * do the XLogFlush while we're sleeping. This needs work still,
762 * because on most Unixen, the minimum select() delay is 10msec or
763 * more, which is way too long.)
765 * We do not sleep if enableFsync is not turned on, nor if there are
766 * fewer than CommitSiblings other backends with active
769 if (CommitDelay > 0 && enableFsync &&
770 CountActiveBackends() >= CommitSiblings)
771 pg_usleep(CommitDelay);
777 * We must mark the transaction committed in clog if its XID appears
778 * either in permanent rels or in local temporary rels. We test this
779 * by seeing if we made transaction-controlled entries *OR* local-rel
780 * tuple updates. Note that if we made only the latter, we have not
781 * emitted an XLOG record for our commit, and so in the event of a
782 * crash the clog update might be lost. This is okay because no one
783 * else will ever care whether we committed.
785 if (madeTCentries || MyXactMadeTempRelUpdate)
787 TransactionIdCommit(xid);
788 /* to avoid race conditions, the parent must commit first */
789 TransactionIdCommitTree(nchildren, children);
792 /* Unlock checkpoint lock if we acquired it */
794 LWLockRelease(CheckpointStartLock);
799 /* Break the chain of back-links in the XLOG records I output */
800 MyLastRecPtr.xrecoff = 0;
801 MyXactMadeXLogEntry = false;
802 MyXactMadeTempRelUpdate = false;
804 /* And clean up local data */
813 * AtCommit_LocalCache
816 AtCommit_LocalCache(void)
819 * Make catalog changes visible to me for the next command.
821 CommandEndInvalidationMessages();
828 AtCommit_Memory(void)
831 * Now that we're "out" of a transaction, have the system allocate things
832 * in the top memory context instead of per-transaction contexts.
834 MemoryContextSwitchTo(TopMemoryContext);
837 * Release all transaction-local memory.
839 Assert(TopTransactionContext != NULL);
840 MemoryContextDelete(TopTransactionContext);
841 TopTransactionContext = NULL;
842 CurTransactionContext = NULL;
843 CurrentTransactionState->curTransactionContext = NULL;
846 /* ----------------------------------------------------------------
847 * CommitSubTransaction stuff
848 * ----------------------------------------------------------------
855 AtSubCommit_Memory(void)
857 TransactionState s = CurrentTransactionState;
859 Assert(s->parent != NULL);
861 /* Return to parent transaction level's memory context. */
862 CurTransactionContext = s->parent->curTransactionContext;
863 MemoryContextSwitchTo(CurTransactionContext);
866 * Ordinarily we cannot throw away the child's CurTransactionContext,
867 * since the data it contains will be needed at upper commit. However, if
868 * there isn't actually anything in it, we can throw it away. This avoids
869 * a small memory leak in the common case of "trivial" subxacts.
871 if (MemoryContextIsEmpty(s->curTransactionContext))
873 MemoryContextDelete(s->curTransactionContext);
874 s->curTransactionContext = NULL;
879 * AtSubCommit_childXids
881 * Pass my own XID and my child XIDs up to my parent as committed children.
884 AtSubCommit_childXids(void)
886 TransactionState s = CurrentTransactionState;
887 MemoryContext old_cxt;
889 Assert(s->parent != NULL);
892 * We keep the child-XID lists in TopTransactionContext; this avoids
893 * setting up child-transaction contexts for what might be just a few
894 * bytes of grandchild XIDs.
896 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
898 s->parent->childXids = lappend_xid(s->parent->childXids,
901 if (s->childXids != NIL)
903 s->parent->childXids = list_concat(s->parent->childXids,
907 * list_concat doesn't free the list header for the second list; do so
908 * here to avoid memory leakage (kluge)
914 MemoryContextSwitchTo(old_cxt);
918 * RecordSubTransactionCommit
921 RecordSubTransactionCommit(void)
924 * We do not log the subcommit in XLOG; it doesn't matter until the
925 * top-level transaction commits.
927 * We must mark the subtransaction subcommitted in clog if its XID appears
928 * either in permanent rels or in local temporary rels. We test this by
929 * seeing if we made transaction-controlled entries *OR* local-rel tuple
930 * updates. (The test here actually covers the entire transaction tree so
931 * far, so it may mark subtransactions that don't really need it, but it's
932 * probably not worth being tenser. Note that if a prior subtransaction
933 * dirtied these variables, then RecordTransactionCommit will have to do
934 * the full pushup anyway...)
936 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
938 TransactionId xid = GetCurrentTransactionId();
940 /* XXX does this really need to be a critical section? */
941 START_CRIT_SECTION();
943 /* Record subtransaction subcommit */
944 TransactionIdSubCommit(xid);
950 /* ----------------------------------------------------------------
951 * AbortTransaction stuff
952 * ----------------------------------------------------------------
956 * RecordTransactionAbort
959 RecordTransactionAbort(void)
964 TransactionId *children;
966 /* Get data needed for abort record */
967 nrels = smgrGetPendingDeletes(false, &rels);
968 nchildren = xactGetCommittedChildren(&children);
971 * If we made neither any transaction-controlled XLOG entries nor any
972 * temp-rel updates, and are not going to delete any files, we can omit
973 * recording the transaction abort at all. No one will ever care that it
974 * aborted. (These tests cover our whole transaction tree.)
976 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
978 TransactionId xid = GetCurrentTransactionId();
981 * Catch the scenario where we aborted partway through
982 * RecordTransactionCommit ...
984 if (TransactionIdDidCommit(xid))
985 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
987 START_CRIT_SECTION();
990 * We only need to log the abort in XLOG if the transaction made any
991 * transaction-controlled XLOG entries or will delete files. (If it
992 * made no transaction-controlled XLOG entries, its XID appears
993 * nowhere in permanent storage, so no one else will ever care if it
996 * We do not flush XLOG to disk unless deleting files, since the default
997 * assumption after a crash would be that we aborted, anyway. For the
998 * same reason, we don't need to worry about interlocking against
1001 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1003 XLogRecData rdata[3];
1005 xl_xact_abort xlrec;
1008 xlrec.xtime = time(NULL);
1009 xlrec.nrels = nrels;
1010 xlrec.nsubxacts = nchildren;
1011 rdata[0].data = (char *) (&xlrec);
1012 rdata[0].len = MinSizeOfXactAbort;
1013 rdata[0].buffer = InvalidBuffer;
1014 /* dump rels to delete */
1017 rdata[0].next = &(rdata[1]);
1018 rdata[1].data = (char *) rels;
1019 rdata[1].len = nrels * sizeof(RelFileNode);
1020 rdata[1].buffer = InvalidBuffer;
1023 /* dump committed child Xids */
1026 rdata[lastrdata].next = &(rdata[2]);
1027 rdata[2].data = (char *) children;
1028 rdata[2].len = nchildren * sizeof(TransactionId);
1029 rdata[2].buffer = InvalidBuffer;
1032 rdata[lastrdata].next = NULL;
1034 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1036 /* Must flush if we are deleting files... */
1042 * Mark the transaction aborted in clog. This is not absolutely
1043 * necessary but we may as well do it while we are here.
1045 * The ordering here isn't critical but it seems best to mark the parent
1046 * first. This assures an atomic transition of all the
1047 * subtransactions to aborted state from the point of view of
1048 * concurrent TransactionIdDidAbort calls.
1050 TransactionIdAbort(xid);
1051 TransactionIdAbortTree(nchildren, children);
1056 /* Break the chain of back-links in the XLOG records I output */
1057 MyLastRecPtr.xrecoff = 0;
1058 MyXactMadeXLogEntry = false;
1059 MyXactMadeTempRelUpdate = false;
1061 /* And clean up local data */
1072 AtAbort_Memory(void)
1075 * Make sure we are in a valid context (not a child of
1076 * TopTransactionContext...). Note that it is possible for this code to
1077 * be called when we aren't in a transaction at all; go directly to
1078 * TopMemoryContext in that case.
1080 if (TopTransactionContext != NULL)
1082 MemoryContextSwitchTo(TopTransactionContext);
1085 * We do not want to destroy the transaction's global state yet, so we
1086 * can't free any memory here.
1090 MemoryContextSwitchTo(TopMemoryContext);
1097 AtSubAbort_Memory(void)
1099 Assert(TopTransactionContext != NULL);
1101 MemoryContextSwitchTo(TopTransactionContext);
1106 * AtAbort_ResourceOwner
1109 AtAbort_ResourceOwner(void)
1112 * Make sure we have a valid ResourceOwner, if possible (else it will be
1113 * NULL, which is OK)
1115 CurrentResourceOwner = TopTransactionResourceOwner;
1119 * AtSubAbort_ResourceOwner
1122 AtSubAbort_ResourceOwner(void)
1124 TransactionState s = CurrentTransactionState;
1126 /* Make sure we have a valid ResourceOwner */
1127 CurrentResourceOwner = s->curTransactionOwner;
1132 * AtSubAbort_childXids
1135 AtSubAbort_childXids(void)
1137 TransactionState s = CurrentTransactionState;
1140 * We keep the child-XID lists in TopTransactionContext (see
1141 * AtSubCommit_childXids). This means we'd better free the list
1142 * explicitly at abort to avoid leakage.
1144 list_free(s->childXids);
1149 * RecordSubTransactionAbort
1152 RecordSubTransactionAbort(void)
1156 TransactionId xid = GetCurrentTransactionId();
1158 TransactionId *children;
1160 /* Get data needed for abort record */
1161 nrels = smgrGetPendingDeletes(false, &rels);
1162 nchildren = xactGetCommittedChildren(&children);
1165 * If we made neither any transaction-controlled XLOG entries nor any
1166 * temp-rel updates, and are not going to delete any files, we can omit
1167 * recording the transaction abort at all. No one will ever care that it
1168 * aborted. (These tests cover our whole transaction tree, and therefore
1169 * may mark subxacts that don't really need it, but it's probably not
1170 * worth being tenser.)
1172 * In this case we needn't worry about marking subcommitted children as
1173 * aborted, because they didn't mark themselves as subcommitted in the
1174 * first place; see the optimization in RecordSubTransactionCommit.
1176 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1178 START_CRIT_SECTION();
1181 * We only need to log the abort in XLOG if the transaction made any
1182 * transaction-controlled XLOG entries or will delete files.
1184 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1186 XLogRecData rdata[3];
1188 xl_xact_abort xlrec;
1191 xlrec.xtime = time(NULL);
1192 xlrec.nrels = nrels;
1193 xlrec.nsubxacts = nchildren;
1194 rdata[0].data = (char *) (&xlrec);
1195 rdata[0].len = MinSizeOfXactAbort;
1196 rdata[0].buffer = InvalidBuffer;
1197 /* dump rels to delete */
1200 rdata[0].next = &(rdata[1]);
1201 rdata[1].data = (char *) rels;
1202 rdata[1].len = nrels * sizeof(RelFileNode);
1203 rdata[1].buffer = InvalidBuffer;
1206 /* dump committed child Xids */
1209 rdata[lastrdata].next = &(rdata[2]);
1210 rdata[2].data = (char *) children;
1211 rdata[2].len = nchildren * sizeof(TransactionId);
1212 rdata[2].buffer = InvalidBuffer;
1215 rdata[lastrdata].next = NULL;
1217 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1219 /* Must flush if we are deleting files... */
1225 * Mark the transaction aborted in clog. This is not absolutely
1226 * necessary but XactLockTableWait makes use of it to avoid waiting
1227 * for already-aborted subtransactions.
1229 TransactionIdAbort(xid);
1230 TransactionIdAbortTree(nchildren, children);
1236 * We can immediately remove failed XIDs from PGPROC's cache of running
1237 * child XIDs. It's easiest to do it here while we have the child XID
1238 * array at hand, even though in the main-transaction case the equivalent
1239 * work happens just after return from RecordTransactionAbort.
1241 XidCacheRemoveRunningXids(xid, nchildren, children);
1243 /* And clean up local data */
1250 /* ----------------------------------------------------------------
1251 * CleanupTransaction stuff
1252 * ----------------------------------------------------------------
1259 AtCleanup_Memory(void)
1262 * Now that we're "out" of a transaction, have the system allocate things
1263 * in the top memory context instead of per-transaction contexts.
1265 MemoryContextSwitchTo(TopMemoryContext);
1267 Assert(CurrentTransactionState->parent == NULL);
1270 * Release all transaction-local memory.
1272 if (TopTransactionContext != NULL)
1273 MemoryContextDelete(TopTransactionContext);
1274 TopTransactionContext = NULL;
1275 CurTransactionContext = NULL;
1276 CurrentTransactionState->curTransactionContext = NULL;
1280 /* ----------------------------------------------------------------
1281 * CleanupSubTransaction stuff
1282 * ----------------------------------------------------------------
1286 * AtSubCleanup_Memory
1289 AtSubCleanup_Memory(void)
1291 TransactionState s = CurrentTransactionState;
1293 Assert(s->parent != NULL);
1295 /* Make sure we're not in an about-to-be-deleted context */
1296 MemoryContextSwitchTo(s->parent->curTransactionContext);
1297 CurTransactionContext = s->parent->curTransactionContext;
1300 * Delete the subxact local memory contexts. Its CurTransactionContext can
1301 * go too (note this also kills CurTransactionContexts from any children
1304 if (s->curTransactionContext)
1305 MemoryContextDelete(s->curTransactionContext);
1306 s->curTransactionContext = NULL;
1309 /* ----------------------------------------------------------------
1310 * interface routines
1311 * ----------------------------------------------------------------
1318 StartTransaction(void)
1323 * Let's just make sure the state stack is empty
1325 s = &TopTransactionStateData;
1326 CurrentTransactionState = s;
1329 * check the current transaction state
1331 if (s->state != TRANS_DEFAULT)
1332 elog(WARNING, "StartTransaction while in %s state",
1333 TransStateAsString(s->state));
1336 * set the current transaction state information appropriately during
1339 s->state = TRANS_START;
1340 s->transactionId = InvalidTransactionId; /* until assigned */
1343 * Make sure we've freed any old snapshot, and reset xact state variables
1346 XactIsoLevel = DefaultXactIsoLevel;
1347 XactReadOnly = DefaultXactReadOnly;
1350 * reinitialize within-transaction counters
1352 s->subTransactionId = TopSubTransactionId;
1353 currentSubTransactionId = TopSubTransactionId;
1354 currentCommandId = FirstCommandId;
1357 * must initialize resource-management stuff first
1360 AtStart_ResourceOwner();
1363 * generate a new transaction id
1365 s->transactionId = GetNewTransactionId(false);
1367 XactLockTableInsert(s->transactionId);
1372 xactStartTimestamp = GetCurrentTimestamp();
1375 * initialize current transaction state fields
1377 s->nestingLevel = 1;
1381 * You might expect to see "s->currentUser = GetUserId();" here, but you
1382 * won't because it doesn't work during startup; the userid isn't set yet
1383 * during a backend's first transaction start. We only use the
1384 * currentUser field in sub-transaction state structs.
1386 * prevXactReadOnly is also valid only in sub-transactions.
1390 * initialize other subsystems for new transaction
1394 AfterTriggerBeginXact();
1397 * done with start processing, set current transaction state to "in
1400 s->state = TRANS_INPROGRESS;
1402 ShowTransactionState("StartTransaction");
1409 * NB: if you change this routine, better look at PrepareTransaction too!
1412 CommitTransaction(void)
1414 TransactionState s = CurrentTransactionState;
1416 ShowTransactionState("CommitTransaction");
1419 * check the current transaction state
1421 if (s->state != TRANS_INPROGRESS)
1422 elog(WARNING, "CommitTransaction while in %s state",
1423 TransStateAsString(s->state));
1424 Assert(s->parent == NULL);
1427 * Do pre-commit processing (most of this stuff requires database access,
1428 * and in fact could still cause an error...)
1430 * It is possible for CommitHoldablePortals to invoke functions that queue
1431 * deferred triggers, and it's also possible that triggers create holdable
1432 * cursors. So we have to loop until there's nothing left to do.
1437 * Fire all currently pending deferred triggers.
1439 AfterTriggerFireDeferred();
1442 * Convert any open holdable cursors into static portals. If there
1443 * weren't any, we are done ... otherwise loop back to check if they
1444 * queued deferred triggers. Lather, rinse, repeat.
1446 if (!CommitHoldablePortals())
1450 /* Now we can shut down the deferred-trigger manager */
1451 AfterTriggerEndXact(true);
1453 /* Close any open regular cursors */
1457 * Let ON COMMIT management do its thing (must happen after closing
1458 * cursors, to avoid dangling-reference problems)
1460 PreCommit_on_commit_actions();
1462 /* close large objects before lower-level cleanup */
1463 AtEOXact_LargeObject(true);
1465 /* NOTIFY commit must come before lower-level cleanup */
1469 * Update flat files if we changed pg_database, pg_authid or
1470 * pg_auth_members. This should be the last step before commit.
1472 AtEOXact_UpdateFlatFiles(true);
1474 /* Prevent cancel/die interrupt while cleaning up */
1478 * set the current transaction state information appropriately during
1481 s->state = TRANS_COMMIT;
1484 * Here is where we really truly commit.
1486 RecordTransactionCommit();
1489 * Let others know about no transaction in progress by me. Note that
1490 * this must be done _before_ releasing locks we hold and _after_
1491 * RecordTransactionCommit.
1493 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1494 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1495 * xid 1 is doing commit while xid 2 gets snapshot.
1496 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1497 * xid 0 as running as well, or it will be able to see two tuple versions
1498 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1501 * Note: MyProc may be null during bootstrap.
1506 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1507 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1508 MyProc->xid = InvalidTransactionId;
1509 MyProc->xmin = InvalidTransactionId;
1511 /* Clear the subtransaction-XID cache too while holding the lock */
1512 MyProc->subxids.nxids = 0;
1513 MyProc->subxids.overflowed = false;
1515 LWLockRelease(ProcArrayLock);
1519 * This is all post-commit cleanup. Note that if an error is raised here,
1520 * it's too late to abort the transaction. This should be just
1521 * noncritical resource releasing.
1523 * The ordering of operations is not entirely random. The idea is: release
1524 * resources visible to other backends (eg, files, buffer pins); then
1525 * release locks; then release backend-local resources. We want to release
1526 * locks at the point where any backend waiting for us will see our
1527 * transaction as being fully cleaned up.
1529 * Resources that can be associated with individual queries are handled by
1530 * the ResourceOwner mechanism. The other calls here are for backend-wide
1534 CallXactCallbacks(XACT_EVENT_COMMIT);
1536 ResourceOwnerRelease(TopTransactionResourceOwner,
1537 RESOURCE_RELEASE_BEFORE_LOCKS,
1540 /* Check we've released all buffer pins */
1541 AtEOXact_Buffers(true);
1543 /* Clean up the relation cache */
1544 AtEOXact_RelationCache(true);
1547 * Make catalog changes visible to all backends. This has to happen after
1548 * relcache references are dropped (see comments for
1549 * AtEOXact_RelationCache), but before locks are released (if anyone is
1550 * waiting for lock on a relation we've modified, we want them to know
1551 * about the catalog change before they start using the relation).
1553 AtEOXact_Inval(true);
1556 * Likewise, dropping of files deleted during the transaction is best done
1557 * after releasing relcache and buffer pins. (This is not strictly
1558 * necessary during commit, since such pins should have been released
1559 * already, but this ordering is definitely critical during abort.)
1561 smgrDoPendingDeletes(true);
1563 AtEOXact_MultiXact();
1565 ResourceOwnerRelease(TopTransactionResourceOwner,
1566 RESOURCE_RELEASE_LOCKS,
1568 ResourceOwnerRelease(TopTransactionResourceOwner,
1569 RESOURCE_RELEASE_AFTER_LOCKS,
1572 /* Check we've released all catcache entries */
1573 AtEOXact_CatCache(true);
1575 AtEOXact_GUC(true, false);
1577 AtEOXact_on_commit_actions(true);
1578 AtEOXact_Namespace(true);
1579 /* smgrcommit already done */
1581 pgstat_count_xact_commit();
1583 CurrentResourceOwner = NULL;
1584 ResourceOwnerDelete(TopTransactionResourceOwner);
1585 s->curTransactionOwner = NULL;
1586 CurTransactionResourceOwner = NULL;
1587 TopTransactionResourceOwner = NULL;
1591 s->transactionId = InvalidTransactionId;
1592 s->subTransactionId = InvalidSubTransactionId;
1593 s->nestingLevel = 0;
1597 * done with commit processing, set current transaction state back to
1600 s->state = TRANS_DEFAULT;
1602 RESUME_INTERRUPTS();
1607 * PrepareTransaction
1609 * NB: if you change this routine, better look at CommitTransaction too!
1612 PrepareTransaction(void)
1614 TransactionState s = CurrentTransactionState;
1615 TransactionId xid = GetCurrentTransactionId();
1616 GlobalTransaction gxact;
1617 TimestampTz prepared_at;
1619 ShowTransactionState("PrepareTransaction");
1622 * check the current transaction state
1624 if (s->state != TRANS_INPROGRESS)
1625 elog(WARNING, "PrepareTransaction while in %s state",
1626 TransStateAsString(s->state));
1627 Assert(s->parent == NULL);
1630 * Do pre-commit processing (most of this stuff requires database access,
1631 * and in fact could still cause an error...)
1633 * It is possible for PrepareHoldablePortals to invoke functions that queue
1634 * deferred triggers, and it's also possible that triggers create holdable
1635 * cursors. So we have to loop until there's nothing left to do.
1640 * Fire all currently pending deferred triggers.
1642 AfterTriggerFireDeferred();
1645 * Convert any open holdable cursors into static portals. If there
1646 * weren't any, we are done ... otherwise loop back to check if they
1647 * queued deferred triggers. Lather, rinse, repeat.
1649 if (!PrepareHoldablePortals())
1653 /* Now we can shut down the deferred-trigger manager */
1654 AfterTriggerEndXact(true);
1656 /* Close any open regular cursors */
1660 * Let ON COMMIT management do its thing (must happen after closing
1661 * cursors, to avoid dangling-reference problems)
1663 PreCommit_on_commit_actions();
1665 /* close large objects before lower-level cleanup */
1666 AtEOXact_LargeObject(true);
1668 /* NOTIFY and flatfiles will be handled below */
1670 /* Prevent cancel/die interrupt while cleaning up */
1674 * set the current transaction state information appropriately during
1675 * prepare processing
1677 s->state = TRANS_PREPARE;
1679 prepared_at = GetCurrentTimestamp();
1681 /* Tell bufmgr and smgr to prepare for commit */
1685 * Reserve the GID for this transaction. This could fail if the requested
1686 * GID is invalid or already in use.
1688 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1689 GetUserId(), MyDatabaseId);
1693 * Collect data for the 2PC state file. Note that in general, no actual
1694 * state change should happen in the called modules during this step,
1695 * since it's still possible to fail before commit, and in that case we
1696 * want transaction abort to be able to clean up. (In particular, the
1697 * AtPrepare routines may error out if they find cases they cannot
1698 * handle.) State cleanup should happen in the PostPrepare routines
1699 * below. However, some modules can go ahead and clear state here because
1700 * they wouldn't do anything with it during abort anyway.
1702 * Note: because the 2PC state file records will be replayed in the same
1703 * order they are made, the order of these calls has to match the order in
1704 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1705 * PREPARED; in particular, pay attention to whether things should happen
1706 * before or after releasing the transaction's locks.
1708 StartPrepare(gxact);
1711 AtPrepare_UpdateFlatFiles();
1716 * Here is where we really truly prepare.
1718 * We have to record transaction prepares even if we didn't make any updates,
1719 * because the transaction manager might get confused if we lose a global
1725 * Now we clean up backend-internal state and release internal resources.
1728 /* Break the chain of back-links in the XLOG records I output */
1729 MyLastRecPtr.xrecoff = 0;
1730 MyXactMadeXLogEntry = false;
1731 MyXactMadeTempRelUpdate = false;
1734 * Let others know about no transaction in progress by me. This has to be
1735 * done *after* the prepared transaction has been marked valid, else
1736 * someone may think it is unlocked and recyclable.
1739 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1740 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1741 MyProc->xid = InvalidTransactionId;
1742 MyProc->xmin = InvalidTransactionId;
1744 /* Clear the subtransaction-XID cache too while holding the lock */
1745 MyProc->subxids.nxids = 0;
1746 MyProc->subxids.overflowed = false;
1748 LWLockRelease(ProcArrayLock);
1751 * This is all post-transaction cleanup. Note that if an error is raised
1752 * here, it's too late to abort the transaction. This should be just
1753 * noncritical resource releasing. See notes in CommitTransaction.
1756 CallXactCallbacks(XACT_EVENT_PREPARE);
1758 ResourceOwnerRelease(TopTransactionResourceOwner,
1759 RESOURCE_RELEASE_BEFORE_LOCKS,
1762 /* Check we've released all buffer pins */
1763 AtEOXact_Buffers(true);
1765 /* Clean up the relation cache */
1766 AtEOXact_RelationCache(true);
1768 /* notify and flatfiles don't need a postprepare call */
1770 PostPrepare_Inval();
1774 AtEOXact_MultiXact();
1776 PostPrepare_Locks(xid);
1778 ResourceOwnerRelease(TopTransactionResourceOwner,
1779 RESOURCE_RELEASE_LOCKS,
1781 ResourceOwnerRelease(TopTransactionResourceOwner,
1782 RESOURCE_RELEASE_AFTER_LOCKS,
1785 /* Check we've released all catcache entries */
1786 AtEOXact_CatCache(true);
1788 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1789 AtEOXact_GUC(true, false);
1791 AtEOXact_on_commit_actions(true);
1792 AtEOXact_Namespace(true);
1793 /* smgrcommit already done */
1796 CurrentResourceOwner = NULL;
1797 ResourceOwnerDelete(TopTransactionResourceOwner);
1798 s->curTransactionOwner = NULL;
1799 CurTransactionResourceOwner = NULL;
1800 TopTransactionResourceOwner = NULL;
1804 s->transactionId = InvalidTransactionId;
1805 s->subTransactionId = InvalidSubTransactionId;
1806 s->nestingLevel = 0;
1810 * done with 1st phase commit processing, set current transaction state
1813 s->state = TRANS_DEFAULT;
1815 RESUME_INTERRUPTS();
1823 AbortTransaction(void)
1825 TransactionState s = CurrentTransactionState;
1827 /* Prevent cancel/die interrupt while cleaning up */
1831 * Release any LW locks we might be holding as quickly as possible.
1832 * (Regular locks, however, must be held till we finish aborting.)
1833 * Releasing LW locks is critical since we might try to grab them again
1834 * while cleaning up!
1838 /* Clean up buffer I/O and buffer context locks, too */
1843 * Also clean up any open wait for lock, since the lock manager will choke
1844 * if we try to wait for another lock before doing this.
1849 * check the current transaction state
1851 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1852 elog(WARNING, "AbortTransaction while in %s state",
1853 TransStateAsString(s->state));
1854 Assert(s->parent == NULL);
1857 * set the current transaction state information appropriately during the
1860 s->state = TRANS_ABORT;
1862 /* Make sure we have a valid memory context and resource owner */
1864 AtAbort_ResourceOwner();
1867 * Reset user id which might have been changed transiently. We cannot use
1868 * s->currentUser, since it may not be set yet; instead rely on internal
1869 * state of miscinit.c.
1871 * (Note: it is not necessary to restore session authorization here because
1872 * that can only be changed via GUC, and GUC will take care of rolling it
1873 * back if need be. However, an error within a SECURITY DEFINER function
1874 * could send control here with the wrong current userid.)
1879 * do abort processing
1881 AfterTriggerEndXact(false);
1883 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1885 AtEOXact_UpdateFlatFiles(false);
1888 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1889 * far as assigning an XID to advertise).
1891 if (TransactionIdIsValid(s->transactionId))
1892 RecordTransactionAbort();
1895 * Let others know about no transaction in progress by me. Note that this
1896 * must be done _before_ releasing locks we hold and _after_
1897 * RecordTransactionAbort.
1901 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1902 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1903 MyProc->xid = InvalidTransactionId;
1904 MyProc->xmin = InvalidTransactionId;
1906 /* Clear the subtransaction-XID cache too while holding the lock */
1907 MyProc->subxids.nxids = 0;
1908 MyProc->subxids.overflowed = false;
1910 LWLockRelease(ProcArrayLock);
1914 * Post-abort cleanup. See notes in CommitTransaction() concerning
1918 CallXactCallbacks(XACT_EVENT_ABORT);
1920 ResourceOwnerRelease(TopTransactionResourceOwner,
1921 RESOURCE_RELEASE_BEFORE_LOCKS,
1923 AtEOXact_Buffers(false);
1924 AtEOXact_RelationCache(false);
1925 AtEOXact_Inval(false);
1926 smgrDoPendingDeletes(false);
1927 AtEOXact_MultiXact();
1928 ResourceOwnerRelease(TopTransactionResourceOwner,
1929 RESOURCE_RELEASE_LOCKS,
1931 ResourceOwnerRelease(TopTransactionResourceOwner,
1932 RESOURCE_RELEASE_AFTER_LOCKS,
1934 AtEOXact_CatCache(false);
1936 AtEOXact_GUC(false, false);
1937 AtEOXact_SPI(false);
1938 AtEOXact_on_commit_actions(false);
1939 AtEOXact_Namespace(false);
1942 pgstat_count_xact_rollback();
1945 * State remains TRANS_ABORT until CleanupTransaction().
1947 RESUME_INTERRUPTS();
1951 * CleanupTransaction
1954 CleanupTransaction(void)
1956 TransactionState s = CurrentTransactionState;
1959 * State should still be TRANS_ABORT from AbortTransaction().
1961 if (s->state != TRANS_ABORT)
1962 elog(FATAL, "CleanupTransaction: unexpected state %s",
1963 TransStateAsString(s->state));
1966 * do abort cleanup processing
1968 AtCleanup_Portals(); /* now safe to release portal memory */
1970 CurrentResourceOwner = NULL; /* and resource owner */
1971 if (TopTransactionResourceOwner)
1972 ResourceOwnerDelete(TopTransactionResourceOwner);
1973 s->curTransactionOwner = NULL;
1974 CurTransactionResourceOwner = NULL;
1975 TopTransactionResourceOwner = NULL;
1977 AtCleanup_Memory(); /* and transaction memory */
1979 s->transactionId = InvalidTransactionId;
1980 s->subTransactionId = InvalidSubTransactionId;
1981 s->nestingLevel = 0;
1985 * done with abort processing, set current transaction state back to
1988 s->state = TRANS_DEFAULT;
1992 * StartTransactionCommand
1995 StartTransactionCommand(void)
1997 TransactionState s = CurrentTransactionState;
1999 switch (s->blockState)
2002 * if we aren't in a transaction block, we just do our usual start
2005 case TBLOCK_DEFAULT:
2007 s->blockState = TBLOCK_STARTED;
2011 * We are somewhere in a transaction block or subtransaction and
2012 * about to start a new command. For now we do nothing, but
2013 * someday we may do command-local resource initialization. (Note
2014 * that any needed CommandCounterIncrement was done by the
2015 * previous CommitTransactionCommand.)
2017 case TBLOCK_INPROGRESS:
2018 case TBLOCK_SUBINPROGRESS:
2022 * Here we are in a failed transaction block (one of the commands
2023 * caused an abort) so we do nothing but remain in the abort
2024 * state. Eventually we will get a ROLLBACK command which will
2025 * get us out of this state. (It is up to other code to ensure
2026 * that no commands other than ROLLBACK will be processed in these
2030 case TBLOCK_SUBABORT:
2033 /* These cases are invalid. */
2034 case TBLOCK_STARTED:
2036 case TBLOCK_SUBBEGIN:
2039 case TBLOCK_ABORT_END:
2040 case TBLOCK_SUBABORT_END:
2041 case TBLOCK_ABORT_PENDING:
2042 case TBLOCK_SUBABORT_PENDING:
2043 case TBLOCK_SUBRESTART:
2044 case TBLOCK_SUBABORT_RESTART:
2045 case TBLOCK_PREPARE:
2046 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2047 BlockStateAsString(s->blockState));
2052 * We must switch to CurTransactionContext before returning. This is
2053 * already done if we called StartTransaction, otherwise not.
2055 Assert(CurTransactionContext != NULL);
2056 MemoryContextSwitchTo(CurTransactionContext);
2060 * CommitTransactionCommand
2063 CommitTransactionCommand(void)
2065 TransactionState s = CurrentTransactionState;
2067 switch (s->blockState)
2070 * This shouldn't happen, because it means the previous
2071 * StartTransactionCommand didn't set the STARTED state
2074 case TBLOCK_DEFAULT:
2075 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2076 BlockStateAsString(s->blockState));
2080 * If we aren't in a transaction block, just do our usual
2081 * transaction commit, and return to the idle state.
2083 case TBLOCK_STARTED:
2084 CommitTransaction();
2085 s->blockState = TBLOCK_DEFAULT;
2089 * We are completing a "BEGIN TRANSACTION" command, so we change
2090 * to the "transaction block in progress" state and return. (We
2091 * assume the BEGIN did nothing to the database, so we need no
2092 * CommandCounterIncrement.)
2095 s->blockState = TBLOCK_INPROGRESS;
2099 * This is the case when we have finished executing a command
2100 * someplace within a transaction block. We increment the command
2101 * counter and return.
2103 case TBLOCK_INPROGRESS:
2104 case TBLOCK_SUBINPROGRESS:
2105 CommandCounterIncrement();
2109 * We are completing a "COMMIT" command. Do it and return to the
2113 CommitTransaction();
2114 s->blockState = TBLOCK_DEFAULT;
2118 * Here we are in the middle of a transaction block but one of the
2119 * commands caused an abort so we do nothing but remain in the
2120 * abort state. Eventually we will get a ROLLBACK comand.
2123 case TBLOCK_SUBABORT:
2127 * Here we were in an aborted transaction block and we just got
2128 * the ROLLBACK command from the user, so clean up the
2129 * already-aborted transaction and return to the idle state.
2131 case TBLOCK_ABORT_END:
2132 CleanupTransaction();
2133 s->blockState = TBLOCK_DEFAULT;
2137 * Here we were in a perfectly good transaction block but the user
2138 * told us to ROLLBACK anyway. We have to abort the transaction
2139 * and then clean up.
2141 case TBLOCK_ABORT_PENDING:
2143 CleanupTransaction();
2144 s->blockState = TBLOCK_DEFAULT;
2148 * We are completing a "PREPARE TRANSACTION" command. Do it and
2149 * return to the idle state.
2151 case TBLOCK_PREPARE:
2152 PrepareTransaction();
2153 s->blockState = TBLOCK_DEFAULT;
2157 * We were just issued a SAVEPOINT inside a transaction block.
2158 * Start a subtransaction. (DefineSavepoint already did
2159 * PushTransaction, so as to have someplace to put the SUBBEGIN
2162 case TBLOCK_SUBBEGIN:
2163 StartSubTransaction();
2164 s->blockState = TBLOCK_SUBINPROGRESS;
2168 * We were issued a COMMIT or RELEASE command, so we end the
2169 * current subtransaction and return to the parent transaction.
2170 * The parent might be ended too, so repeat till we are all the
2171 * way out or find an INPROGRESS transaction.
2176 CommitSubTransaction();
2177 s = CurrentTransactionState; /* changed by pop */
2178 } while (s->blockState == TBLOCK_SUBEND);
2179 /* If we had a COMMIT command, finish off the main xact too */
2180 if (s->blockState == TBLOCK_END)
2182 Assert(s->parent == NULL);
2183 CommitTransaction();
2184 s->blockState = TBLOCK_DEFAULT;
2186 else if (s->blockState == TBLOCK_PREPARE)
2188 Assert(s->parent == NULL);
2189 PrepareTransaction();
2190 s->blockState = TBLOCK_DEFAULT;
2194 Assert(s->blockState == TBLOCK_INPROGRESS ||
2195 s->blockState == TBLOCK_SUBINPROGRESS);
2200 * The current already-failed subtransaction is ending due to a
2201 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2202 * examine the parent (which could be in any of several states).
2204 case TBLOCK_SUBABORT_END:
2205 CleanupSubTransaction();
2206 CommitTransactionCommand();
2210 * As above, but it's not dead yet, so abort first.
2212 case TBLOCK_SUBABORT_PENDING:
2213 AbortSubTransaction();
2214 CleanupSubTransaction();
2215 CommitTransactionCommand();
2219 * The current subtransaction is the target of a ROLLBACK TO
2220 * command. Abort and pop it, then start a new subtransaction
2221 * with the same name.
2223 case TBLOCK_SUBRESTART:
2228 /* save name and keep Cleanup from freeing it */
2231 savepointLevel = s->savepointLevel;
2233 AbortSubTransaction();
2234 CleanupSubTransaction();
2236 DefineSavepoint(NULL);
2237 s = CurrentTransactionState; /* changed by push */
2239 s->savepointLevel = savepointLevel;
2241 /* This is the same as TBLOCK_SUBBEGIN case */
2242 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2243 StartSubTransaction();
2244 s->blockState = TBLOCK_SUBINPROGRESS;
2249 * Same as above, but the subtransaction had already failed, so we
2250 * don't need AbortSubTransaction.
2252 case TBLOCK_SUBABORT_RESTART:
2257 /* save name and keep Cleanup from freeing it */
2260 savepointLevel = s->savepointLevel;
2262 CleanupSubTransaction();
2264 DefineSavepoint(NULL);
2265 s = CurrentTransactionState; /* changed by push */
2267 s->savepointLevel = savepointLevel;
2269 /* This is the same as TBLOCK_SUBBEGIN case */
2270 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2271 StartSubTransaction();
2272 s->blockState = TBLOCK_SUBINPROGRESS;
2279 * AbortCurrentTransaction
2282 AbortCurrentTransaction(void)
2284 TransactionState s = CurrentTransactionState;
2286 switch (s->blockState)
2288 case TBLOCK_DEFAULT:
2289 if (s->state == TRANS_DEFAULT)
2291 /* we are idle, so nothing to do */
2296 * We can get here after an error during transaction start
2297 * (state will be TRANS_START). Need to clean up the
2298 * incompletely started transaction. First, adjust the
2299 * low-level state to suppress warning message from
2302 if (s->state == TRANS_START)
2303 s->state = TRANS_INPROGRESS;
2305 CleanupTransaction();
2310 * if we aren't in a transaction block, we just do the basic abort
2311 * & cleanup transaction.
2313 case TBLOCK_STARTED:
2315 CleanupTransaction();
2316 s->blockState = TBLOCK_DEFAULT;
2320 * If we are in TBLOCK_BEGIN it means something screwed up right
2321 * after reading "BEGIN TRANSACTION". We assume that the user
2322 * will interpret the error as meaning the BEGIN failed to get him
2323 * into a transaction block, so we should abort and return to idle
2328 CleanupTransaction();
2329 s->blockState = TBLOCK_DEFAULT;
2333 * We are somewhere in a transaction block and we've gotten a
2334 * failure, so we abort the transaction and set up the persistent
2335 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2337 case TBLOCK_INPROGRESS:
2339 s->blockState = TBLOCK_ABORT;
2340 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2344 * Here, we failed while trying to COMMIT. Clean up the
2345 * transaction and return to idle state (we do not want to stay in
2350 CleanupTransaction();
2351 s->blockState = TBLOCK_DEFAULT;
2355 * Here, we are already in an aborted transaction state and are
2356 * waiting for a ROLLBACK, but for some reason we failed again!
2357 * So we just remain in the abort state.
2360 case TBLOCK_SUBABORT:
2364 * We are in a failed transaction and we got the ROLLBACK command.
2365 * We have already aborted, we just need to cleanup and go to idle
2368 case TBLOCK_ABORT_END:
2369 CleanupTransaction();
2370 s->blockState = TBLOCK_DEFAULT;
2374 * We are in a live transaction and we got a ROLLBACK command.
2375 * Abort, cleanup, go to idle state.
2377 case TBLOCK_ABORT_PENDING:
2379 CleanupTransaction();
2380 s->blockState = TBLOCK_DEFAULT;
2384 * Here, we failed while trying to PREPARE. Clean up the
2385 * transaction and return to idle state (we do not want to stay in
2388 case TBLOCK_PREPARE:
2390 CleanupTransaction();
2391 s->blockState = TBLOCK_DEFAULT;
2395 * We got an error inside a subtransaction. Abort just the
2396 * subtransaction, and go to the persistent SUBABORT state until
2399 case TBLOCK_SUBINPROGRESS:
2400 AbortSubTransaction();
2401 s->blockState = TBLOCK_SUBABORT;
2405 * If we failed while trying to create a subtransaction, clean up
2406 * the broken subtransaction and abort the parent. The same
2407 * applies if we get a failure while ending a subtransaction.
2409 case TBLOCK_SUBBEGIN:
2411 case TBLOCK_SUBABORT_PENDING:
2412 case TBLOCK_SUBRESTART:
2413 AbortSubTransaction();
2414 CleanupSubTransaction();
2415 AbortCurrentTransaction();
2419 * Same as above, except the Abort() was already done.
2421 case TBLOCK_SUBABORT_END:
2422 case TBLOCK_SUBABORT_RESTART:
2423 CleanupSubTransaction();
2424 AbortCurrentTransaction();
2430 * PreventTransactionChain
2432 * This routine is to be called by statements that must not run inside
2433 * a transaction block, typically because they have non-rollback-able
2434 * side effects or do internal commits.
2436 * If we have already started a transaction block, issue an error; also issue
2437 * an error if we appear to be running inside a user-defined function (which
2438 * could issue more commands and possibly cause a failure after the statement
2439 * completes). Subtransactions are verboten too.
2441 * stmtNode: pointer to parameter block for statement; this is used in
2442 * a very klugy way to determine whether we are inside a function.
2443 * stmtType: statement type name for error messages.
2446 PreventTransactionChain(void *stmtNode, const char *stmtType)
2449 * xact block already started?
2451 if (IsTransactionBlock())
2453 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2454 /* translator: %s represents an SQL statement name */
2455 errmsg("%s cannot run inside a transaction block",
2461 if (IsSubTransaction())
2463 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2464 /* translator: %s represents an SQL statement name */
2465 errmsg("%s cannot run inside a subtransaction",
2469 * Are we inside a function call? If the statement's parameter block was
2470 * allocated in QueryContext, assume it is an interactive command.
2471 * Otherwise assume it is coming from a function.
2473 if (!MemoryContextContains(QueryContext, stmtNode))
2475 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2476 /* translator: %s represents an SQL statement name */
2477 errmsg("%s cannot be executed from a function", stmtType)));
2479 /* If we got past IsTransactionBlock test, should be in default state */
2480 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2481 CurrentTransactionState->blockState != TBLOCK_STARTED)
2482 elog(FATAL, "cannot prevent transaction chain");
2487 * RequireTransactionChain
2489 * This routine is to be called by statements that must run inside
2490 * a transaction block, because they have no effects that persist past
2491 * transaction end (and so calling them outside a transaction block
2492 * is presumably an error). DECLARE CURSOR is an example.
2494 * If we appear to be running inside a user-defined function, we do not
2495 * issue an error, since the function could issue more commands that make
2496 * use of the current statement's results. Likewise subtransactions.
2497 * Thus this is an inverse for PreventTransactionChain.
2499 * stmtNode: pointer to parameter block for statement; this is used in
2500 * a very klugy way to determine whether we are inside a function.
2501 * stmtType: statement type name for error messages.
2504 RequireTransactionChain(void *stmtNode, const char *stmtType)
2507 * xact block already started?
2509 if (IsTransactionBlock())
2515 if (IsSubTransaction())
2519 * Are we inside a function call? If the statement's parameter block was
2520 * allocated in QueryContext, assume it is an interactive command.
2521 * Otherwise assume it is coming from a function.
2523 if (!MemoryContextContains(QueryContext, stmtNode))
2526 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2527 /* translator: %s represents an SQL statement name */
2528 errmsg("%s may only be used in transaction blocks",
2533 * IsInTransactionChain
2535 * This routine is for statements that need to behave differently inside
2536 * a transaction block than when running as single commands. ANALYZE is
2537 * currently the only example.
2539 * stmtNode: pointer to parameter block for statement; this is used in
2540 * a very klugy way to determine whether we are inside a function.
2543 IsInTransactionChain(void *stmtNode)
2546 * Return true on same conditions that would make PreventTransactionChain
2549 if (IsTransactionBlock())
2552 if (IsSubTransaction())
2555 if (!MemoryContextContains(QueryContext, stmtNode))
2558 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2559 CurrentTransactionState->blockState != TBLOCK_STARTED)
2567 * Register or deregister callback functions for start- and end-of-xact
2570 * These functions are intended for use by dynamically loaded modules.
2571 * For built-in modules we generally just hardwire the appropriate calls
2572 * (mainly because it's easier to control the order that way, where needed).
2574 * At transaction end, the callback occurs post-commit or post-abort, so the
2575 * callback functions can only do noncritical cleanup.
2578 RegisterXactCallback(XactCallback callback, void *arg)
2580 XactCallbackItem *item;
2582 item = (XactCallbackItem *)
2583 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2584 item->callback = callback;
2586 item->next = Xact_callbacks;
2587 Xact_callbacks = item;
2591 UnregisterXactCallback(XactCallback callback, void *arg)
2593 XactCallbackItem *item;
2594 XactCallbackItem *prev;
2597 for (item = Xact_callbacks; item; prev = item, item = item->next)
2599 if (item->callback == callback && item->arg == arg)
2602 prev->next = item->next;
2604 Xact_callbacks = item->next;
2612 CallXactCallbacks(XactEvent event)
2614 XactCallbackItem *item;
2616 for (item = Xact_callbacks; item; item = item->next)
2617 (*item->callback) (event, item->arg);
2622 * Register or deregister callback functions for start- and end-of-subxact
2625 * Pretty much same as above, but for subtransaction events.
2627 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2628 * so the callback functions can only do noncritical cleanup. At
2629 * subtransaction start, the callback is called when the subtransaction has
2630 * finished initializing.
2633 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2635 SubXactCallbackItem *item;
2637 item = (SubXactCallbackItem *)
2638 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2639 item->callback = callback;
2641 item->next = SubXact_callbacks;
2642 SubXact_callbacks = item;
2646 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2648 SubXactCallbackItem *item;
2649 SubXactCallbackItem *prev;
2652 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2654 if (item->callback == callback && item->arg == arg)
2657 prev->next = item->next;
2659 SubXact_callbacks = item->next;
2667 CallSubXactCallbacks(SubXactEvent event,
2668 SubTransactionId mySubid,
2669 SubTransactionId parentSubid)
2671 SubXactCallbackItem *item;
2673 for (item = SubXact_callbacks; item; item = item->next)
2674 (*item->callback) (event, mySubid, parentSubid, item->arg);
2678 /* ----------------------------------------------------------------
2679 * transaction block support
2680 * ----------------------------------------------------------------
2684 * BeginTransactionBlock
2685 * This executes a BEGIN command.
2688 BeginTransactionBlock(void)
2690 TransactionState s = CurrentTransactionState;
2692 switch (s->blockState)
2695 * We are not inside a transaction block, so allow one to begin.
2697 case TBLOCK_STARTED:
2698 s->blockState = TBLOCK_BEGIN;
2702 * Already a transaction block in progress.
2704 case TBLOCK_INPROGRESS:
2705 case TBLOCK_SUBINPROGRESS:
2707 case TBLOCK_SUBABORT:
2709 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2710 errmsg("there is already a transaction in progress")));
2713 /* These cases are invalid. */
2714 case TBLOCK_DEFAULT:
2716 case TBLOCK_SUBBEGIN:
2719 case TBLOCK_ABORT_END:
2720 case TBLOCK_SUBABORT_END:
2721 case TBLOCK_ABORT_PENDING:
2722 case TBLOCK_SUBABORT_PENDING:
2723 case TBLOCK_SUBRESTART:
2724 case TBLOCK_SUBABORT_RESTART:
2725 case TBLOCK_PREPARE:
2726 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2727 BlockStateAsString(s->blockState));
2733 * PrepareTransactionBlock
2734 * This executes a PREPARE command.
2736 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2737 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2739 * Note that we don't actually do anything here except change blockState.
2740 * The real work will be done in the upcoming PrepareTransaction().
2741 * We do it this way because it's not convenient to change memory context,
2742 * resource owner, etc while executing inside a Portal.
2745 PrepareTransactionBlock(char *gid)
2750 /* Set up to commit the current transaction */
2751 result = EndTransactionBlock();
2753 /* If successful, change outer tblock state to PREPARE */
2756 s = CurrentTransactionState;
2758 while (s->parent != NULL)
2761 if (s->blockState == TBLOCK_END)
2763 /* Save GID where PrepareTransaction can find it again */
2764 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2766 s->blockState = TBLOCK_PREPARE;
2771 * ignore case where we are not in a transaction;
2772 * EndTransactionBlock already issued a warning.
2774 Assert(s->blockState == TBLOCK_STARTED);
2775 /* Don't send back a PREPARE result tag... */
2784 * EndTransactionBlock
2785 * This executes a COMMIT command.
2787 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2788 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2790 * Note that we don't actually do anything here except change blockState.
2791 * The real work will be done in the upcoming CommitTransactionCommand().
2792 * We do it this way because it's not convenient to change memory context,
2793 * resource owner, etc while executing inside a Portal.
2796 EndTransactionBlock(void)
2798 TransactionState s = CurrentTransactionState;
2799 bool result = false;
2801 switch (s->blockState)
2804 * We are in a transaction block, so tell CommitTransactionCommand
2807 case TBLOCK_INPROGRESS:
2808 s->blockState = TBLOCK_END;
2813 * We are in a failed transaction block. Tell
2814 * CommitTransactionCommand it's time to exit the block.
2817 s->blockState = TBLOCK_ABORT_END;
2821 * We are in a live subtransaction block. Set up to subcommit all
2822 * open subtransactions and then commit the main transaction.
2824 case TBLOCK_SUBINPROGRESS:
2825 while (s->parent != NULL)
2827 if (s->blockState == TBLOCK_SUBINPROGRESS)
2828 s->blockState = TBLOCK_SUBEND;
2830 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2831 BlockStateAsString(s->blockState));
2834 if (s->blockState == TBLOCK_INPROGRESS)
2835 s->blockState = TBLOCK_END;
2837 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2838 BlockStateAsString(s->blockState));
2843 * Here we are inside an aborted subtransaction. Treat the COMMIT
2844 * as ROLLBACK: set up to abort everything and exit the main
2847 case TBLOCK_SUBABORT:
2848 while (s->parent != NULL)
2850 if (s->blockState == TBLOCK_SUBINPROGRESS)
2851 s->blockState = TBLOCK_SUBABORT_PENDING;
2852 else if (s->blockState == TBLOCK_SUBABORT)
2853 s->blockState = TBLOCK_SUBABORT_END;
2855 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2856 BlockStateAsString(s->blockState));
2859 if (s->blockState == TBLOCK_INPROGRESS)
2860 s->blockState = TBLOCK_ABORT_PENDING;
2861 else if (s->blockState == TBLOCK_ABORT)
2862 s->blockState = TBLOCK_ABORT_END;
2864 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2865 BlockStateAsString(s->blockState));
2869 * The user issued COMMIT when not inside a transaction. Issue a
2870 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2871 * CommitTransactionCommand() will then close the transaction and
2872 * put us back into the default state.
2874 case TBLOCK_STARTED:
2876 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2877 errmsg("there is no transaction in progress")));
2881 /* These cases are invalid. */
2882 case TBLOCK_DEFAULT:
2884 case TBLOCK_SUBBEGIN:
2887 case TBLOCK_ABORT_END:
2888 case TBLOCK_SUBABORT_END:
2889 case TBLOCK_ABORT_PENDING:
2890 case TBLOCK_SUBABORT_PENDING:
2891 case TBLOCK_SUBRESTART:
2892 case TBLOCK_SUBABORT_RESTART:
2893 case TBLOCK_PREPARE:
2894 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2895 BlockStateAsString(s->blockState));
2903 * UserAbortTransactionBlock
2904 * This executes a ROLLBACK command.
2906 * As above, we don't actually do anything here except change blockState.
2909 UserAbortTransactionBlock(void)
2911 TransactionState s = CurrentTransactionState;
2913 switch (s->blockState)
2916 * We are inside a transaction block and we got a ROLLBACK command
2917 * from the user, so tell CommitTransactionCommand to abort and
2918 * exit the transaction block.
2920 case TBLOCK_INPROGRESS:
2921 s->blockState = TBLOCK_ABORT_PENDING;
2925 * We are inside a failed transaction block and we got a ROLLBACK
2926 * command from the user. Abort processing is already done, so
2927 * CommitTransactionCommand just has to cleanup and go back to
2931 s->blockState = TBLOCK_ABORT_END;
2935 * We are inside a subtransaction. Mark everything up to top
2936 * level as exitable.
2938 case TBLOCK_SUBINPROGRESS:
2939 case TBLOCK_SUBABORT:
2940 while (s->parent != NULL)
2942 if (s->blockState == TBLOCK_SUBINPROGRESS)
2943 s->blockState = TBLOCK_SUBABORT_PENDING;
2944 else if (s->blockState == TBLOCK_SUBABORT)
2945 s->blockState = TBLOCK_SUBABORT_END;
2947 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2948 BlockStateAsString(s->blockState));
2951 if (s->blockState == TBLOCK_INPROGRESS)
2952 s->blockState = TBLOCK_ABORT_PENDING;
2953 else if (s->blockState == TBLOCK_ABORT)
2954 s->blockState = TBLOCK_ABORT_END;
2956 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2957 BlockStateAsString(s->blockState));
2961 * The user issued ABORT when not inside a transaction. Issue a
2962 * WARNING and go to abort state. The upcoming call to
2963 * CommitTransactionCommand() will then put us back into the
2966 case TBLOCK_STARTED:
2968 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2969 errmsg("there is no transaction in progress")));
2970 s->blockState = TBLOCK_ABORT_PENDING;
2973 /* These cases are invalid. */
2974 case TBLOCK_DEFAULT:
2976 case TBLOCK_SUBBEGIN:
2979 case TBLOCK_ABORT_END:
2980 case TBLOCK_SUBABORT_END:
2981 case TBLOCK_ABORT_PENDING:
2982 case TBLOCK_SUBABORT_PENDING:
2983 case TBLOCK_SUBRESTART:
2984 case TBLOCK_SUBABORT_RESTART:
2985 case TBLOCK_PREPARE:
2986 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2987 BlockStateAsString(s->blockState));
2994 * This executes a SAVEPOINT command.
2997 DefineSavepoint(char *name)
2999 TransactionState s = CurrentTransactionState;
3001 switch (s->blockState)
3003 case TBLOCK_INPROGRESS:
3004 case TBLOCK_SUBINPROGRESS:
3005 /* Normal subtransaction start */
3007 s = CurrentTransactionState; /* changed by push */
3010 * Savepoint names, like the TransactionState block itself, live
3011 * in TopTransactionContext.
3014 s->name = MemoryContextStrdup(TopTransactionContext, name);
3017 /* These cases are invalid. */
3018 case TBLOCK_DEFAULT:
3019 case TBLOCK_STARTED:
3021 case TBLOCK_SUBBEGIN:
3025 case TBLOCK_SUBABORT:
3026 case TBLOCK_ABORT_END:
3027 case TBLOCK_SUBABORT_END:
3028 case TBLOCK_ABORT_PENDING:
3029 case TBLOCK_SUBABORT_PENDING:
3030 case TBLOCK_SUBRESTART:
3031 case TBLOCK_SUBABORT_RESTART:
3032 case TBLOCK_PREPARE:
3033 elog(FATAL, "DefineSavepoint: unexpected state %s",
3034 BlockStateAsString(s->blockState));
3041 * This executes a RELEASE command.
3043 * As above, we don't actually do anything here except change blockState.
3046 ReleaseSavepoint(List *options)
3048 TransactionState s = CurrentTransactionState;
3049 TransactionState target,
3054 switch (s->blockState)
3057 * We can't rollback to a savepoint if there is no savepoint
3060 case TBLOCK_INPROGRESS:
3062 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3063 errmsg("no such savepoint")));
3067 * We are in a non-aborted subtransaction. This is the only valid
3070 case TBLOCK_SUBINPROGRESS:
3073 /* These cases are invalid. */
3074 case TBLOCK_DEFAULT:
3075 case TBLOCK_STARTED:
3077 case TBLOCK_SUBBEGIN:
3081 case TBLOCK_SUBABORT:
3082 case TBLOCK_ABORT_END:
3083 case TBLOCK_SUBABORT_END:
3084 case TBLOCK_ABORT_PENDING:
3085 case TBLOCK_SUBABORT_PENDING:
3086 case TBLOCK_SUBRESTART:
3087 case TBLOCK_SUBABORT_RESTART:
3088 case TBLOCK_PREPARE:
3089 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3090 BlockStateAsString(s->blockState));
3094 foreach(cell, options)
3096 DefElem *elem = lfirst(cell);
3098 if (strcmp(elem->defname, "savepoint_name") == 0)
3099 name = strVal(elem->arg);
3102 Assert(PointerIsValid(name));
3104 for (target = s; PointerIsValid(target); target = target->parent)
3106 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3110 if (!PointerIsValid(target))
3112 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3113 errmsg("no such savepoint")));
3115 /* disallow crossing savepoint level boundaries */
3116 if (target->savepointLevel != s->savepointLevel)
3118 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3119 errmsg("no such savepoint")));
3122 * Mark "commit pending" all subtransactions up to the target
3123 * subtransaction. The actual commits will happen when control gets to
3124 * CommitTransactionCommand.
3126 xact = CurrentTransactionState;
3129 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3130 xact->blockState = TBLOCK_SUBEND;
3133 xact = xact->parent;
3134 Assert(PointerIsValid(xact));
3139 * RollbackToSavepoint
3140 * This executes a ROLLBACK TO <savepoint> command.
3142 * As above, we don't actually do anything here except change blockState.
3145 RollbackToSavepoint(List *options)
3147 TransactionState s = CurrentTransactionState;
3148 TransactionState target,
3153 switch (s->blockState)
3156 * We can't rollback to a savepoint if there is no savepoint
3159 case TBLOCK_INPROGRESS:
3162 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3163 errmsg("no such savepoint")));
3167 * There is at least one savepoint, so proceed.
3169 case TBLOCK_SUBINPROGRESS:
3170 case TBLOCK_SUBABORT:
3173 /* These cases are invalid. */
3174 case TBLOCK_DEFAULT:
3175 case TBLOCK_STARTED:
3177 case TBLOCK_SUBBEGIN:
3180 case TBLOCK_ABORT_END:
3181 case TBLOCK_SUBABORT_END:
3182 case TBLOCK_ABORT_PENDING:
3183 case TBLOCK_SUBABORT_PENDING:
3184 case TBLOCK_SUBRESTART:
3185 case TBLOCK_SUBABORT_RESTART:
3186 case TBLOCK_PREPARE:
3187 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3188 BlockStateAsString(s->blockState));
3192 foreach(cell, options)
3194 DefElem *elem = lfirst(cell);
3196 if (strcmp(elem->defname, "savepoint_name") == 0)
3197 name = strVal(elem->arg);
3200 Assert(PointerIsValid(name));
3202 for (target = s; PointerIsValid(target); target = target->parent)
3204 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3208 if (!PointerIsValid(target))
3210 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3211 errmsg("no such savepoint")));
3213 /* disallow crossing savepoint level boundaries */
3214 if (target->savepointLevel != s->savepointLevel)
3216 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3217 errmsg("no such savepoint")));
3220 * Mark "abort pending" all subtransactions up to the target
3221 * subtransaction. The actual aborts will happen when control gets to
3222 * CommitTransactionCommand.
3224 xact = CurrentTransactionState;
3229 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3230 xact->blockState = TBLOCK_SUBABORT_PENDING;
3231 else if (xact->blockState == TBLOCK_SUBABORT)
3232 xact->blockState = TBLOCK_SUBABORT_END;
3234 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3235 BlockStateAsString(xact->blockState));
3236 xact = xact->parent;
3237 Assert(PointerIsValid(xact));
3240 /* And mark the target as "restart pending" */
3241 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3242 xact->blockState = TBLOCK_SUBRESTART;
3243 else if (xact->blockState == TBLOCK_SUBABORT)
3244 xact->blockState = TBLOCK_SUBABORT_RESTART;
3246 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3247 BlockStateAsString(xact->blockState));
3251 * BeginInternalSubTransaction
3252 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3253 * state, and therefore it can safely be used in a function that might
3254 * be called when not inside a BEGIN block. Also, we automatically
3255 * cycle through CommitTransactionCommand/StartTransactionCommand
3256 * instead of expecting the caller to do it.
3259 BeginInternalSubTransaction(char *name)
3261 TransactionState s = CurrentTransactionState;
3263 switch (s->blockState)
3265 case TBLOCK_STARTED:
3266 case TBLOCK_INPROGRESS:
3267 case TBLOCK_SUBINPROGRESS:
3268 /* Normal subtransaction start */
3270 s = CurrentTransactionState; /* changed by push */
3273 * Savepoint names, like the TransactionState block itself, live
3274 * in TopTransactionContext.
3277 s->name = MemoryContextStrdup(TopTransactionContext, name);
3280 /* These cases are invalid. */
3281 case TBLOCK_DEFAULT:
3283 case TBLOCK_SUBBEGIN:
3287 case TBLOCK_SUBABORT:
3288 case TBLOCK_ABORT_END:
3289 case TBLOCK_SUBABORT_END:
3290 case TBLOCK_ABORT_PENDING:
3291 case TBLOCK_SUBABORT_PENDING:
3292 case TBLOCK_SUBRESTART:
3293 case TBLOCK_SUBABORT_RESTART:
3294 case TBLOCK_PREPARE:
3295 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3296 BlockStateAsString(s->blockState));
3300 CommitTransactionCommand();
3301 StartTransactionCommand();
3305 * ReleaseCurrentSubTransaction
3307 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3308 * savepoint name (if any).
3309 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3312 ReleaseCurrentSubTransaction(void)
3314 TransactionState s = CurrentTransactionState;
3316 if (s->blockState != TBLOCK_SUBINPROGRESS)
3317 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3318 BlockStateAsString(s->blockState));
3319 Assert(s->state == TRANS_INPROGRESS);
3320 MemoryContextSwitchTo(CurTransactionContext);
3321 CommitSubTransaction();
3322 s = CurrentTransactionState; /* changed by pop */
3323 Assert(s->state == TRANS_INPROGRESS);
3327 * RollbackAndReleaseCurrentSubTransaction
3329 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3330 * of its savepoint name (if any).
3331 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3334 RollbackAndReleaseCurrentSubTransaction(void)
3336 TransactionState s = CurrentTransactionState;
3338 switch (s->blockState)
3340 /* Must be in a subtransaction */
3341 case TBLOCK_SUBINPROGRESS:
3342 case TBLOCK_SUBABORT:
3345 /* These cases are invalid. */
3346 case TBLOCK_DEFAULT:
3347 case TBLOCK_STARTED:
3349 case TBLOCK_SUBBEGIN:
3350 case TBLOCK_INPROGRESS:
3354 case TBLOCK_ABORT_END:
3355 case TBLOCK_SUBABORT_END:
3356 case TBLOCK_ABORT_PENDING:
3357 case TBLOCK_SUBABORT_PENDING:
3358 case TBLOCK_SUBRESTART:
3359 case TBLOCK_SUBABORT_RESTART:
3360 case TBLOCK_PREPARE:
3361 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3362 BlockStateAsString(s->blockState));
3367 * Abort the current subtransaction, if needed.
3369 if (s->blockState == TBLOCK_SUBINPROGRESS)
3370 AbortSubTransaction();
3372 /* And clean it up, too */
3373 CleanupSubTransaction();
3375 s = CurrentTransactionState; /* changed by pop */
3376 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3377 s->blockState == TBLOCK_INPROGRESS ||
3378 s->blockState == TBLOCK_STARTED);
3382 * AbortOutOfAnyTransaction
3384 * This routine is provided for error recovery purposes. It aborts any
3385 * active transaction or transaction block, leaving the system in a known
3389 AbortOutOfAnyTransaction(void)
3391 TransactionState s = CurrentTransactionState;
3394 * Get out of any transaction or nested transaction
3398 switch (s->blockState)
3400 case TBLOCK_DEFAULT:
3401 /* Not in a transaction, do nothing */
3403 case TBLOCK_STARTED:
3405 case TBLOCK_INPROGRESS:
3407 case TBLOCK_ABORT_PENDING:
3408 case TBLOCK_PREPARE:
3409 /* In a transaction, so clean up */
3411 CleanupTransaction();
3412 s->blockState = TBLOCK_DEFAULT;
3415 case TBLOCK_ABORT_END:
3416 /* AbortTransaction already done, still need Cleanup */
3417 CleanupTransaction();
3418 s->blockState = TBLOCK_DEFAULT;
3422 * In a subtransaction, so clean it up and abort parent too
3424 case TBLOCK_SUBBEGIN:
3425 case TBLOCK_SUBINPROGRESS:
3427 case TBLOCK_SUBABORT_PENDING:
3428 case TBLOCK_SUBRESTART:
3429 AbortSubTransaction();
3430 CleanupSubTransaction();
3431 s = CurrentTransactionState; /* changed by pop */
3434 case TBLOCK_SUBABORT:
3435 case TBLOCK_SUBABORT_END:
3436 case TBLOCK_SUBABORT_RESTART:
3437 /* As above, but AbortSubTransaction already done */
3438 CleanupSubTransaction();
3439 s = CurrentTransactionState; /* changed by pop */
3442 } while (s->blockState != TBLOCK_DEFAULT);
3444 /* Should be out of all subxacts now */
3445 Assert(s->parent == NULL);
3449 * IsTransactionBlock --- are we within a transaction block?
3452 IsTransactionBlock(void)
3454 TransactionState s = CurrentTransactionState;
3456 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3463 * IsTransactionOrTransactionBlock --- are we within either a transaction
3464 * or a transaction block? (The backend is only really "idle" when this
3467 * This should match up with IsTransactionBlock and IsTransactionState.
3470 IsTransactionOrTransactionBlock(void)
3472 TransactionState s = CurrentTransactionState;
3474 if (s->blockState == TBLOCK_DEFAULT)
3481 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3484 TransactionBlockStatusCode(void)
3486 TransactionState s = CurrentTransactionState;
3488 switch (s->blockState)
3490 case TBLOCK_DEFAULT:
3491 case TBLOCK_STARTED:
3492 return 'I'; /* idle --- not in transaction */
3494 case TBLOCK_SUBBEGIN:
3495 case TBLOCK_INPROGRESS:
3496 case TBLOCK_SUBINPROGRESS:
3499 case TBLOCK_PREPARE:
3500 return 'T'; /* in transaction */
3502 case TBLOCK_SUBABORT:
3503 case TBLOCK_ABORT_END:
3504 case TBLOCK_SUBABORT_END:
3505 case TBLOCK_ABORT_PENDING:
3506 case TBLOCK_SUBABORT_PENDING:
3507 case TBLOCK_SUBRESTART:
3508 case TBLOCK_SUBABORT_RESTART:
3509 return 'E'; /* in failed transaction */
3512 /* should never get here */
3513 elog(FATAL, "invalid transaction block state: %s",
3514 BlockStateAsString(s->blockState));
3515 return 0; /* keep compiler quiet */
3522 IsSubTransaction(void)
3524 TransactionState s = CurrentTransactionState;
3526 if (s->nestingLevel >= 2)
3533 * StartSubTransaction
3535 * If you're wondering why this is separate from PushTransaction: it's because
3536 * we can't conveniently do this stuff right inside DefineSavepoint. The
3537 * SAVEPOINT utility command will be executed inside a Portal, and if we
3538 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3539 * the Portal will undo those settings. So we make DefineSavepoint just
3540 * push a dummy transaction block, and when control returns to the main
3541 * idle loop, CommitTransactionCommand will be called, and we'll come here
3542 * to finish starting the subtransaction.
3545 StartSubTransaction(void)
3547 TransactionState s = CurrentTransactionState;
3549 if (s->state != TRANS_DEFAULT)
3550 elog(WARNING, "StartSubTransaction while in %s state",
3551 TransStateAsString(s->state));
3553 s->state = TRANS_START;
3556 * Initialize subsystems for new subtransaction
3558 * must initialize resource-management stuff first
3560 AtSubStart_Memory();
3561 AtSubStart_ResourceOwner();
3563 AtSubStart_Notify();
3564 AfterTriggerBeginSubXact();
3566 s->state = TRANS_INPROGRESS;
3569 * Call start-of-subxact callbacks
3571 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3572 s->parent->subTransactionId);
3574 ShowTransactionState("StartSubTransaction");
3578 * CommitSubTransaction
3580 * The caller has to make sure to always reassign CurrentTransactionState
3581 * if it has a local pointer to it after calling this function.
3584 CommitSubTransaction(void)
3586 TransactionState s = CurrentTransactionState;
3588 ShowTransactionState("CommitSubTransaction");
3590 if (s->state != TRANS_INPROGRESS)
3591 elog(WARNING, "CommitSubTransaction while in %s state",
3592 TransStateAsString(s->state));
3594 /* Pre-commit processing goes here -- nothing to do at the moment */
3596 s->state = TRANS_COMMIT;
3598 /* Must CCI to ensure commands of subtransaction are seen as done */
3599 CommandCounterIncrement();
3601 /* Mark subtransaction as subcommitted */
3602 if (TransactionIdIsValid(s->transactionId))
3604 RecordSubTransactionCommit();
3605 AtSubCommit_childXids();
3608 /* Post-commit cleanup */
3609 AfterTriggerEndSubXact(true);
3610 AtSubCommit_Portals(s->subTransactionId,
3611 s->parent->subTransactionId,
3612 s->parent->curTransactionOwner);
3613 AtEOSubXact_LargeObject(true, s->subTransactionId,
3614 s->parent->subTransactionId);
3615 AtSubCommit_Notify();
3616 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3617 s->parent->subTransactionId);
3619 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3620 s->parent->subTransactionId);
3622 ResourceOwnerRelease(s->curTransactionOwner,
3623 RESOURCE_RELEASE_BEFORE_LOCKS,
3625 AtEOSubXact_RelationCache(true, s->subTransactionId,
3626 s->parent->subTransactionId);
3627 AtEOSubXact_Inval(true);
3631 * The only lock we actually release here is the subtransaction XID lock.
3632 * The rest just get transferred to the parent resource owner.
3634 CurrentResourceOwner = s->curTransactionOwner;
3635 if (TransactionIdIsValid(s->transactionId))
3636 XactLockTableDelete(s->transactionId);
3638 ResourceOwnerRelease(s->curTransactionOwner,
3639 RESOURCE_RELEASE_LOCKS,
3641 ResourceOwnerRelease(s->curTransactionOwner,
3642 RESOURCE_RELEASE_AFTER_LOCKS,
3645 AtEOXact_GUC(true, true);
3646 AtEOSubXact_SPI(true, s->subTransactionId);
3647 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3648 s->parent->subTransactionId);
3649 AtEOSubXact_Namespace(true, s->subTransactionId,
3650 s->parent->subTransactionId);
3651 AtEOSubXact_Files(true, s->subTransactionId,
3652 s->parent->subTransactionId);
3655 * We need to restore the upper transaction's read-only state, in case the
3656 * upper is read-write while the child is read-only; GUC will incorrectly
3657 * think it should leave the child state in place.
3659 XactReadOnly = s->prevXactReadOnly;
3661 CurrentResourceOwner = s->parent->curTransactionOwner;
3662 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3663 ResourceOwnerDelete(s->curTransactionOwner);
3664 s->curTransactionOwner = NULL;
3666 AtSubCommit_Memory();
3668 s->state = TRANS_DEFAULT;
3674 * AbortSubTransaction
3677 AbortSubTransaction(void)
3679 TransactionState s = CurrentTransactionState;
3681 ShowTransactionState("AbortSubTransaction");
3683 if (s->state != TRANS_INPROGRESS)
3684 elog(WARNING, "AbortSubTransaction while in %s state",
3685 TransStateAsString(s->state));
3689 s->state = TRANS_ABORT;
3692 * Release any LW locks we might be holding as quickly as possible.
3693 * (Regular locks, however, must be held till we finish aborting.)
3694 * Releasing LW locks is critical since we might try to grab them again
3695 * while cleaning up!
3697 * FIXME This may be incorrect --- Are there some locks we should keep?
3698 * Buffer locks, for example? I don't think so but I'm not sure.
3708 * do abort processing
3710 AtSubAbort_Memory();
3711 AtSubAbort_ResourceOwner();
3714 * We can skip all this stuff if the subxact failed before creating a
3717 if (s->curTransactionOwner)
3719 AfterTriggerEndSubXact(false);
3720 AtSubAbort_Portals(s->subTransactionId,
3721 s->parent->subTransactionId,
3722 s->parent->curTransactionOwner);
3723 AtEOSubXact_LargeObject(false, s->subTransactionId,
3724 s->parent->subTransactionId);
3725 AtSubAbort_Notify();
3726 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3727 s->parent->subTransactionId);
3729 /* Advertise the fact that we aborted in pg_clog. */
3730 if (TransactionIdIsValid(s->transactionId))
3732 RecordSubTransactionAbort();
3733 AtSubAbort_childXids();
3736 /* Post-abort cleanup */
3737 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3738 s->parent->subTransactionId);
3740 ResourceOwnerRelease(s->curTransactionOwner,
3741 RESOURCE_RELEASE_BEFORE_LOCKS,
3743 AtEOSubXact_RelationCache(false, s->subTransactionId,
3744 s->parent->subTransactionId);
3745 AtEOSubXact_Inval(false);
3747 ResourceOwnerRelease(s->curTransactionOwner,
3748 RESOURCE_RELEASE_LOCKS,
3750 ResourceOwnerRelease(s->curTransactionOwner,
3751 RESOURCE_RELEASE_AFTER_LOCKS,
3754 AtEOXact_GUC(false, true);
3755 AtEOSubXact_SPI(false, s->subTransactionId);
3756 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3757 s->parent->subTransactionId);
3758 AtEOSubXact_Namespace(false, s->subTransactionId,
3759 s->parent->subTransactionId);
3760 AtEOSubXact_Files(false, s->subTransactionId,
3761 s->parent->subTransactionId);
3765 * Reset user id which might have been changed transiently. Here we want
3766 * to restore to the userid that was current at subxact entry. (As in
3767 * AbortTransaction, we need not worry about the session userid.)
3769 * Must do this after AtEOXact_GUC to handle the case where we entered the
3770 * subxact inside a SECURITY DEFINER function (hence current and session
3771 * userids were different) and then session auth was changed inside the
3772 * subxact. GUC will reset both current and session userids to the
3773 * entry-time session userid. This is right in every other scenario so it
3774 * seems simplest to let GUC do that and fix it here.
3776 SetUserId(s->currentUser);
3779 * Restore the upper transaction's read-only state, too. This should be
3780 * redundant with GUC's cleanup but we may as well do it for consistency
3781 * with the commit case.
3783 XactReadOnly = s->prevXactReadOnly;
3785 RESUME_INTERRUPTS();
3789 * CleanupSubTransaction
3791 * The caller has to make sure to always reassign CurrentTransactionState
3792 * if it has a local pointer to it after calling this function.
3795 CleanupSubTransaction(void)
3797 TransactionState s = CurrentTransactionState;
3799 ShowTransactionState("CleanupSubTransaction");
3801 if (s->state != TRANS_ABORT)
3802 elog(WARNING, "CleanupSubTransaction while in %s state",
3803 TransStateAsString(s->state));
3805 AtSubCleanup_Portals(s->subTransactionId);
3807 CurrentResourceOwner = s->parent->curTransactionOwner;
3808 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3809 if (s->curTransactionOwner)
3810 ResourceOwnerDelete(s->curTransactionOwner);
3811 s->curTransactionOwner = NULL;
3813 AtSubCleanup_Memory();
3815 s->state = TRANS_DEFAULT;
3822 * Create transaction state stack entry for a subtransaction
3824 * The caller has to make sure to always reassign CurrentTransactionState
3825 * if it has a local pointer to it after calling this function.
3828 PushTransaction(void)
3830 TransactionState p = CurrentTransactionState;
3835 * At present, GetUserId cannot fail, but let's not assume that. Get the
3836 * ID before entering the critical code sequence.
3838 currentUser = GetUserId();
3841 * We keep subtransaction state nodes in TopTransactionContext.
3843 s = (TransactionState)
3844 MemoryContextAllocZero(TopTransactionContext,
3845 sizeof(TransactionStateData));
3848 * Assign a subtransaction ID, watching out for counter wraparound.
3850 currentSubTransactionId += 1;
3851 if (currentSubTransactionId == InvalidSubTransactionId)
3853 currentSubTransactionId -= 1;
3856 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3857 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3861 * We can now stack a minimally valid subtransaction without fear of
3864 s->transactionId = InvalidTransactionId; /* until assigned */
3865 s->subTransactionId = currentSubTransactionId;
3867 s->nestingLevel = p->nestingLevel + 1;
3868 s->savepointLevel = p->savepointLevel;
3869 s->state = TRANS_DEFAULT;
3870 s->blockState = TBLOCK_SUBBEGIN;
3871 s->currentUser = currentUser;
3872 s->prevXactReadOnly = XactReadOnly;
3874 CurrentTransactionState = s;
3877 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3878 * with the subtransaction from here on out; in particular they should not
3879 * assume that it necessarily has a transaction context, resource owner,
3886 * Pop back to parent transaction state
3888 * The caller has to make sure to always reassign CurrentTransactionState
3889 * if it has a local pointer to it after calling this function.
3892 PopTransaction(void)
3894 TransactionState s = CurrentTransactionState;
3896 if (s->state != TRANS_DEFAULT)
3897 elog(WARNING, "PopTransaction while in %s state",
3898 TransStateAsString(s->state));
3900 if (s->parent == NULL)
3901 elog(FATAL, "PopTransaction with no parent");
3903 CurrentTransactionState = s->parent;
3905 /* Let's just make sure CurTransactionContext is good */
3906 CurTransactionContext = s->parent->curTransactionContext;
3907 MemoryContextSwitchTo(CurTransactionContext);
3909 /* Ditto for ResourceOwner links */
3910 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3911 CurrentResourceOwner = s->parent->curTransactionOwner;
3913 /* Free the old child structure */
3920 * ShowTransactionState
3924 ShowTransactionState(const char *str)
3926 /* skip work if message will definitely not be printed */
3927 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3929 elog(DEBUG3, "%s", str);
3930 ShowTransactionStateRec(CurrentTransactionState);
3935 * ShowTransactionStateRec
3936 * Recursive subroutine for ShowTransactionState
3939 ShowTransactionStateRec(TransactionState s)
3942 ShowTransactionStateRec(s->parent);
3944 /* use ereport to suppress computation if msg will not be printed */
3946 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3947 PointerIsValid(s->name) ? s->name : "unnamed",
3948 BlockStateAsString(s->blockState),
3949 TransStateAsString(s->state),
3950 (unsigned int) s->transactionId,
3951 (unsigned int) s->subTransactionId,
3952 (unsigned int) currentCommandId,
3954 nodeToString(s->childXids))));
3958 * BlockStateAsString
3962 BlockStateAsString(TBlockState blockState)
3966 case TBLOCK_DEFAULT:
3968 case TBLOCK_STARTED:
3972 case TBLOCK_INPROGRESS:
3973 return "INPROGRESS";
3978 case TBLOCK_ABORT_END:
3980 case TBLOCK_ABORT_PENDING:
3981 return "ABORT PEND";
3982 case TBLOCK_PREPARE:
3984 case TBLOCK_SUBBEGIN:
3986 case TBLOCK_SUBINPROGRESS:
3987 return "SUB INPROGRS";
3990 case TBLOCK_SUBABORT:
3992 case TBLOCK_SUBABORT_END:
3993 return "SUB ABORT END";
3994 case TBLOCK_SUBABORT_PENDING:
3995 return "SUB ABRT PEND";
3996 case TBLOCK_SUBRESTART:
3997 return "SUB RESTART";
3998 case TBLOCK_SUBABORT_RESTART:
3999 return "SUB AB RESTRT";
4001 return "UNRECOGNIZED";
4005 * TransStateAsString
4009 TransStateAsString(TransState state)
4017 case TRANS_INPROGRESS:
4026 return "UNRECOGNIZED";
4030 * xactGetCommittedChildren
4032 * Gets the list of committed children of the current transaction. The return
4033 * value is the number of child transactions. *children is set to point to a
4034 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4038 xactGetCommittedChildren(TransactionId **ptr)
4040 TransactionState s = CurrentTransactionState;
4042 TransactionId *children;
4045 nchildren = list_length(s->childXids);
4052 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4055 foreach(p, s->childXids)
4057 TransactionId child = lfirst_xid(p);
4059 *children++ = child;
4066 * XLOG support routines
4070 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4072 TransactionId *sub_xids;
4073 TransactionId max_xid;
4076 TransactionIdCommit(xid);
4078 /* Mark committed subtransactions as committed */
4079 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4080 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4082 /* Make sure nextXid is beyond any XID mentioned in the record */
4084 for (i = 0; i < xlrec->nsubxacts; i++)
4086 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4087 max_xid = sub_xids[i];
4089 if (TransactionIdFollowsOrEquals(max_xid,
4090 ShmemVariableCache->nextXid))
4092 ShmemVariableCache->nextXid = max_xid;
4093 TransactionIdAdvance(ShmemVariableCache->nextXid);
4096 /* Make sure files supposed to be dropped are dropped */
4097 for (i = 0; i < xlrec->nrels; i++)
4099 XLogCloseRelation(xlrec->xnodes[i]);
4100 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4105 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4107 TransactionId *sub_xids;
4108 TransactionId max_xid;
4111 TransactionIdAbort(xid);
4113 /* Mark subtransactions as aborted */
4114 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4115 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4117 /* Make sure nextXid is beyond any XID mentioned in the record */
4119 for (i = 0; i < xlrec->nsubxacts; i++)
4121 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4122 max_xid = sub_xids[i];
4124 if (TransactionIdFollowsOrEquals(max_xid,
4125 ShmemVariableCache->nextXid))
4127 ShmemVariableCache->nextXid = max_xid;
4128 TransactionIdAdvance(ShmemVariableCache->nextXid);
4131 /* Make sure files supposed to be dropped are dropped */
4132 for (i = 0; i < xlrec->nrels; i++)
4134 XLogCloseRelation(xlrec->xnodes[i]);
4135 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4140 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4142 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4144 if (info == XLOG_XACT_COMMIT)
4146 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4148 xact_redo_commit(xlrec, record->xl_xid);
4150 else if (info == XLOG_XACT_ABORT)
4152 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4154 xact_redo_abort(xlrec, record->xl_xid);
4156 else if (info == XLOG_XACT_PREPARE)
4158 /* the record contents are exactly the 2PC file */
4159 RecreateTwoPhaseFile(record->xl_xid,
4160 XLogRecGetData(record), record->xl_len);
4162 else if (info == XLOG_XACT_COMMIT_PREPARED)
4164 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4166 xact_redo_commit(&xlrec->crec, xlrec->xid);
4167 RemoveTwoPhaseFile(xlrec->xid, false);
4169 else if (info == XLOG_XACT_ABORT_PREPARED)
4171 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4173 xact_redo_abort(&xlrec->arec, xlrec->xid);
4174 RemoveTwoPhaseFile(xlrec->xid, false);
4177 elog(PANIC, "xact_redo: unknown op code %u", info);
4181 xact_desc_commit(char *buf, xl_xact_commit *xlrec)
4183 struct tm *tm = localtime(&xlrec->xtime);
4186 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4187 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4188 tm->tm_hour, tm->tm_min, tm->tm_sec);
4189 if (xlrec->nrels > 0)
4191 sprintf(buf + strlen(buf), "; rels:");
4192 for (i = 0; i < xlrec->nrels; i++)
4194 RelFileNode rnode = xlrec->xnodes[i];
4196 sprintf(buf + strlen(buf), " %u/%u/%u",
4197 rnode.spcNode, rnode.dbNode, rnode.relNode);
4200 if (xlrec->nsubxacts > 0)
4202 TransactionId *xacts = (TransactionId *)
4203 &xlrec->xnodes[xlrec->nrels];
4205 sprintf(buf + strlen(buf), "; subxacts:");
4206 for (i = 0; i < xlrec->nsubxacts; i++)
4207 sprintf(buf + strlen(buf), " %u", xacts[i]);
4212 xact_desc_abort(char *buf, xl_xact_abort *xlrec)
4214 struct tm *tm = localtime(&xlrec->xtime);
4217 sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4218 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4219 tm->tm_hour, tm->tm_min, tm->tm_sec);
4220 if (xlrec->nrels > 0)
4222 sprintf(buf + strlen(buf), "; rels:");
4223 for (i = 0; i < xlrec->nrels; i++)
4225 RelFileNode rnode = xlrec->xnodes[i];
4227 sprintf(buf + strlen(buf), " %u/%u/%u",
4228 rnode.spcNode, rnode.dbNode, rnode.relNode);
4231 if (xlrec->nsubxacts > 0)
4233 TransactionId *xacts = (TransactionId *)
4234 &xlrec->xnodes[xlrec->nrels];
4236 sprintf(buf + strlen(buf), "; subxacts:");
4237 for (i = 0; i < xlrec->nsubxacts; i++)
4238 sprintf(buf + strlen(buf), " %u", xacts[i]);
4243 xact_desc(char *buf, uint8 xl_info, char *rec)
4245 uint8 info = xl_info & ~XLR_INFO_MASK;
4247 if (info == XLOG_XACT_COMMIT)
4249 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4251 strcat(buf, "commit: ");
4252 xact_desc_commit(buf, xlrec);
4254 else if (info == XLOG_XACT_ABORT)
4256 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4258 strcat(buf, "abort: ");
4259 xact_desc_abort(buf, xlrec);
4261 else if (info == XLOG_XACT_PREPARE)
4263 strcat(buf, "prepare");
4265 else if (info == XLOG_XACT_COMMIT_PREPARED)
4267 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4269 sprintf(buf + strlen(buf), "commit %u: ", xlrec->xid);
4270 xact_desc_commit(buf, &xlrec->crec);
4272 else if (info == XLOG_XACT_ABORT_PREPARED)
4274 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4276 sprintf(buf + strlen(buf), "abort %u: ", xlrec->xid);
4277 xact_desc_abort(buf, &xlrec->arec);
4280 strcat(buf, "UNKNOWN");