1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2006, 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.224 2006/07/24 16:32:44 petere Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
37 #include "storage/fd.h"
38 #include "storage/lmgr.h"
39 #include "storage/procarray.h"
40 #include "storage/smgr.h"
41 #include "utils/flatfiles.h"
42 #include "utils/inval.h"
43 #include "utils/memutils.h"
44 #include "utils/relcache.h"
45 #include "utils/guc.h"
49 * User-tweakable parameters
51 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
54 bool DefaultXactReadOnly = false;
57 int CommitDelay = 0; /* precommit delay in microseconds */
58 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
62 * transaction states - transaction state from server perspective
64 typedef enum TransState
75 * transaction block states - transaction state of client queries
77 * Note: the subtransaction states are used only for non-topmost
78 * transactions; the others appear only in the topmost transaction.
80 typedef enum TBlockState
82 /* not-in-transaction-block states */
83 TBLOCK_DEFAULT, /* idle */
84 TBLOCK_STARTED, /* running single-query transaction */
86 /* transaction block states */
87 TBLOCK_BEGIN, /* starting transaction block */
88 TBLOCK_INPROGRESS, /* live transaction */
89 TBLOCK_END, /* COMMIT received */
90 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
91 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
92 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
93 TBLOCK_PREPARE, /* live xact, PREPARE received */
95 /* subtransaction states */
96 TBLOCK_SUBBEGIN, /* starting a subtransaction */
97 TBLOCK_SUBINPROGRESS, /* live subtransaction */
98 TBLOCK_SUBEND, /* RELEASE received */
99 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
100 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
101 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
102 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
103 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
107 * transaction state structure
109 typedef struct TransactionStateData
111 TransactionId transactionId; /* my XID, or Invalid if none */
112 SubTransactionId subTransactionId; /* my subxact ID */
113 char *name; /* savepoint name, if any */
114 int savepointLevel; /* savepoint level */
115 TransState state; /* low-level state */
116 TBlockState blockState; /* high-level state */
117 int nestingLevel; /* nest depth */
118 MemoryContext curTransactionContext; /* my xact-lifetime context */
119 ResourceOwner curTransactionOwner; /* my query resources */
120 List *childXids; /* subcommitted child XIDs */
121 Oid currentUser; /* subxact start current_user */
122 bool prevXactReadOnly; /* entry-time xact r/o state */
123 struct TransactionStateData *parent; /* back link to parent */
124 } TransactionStateData;
126 typedef TransactionStateData *TransactionState;
129 * childXids is currently implemented as an Oid List, relying on the
130 * assumption that TransactionIds are no wider than Oid. We use these
131 * macros to provide some isolation in case that changes in the future.
133 #define lfirst_xid(lc) ((TransactionId) lfirst_oid(lc))
134 #define lappend_xid(list, datum) lappend_oid(list, (Oid) (datum))
137 * CurrentTransactionState always points to the current transaction state
138 * block. It will point to TopTransactionStateData when not in a
139 * transaction at all, or when in a top-level transaction.
141 static TransactionStateData TopTransactionStateData = {
142 0, /* transaction id */
143 0, /* subtransaction id */
144 NULL, /* savepoint name */
145 0, /* savepoint level */
146 TRANS_DEFAULT, /* transaction state */
147 TBLOCK_DEFAULT, /* transaction block state from the client
149 0, /* nesting level */
150 NULL, /* cur transaction context */
151 NULL, /* cur transaction resource owner */
152 NIL, /* subcommitted child Xids */
153 0, /* entry-time current userid */
154 false, /* entry-time xact r/o state */
155 NULL /* link to parent state block */
158 static TransactionState CurrentTransactionState = &TopTransactionStateData;
161 * The subtransaction ID and command ID assignment counters are global
162 * to a whole transaction, so we do not keep them in the state stack.
164 static SubTransactionId currentSubTransactionId;
165 static CommandId currentCommandId;
168 * xactStartTimestamp is the value of transaction_timestamp().
169 * stmtStartTimestamp is the value of statement_timestamp().
170 * These do not change as we enter and exit subtransactions, so we don't
171 * keep them inside the TransactionState stack.
173 static TimestampTz xactStartTimestamp;
174 static TimestampTz stmtStartTimestamp;
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 * GetCurrentStatementStartTimestamp
434 GetCurrentStatementStartTimestamp(void)
436 return stmtStartTimestamp;
440 * SetCurrentStatementStartTimestamp
443 SetCurrentStatementStartTimestamp(void)
445 stmtStartTimestamp = GetCurrentTimestamp();
449 * GetCurrentTransactionNestLevel
451 * Note: this will return zero when not inside any transaction, one when
452 * inside a top-level transaction, etc.
455 GetCurrentTransactionNestLevel(void)
457 TransactionState s = CurrentTransactionState;
459 return s->nestingLevel;
464 * TransactionIdIsCurrentTransactionId
467 TransactionIdIsCurrentTransactionId(TransactionId xid)
472 * We always say that BootstrapTransactionId is "not my transaction ID"
473 * even when it is (ie, during bootstrap). Along with the fact that
474 * transam.c always treats BootstrapTransactionId as already committed,
475 * this causes the tqual.c routines to see all tuples as committed, which
476 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
477 * it never updates or deletes them, so all tuples can be presumed good
480 if (xid == BootstrapTransactionId)
484 * We will return true for the Xid of the current subtransaction, any of
485 * its subcommitted children, any of its parents, or any of their
486 * previously subcommitted children. However, a transaction being aborted
487 * is no longer "current", even though it may still have an entry on the
490 for (s = CurrentTransactionState; s != NULL; s = s->parent)
494 if (s->state == TRANS_ABORT)
496 if (!TransactionIdIsValid(s->transactionId))
497 continue; /* it can't have any child XIDs either */
498 if (TransactionIdEquals(xid, s->transactionId))
500 foreach(cell, s->childXids)
502 if (TransactionIdEquals(xid, lfirst_xid(cell)))
512 * CommandCounterIncrement
515 CommandCounterIncrement(void)
517 currentCommandId += 1;
518 if (currentCommandId == FirstCommandId) /* check for overflow */
520 currentCommandId -= 1;
522 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
523 errmsg("cannot have more than 2^32-1 commands in a transaction")));
526 /* Propagate new command ID into static snapshots, if set */
527 if (SerializableSnapshot)
528 SerializableSnapshot->curcid = currentCommandId;
530 LatestSnapshot->curcid = currentCommandId;
533 * make cache changes visible to me.
535 AtCommit_LocalCache();
540 /* ----------------------------------------------------------------
541 * StartTransaction stuff
542 * ----------------------------------------------------------------
551 AcceptInvalidationMessages();
560 TransactionState s = CurrentTransactionState;
563 * We shouldn't have a transaction context already.
565 Assert(TopTransactionContext == NULL);
568 * Create a toplevel context for the transaction.
570 TopTransactionContext =
571 AllocSetContextCreate(TopMemoryContext,
572 "TopTransactionContext",
573 ALLOCSET_DEFAULT_MINSIZE,
574 ALLOCSET_DEFAULT_INITSIZE,
575 ALLOCSET_DEFAULT_MAXSIZE);
578 * In a top-level transaction, CurTransactionContext is the same as
579 * TopTransactionContext.
581 CurTransactionContext = TopTransactionContext;
582 s->curTransactionContext = CurTransactionContext;
584 /* Make the CurTransactionContext active. */
585 MemoryContextSwitchTo(CurTransactionContext);
589 * AtStart_ResourceOwner
592 AtStart_ResourceOwner(void)
594 TransactionState s = CurrentTransactionState;
597 * We shouldn't have a transaction resource owner already.
599 Assert(TopTransactionResourceOwner == NULL);
602 * Create a toplevel resource owner for the transaction.
604 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
606 TopTransactionResourceOwner = s->curTransactionOwner;
607 CurTransactionResourceOwner = s->curTransactionOwner;
608 CurrentResourceOwner = s->curTransactionOwner;
611 /* ----------------------------------------------------------------
612 * StartSubTransaction stuff
613 * ----------------------------------------------------------------
620 AtSubStart_Memory(void)
622 TransactionState s = CurrentTransactionState;
624 Assert(CurTransactionContext != NULL);
627 * Create a CurTransactionContext, which will be used to hold data that
628 * survives subtransaction commit but disappears on subtransaction abort.
629 * We make it a child of the immediate parent's CurTransactionContext.
631 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
632 "CurTransactionContext",
633 ALLOCSET_DEFAULT_MINSIZE,
634 ALLOCSET_DEFAULT_INITSIZE,
635 ALLOCSET_DEFAULT_MAXSIZE);
636 s->curTransactionContext = CurTransactionContext;
638 /* Make the CurTransactionContext active. */
639 MemoryContextSwitchTo(CurTransactionContext);
643 * AtSubStart_ResourceOwner
646 AtSubStart_ResourceOwner(void)
648 TransactionState s = CurrentTransactionState;
650 Assert(s->parent != NULL);
653 * Create a resource owner for the subtransaction. We make it a child of
654 * the immediate parent's resource owner.
656 s->curTransactionOwner =
657 ResourceOwnerCreate(s->parent->curTransactionOwner,
660 CurTransactionResourceOwner = s->curTransactionOwner;
661 CurrentResourceOwner = s->curTransactionOwner;
664 /* ----------------------------------------------------------------
665 * CommitTransaction stuff
666 * ----------------------------------------------------------------
670 * RecordTransactionCommit
673 RecordTransactionCommit(void)
678 TransactionId *children;
680 /* Get data needed for commit record */
681 nrels = smgrGetPendingDeletes(true, &rels);
682 nchildren = xactGetCommittedChildren(&children);
685 * If we made neither any XLOG entries nor any temp-rel updates, and have
686 * no files to be deleted, we can omit recording the transaction commit at
687 * all. (This test includes the effects of subtransactions, so the
688 * presence of committed subxacts need not alone force a write.)
690 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
692 TransactionId xid = GetCurrentTransactionId();
696 /* Tell bufmgr and smgr to prepare for commit */
699 START_CRIT_SECTION();
702 * If our transaction made any transaction-controlled XLOG entries, we
703 * need to lock out checkpoint start between writing our XLOG record
704 * and updating pg_clog. Otherwise it is possible for the checkpoint
705 * to set REDO after the XLOG record but fail to flush the pg_clog
706 * update to disk, leading to loss of the transaction commit if we
707 * crash a little later. Slightly klugy fix for problem discovered
710 * (If it made no transaction-controlled XLOG entries, its XID appears
711 * nowhere in permanent storage, so no one else will ever care if it
712 * committed; so it doesn't matter if we lose the commit flag.)
714 * Note we only need a shared lock.
716 madeTCentries = (MyLastRecPtr.xrecoff != 0);
718 LWLockAcquire(CheckpointStartLock, LW_SHARED);
721 * We only need to log the commit in XLOG if the transaction made any
722 * transaction-controlled XLOG entries or will delete files.
724 if (madeTCentries || nrels > 0)
726 XLogRecData rdata[3];
728 xl_xact_commit xlrec;
730 xlrec.xtime = time(NULL);
732 xlrec.nsubxacts = nchildren;
733 rdata[0].data = (char *) (&xlrec);
734 rdata[0].len = MinSizeOfXactCommit;
735 rdata[0].buffer = InvalidBuffer;
736 /* dump rels to delete */
739 rdata[0].next = &(rdata[1]);
740 rdata[1].data = (char *) rels;
741 rdata[1].len = nrels * sizeof(RelFileNode);
742 rdata[1].buffer = InvalidBuffer;
745 /* dump committed child Xids */
748 rdata[lastrdata].next = &(rdata[2]);
749 rdata[2].data = (char *) children;
750 rdata[2].len = nchildren * sizeof(TransactionId);
751 rdata[2].buffer = InvalidBuffer;
754 rdata[lastrdata].next = NULL;
756 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
760 /* Just flush through last record written by me */
761 recptr = ProcLastRecEnd;
765 * We must flush our XLOG entries to disk if we made any XLOG entries,
766 * whether in or out of transaction control. For example, if we
767 * reported a nextval() result to the client, this ensures that any
768 * XLOG record generated by nextval will hit the disk before we report
769 * the transaction committed.
771 * Note: if we generated a commit record above, MyXactMadeXLogEntry
772 * will certainly be set now.
774 if (MyXactMadeXLogEntry)
777 * Sleep before flush! So we can flush more than one commit
778 * records per single fsync. (The idea is some other backend may
779 * do the XLogFlush while we're sleeping. This needs work still,
780 * because on most Unixen, the minimum select() delay is 10msec or
781 * more, which is way too long.)
783 * We do not sleep if enableFsync is not turned on, nor if there
784 * are fewer than CommitSiblings other backends with active
787 if (CommitDelay > 0 && enableFsync &&
788 CountActiveBackends() >= CommitSiblings)
789 pg_usleep(CommitDelay);
795 * We must mark the transaction committed in clog if its XID appears
796 * either in permanent rels or in local temporary rels. We test this
797 * by seeing if we made transaction-controlled entries *OR* local-rel
798 * tuple updates. Note that if we made only the latter, we have not
799 * emitted an XLOG record for our commit, and so in the event of a
800 * crash the clog update might be lost. This is okay because no one
801 * else will ever care whether we committed.
803 if (madeTCentries || MyXactMadeTempRelUpdate)
805 TransactionIdCommit(xid);
806 /* to avoid race conditions, the parent must commit first */
807 TransactionIdCommitTree(nchildren, children);
810 /* Unlock checkpoint lock if we acquired it */
812 LWLockRelease(CheckpointStartLock);
817 /* Break the chain of back-links in the XLOG records I output */
818 MyLastRecPtr.xrecoff = 0;
819 MyXactMadeXLogEntry = false;
820 MyXactMadeTempRelUpdate = false;
822 /* And clean up local data */
831 * AtCommit_LocalCache
834 AtCommit_LocalCache(void)
837 * Make catalog changes visible to me for the next command.
839 CommandEndInvalidationMessages();
846 AtCommit_Memory(void)
849 * Now that we're "out" of a transaction, have the system allocate things
850 * in the top memory context instead of per-transaction contexts.
852 MemoryContextSwitchTo(TopMemoryContext);
855 * Release all transaction-local memory.
857 Assert(TopTransactionContext != NULL);
858 MemoryContextDelete(TopTransactionContext);
859 TopTransactionContext = NULL;
860 CurTransactionContext = NULL;
861 CurrentTransactionState->curTransactionContext = NULL;
864 /* ----------------------------------------------------------------
865 * CommitSubTransaction stuff
866 * ----------------------------------------------------------------
873 AtSubCommit_Memory(void)
875 TransactionState s = CurrentTransactionState;
877 Assert(s->parent != NULL);
879 /* Return to parent transaction level's memory context. */
880 CurTransactionContext = s->parent->curTransactionContext;
881 MemoryContextSwitchTo(CurTransactionContext);
884 * Ordinarily we cannot throw away the child's CurTransactionContext,
885 * since the data it contains will be needed at upper commit. However, if
886 * there isn't actually anything in it, we can throw it away. This avoids
887 * a small memory leak in the common case of "trivial" subxacts.
889 if (MemoryContextIsEmpty(s->curTransactionContext))
891 MemoryContextDelete(s->curTransactionContext);
892 s->curTransactionContext = NULL;
897 * AtSubCommit_childXids
899 * Pass my own XID and my child XIDs up to my parent as committed children.
902 AtSubCommit_childXids(void)
904 TransactionState s = CurrentTransactionState;
905 MemoryContext old_cxt;
907 Assert(s->parent != NULL);
910 * We keep the child-XID lists in TopTransactionContext; this avoids
911 * setting up child-transaction contexts for what might be just a few
912 * bytes of grandchild XIDs.
914 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
916 s->parent->childXids = lappend_xid(s->parent->childXids,
919 if (s->childXids != NIL)
921 s->parent->childXids = list_concat(s->parent->childXids,
925 * list_concat doesn't free the list header for the second list; do so
926 * here to avoid memory leakage (kluge)
932 MemoryContextSwitchTo(old_cxt);
936 * RecordSubTransactionCommit
939 RecordSubTransactionCommit(void)
942 * We do not log the subcommit in XLOG; it doesn't matter until the
943 * top-level transaction commits.
945 * We must mark the subtransaction subcommitted in clog if its XID appears
946 * either in permanent rels or in local temporary rels. We test this by
947 * seeing if we made transaction-controlled entries *OR* local-rel tuple
948 * updates. (The test here actually covers the entire transaction tree so
949 * far, so it may mark subtransactions that don't really need it, but it's
950 * probably not worth being tenser. Note that if a prior subtransaction
951 * dirtied these variables, then RecordTransactionCommit will have to do
952 * the full pushup anyway...)
954 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
956 TransactionId xid = GetCurrentTransactionId();
958 /* XXX does this really need to be a critical section? */
959 START_CRIT_SECTION();
961 /* Record subtransaction subcommit */
962 TransactionIdSubCommit(xid);
968 /* ----------------------------------------------------------------
969 * AbortTransaction stuff
970 * ----------------------------------------------------------------
974 * RecordTransactionAbort
977 RecordTransactionAbort(void)
982 TransactionId *children;
984 /* Get data needed for abort record */
985 nrels = smgrGetPendingDeletes(false, &rels);
986 nchildren = xactGetCommittedChildren(&children);
989 * If we made neither any transaction-controlled XLOG entries nor any
990 * temp-rel updates, and are not going to delete any files, we can omit
991 * recording the transaction abort at all. No one will ever care that it
992 * aborted. (These tests cover our whole transaction tree.)
994 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
996 TransactionId xid = GetCurrentTransactionId();
999 * Catch the scenario where we aborted partway through
1000 * RecordTransactionCommit ...
1002 if (TransactionIdDidCommit(xid))
1003 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1005 START_CRIT_SECTION();
1008 * We only need to log the abort in XLOG if the transaction made any
1009 * transaction-controlled XLOG entries or will delete files. (If it
1010 * made no transaction-controlled XLOG entries, its XID appears
1011 * nowhere in permanent storage, so no one else will ever care if it
1014 * We do not flush XLOG to disk unless deleting files, since the
1015 * default assumption after a crash would be that we aborted, anyway.
1016 * For the same reason, we don't need to worry about interlocking
1017 * against checkpoint start.
1019 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1021 XLogRecData rdata[3];
1023 xl_xact_abort xlrec;
1026 xlrec.xtime = time(NULL);
1027 xlrec.nrels = nrels;
1028 xlrec.nsubxacts = nchildren;
1029 rdata[0].data = (char *) (&xlrec);
1030 rdata[0].len = MinSizeOfXactAbort;
1031 rdata[0].buffer = InvalidBuffer;
1032 /* dump rels to delete */
1035 rdata[0].next = &(rdata[1]);
1036 rdata[1].data = (char *) rels;
1037 rdata[1].len = nrels * sizeof(RelFileNode);
1038 rdata[1].buffer = InvalidBuffer;
1041 /* dump committed child Xids */
1044 rdata[lastrdata].next = &(rdata[2]);
1045 rdata[2].data = (char *) children;
1046 rdata[2].len = nchildren * sizeof(TransactionId);
1047 rdata[2].buffer = InvalidBuffer;
1050 rdata[lastrdata].next = NULL;
1052 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1054 /* Must flush if we are deleting files... */
1060 * Mark the transaction aborted in clog. This is not absolutely
1061 * necessary but we may as well do it while we are here.
1063 * The ordering here isn't critical but it seems best to mark the
1064 * parent first. This assures an atomic transition of all the
1065 * subtransactions to aborted state from the point of view of
1066 * concurrent TransactionIdDidAbort calls.
1068 TransactionIdAbort(xid);
1069 TransactionIdAbortTree(nchildren, children);
1074 /* Break the chain of back-links in the XLOG records I output */
1075 MyLastRecPtr.xrecoff = 0;
1076 MyXactMadeXLogEntry = false;
1077 MyXactMadeTempRelUpdate = false;
1079 /* And clean up local data */
1090 AtAbort_Memory(void)
1093 * Make sure we are in a valid context (not a child of
1094 * TopTransactionContext...). Note that it is possible for this code to
1095 * be called when we aren't in a transaction at all; go directly to
1096 * TopMemoryContext in that case.
1098 if (TopTransactionContext != NULL)
1100 MemoryContextSwitchTo(TopTransactionContext);
1103 * We do not want to destroy the transaction's global state yet, so we
1104 * can't free any memory here.
1108 MemoryContextSwitchTo(TopMemoryContext);
1115 AtSubAbort_Memory(void)
1117 Assert(TopTransactionContext != NULL);
1119 MemoryContextSwitchTo(TopTransactionContext);
1124 * AtAbort_ResourceOwner
1127 AtAbort_ResourceOwner(void)
1130 * Make sure we have a valid ResourceOwner, if possible (else it will be
1131 * NULL, which is OK)
1133 CurrentResourceOwner = TopTransactionResourceOwner;
1137 * AtSubAbort_ResourceOwner
1140 AtSubAbort_ResourceOwner(void)
1142 TransactionState s = CurrentTransactionState;
1144 /* Make sure we have a valid ResourceOwner */
1145 CurrentResourceOwner = s->curTransactionOwner;
1150 * AtSubAbort_childXids
1153 AtSubAbort_childXids(void)
1155 TransactionState s = CurrentTransactionState;
1158 * We keep the child-XID lists in TopTransactionContext (see
1159 * AtSubCommit_childXids). This means we'd better free the list
1160 * explicitly at abort to avoid leakage.
1162 list_free(s->childXids);
1167 * RecordSubTransactionAbort
1170 RecordSubTransactionAbort(void)
1174 TransactionId xid = GetCurrentTransactionId();
1176 TransactionId *children;
1178 /* Get data needed for abort record */
1179 nrels = smgrGetPendingDeletes(false, &rels);
1180 nchildren = xactGetCommittedChildren(&children);
1183 * If we made neither any transaction-controlled XLOG entries nor any
1184 * temp-rel updates, and are not going to delete any files, we can omit
1185 * recording the transaction abort at all. No one will ever care that it
1186 * aborted. (These tests cover our whole transaction tree, and therefore
1187 * may mark subxacts that don't really need it, but it's probably not
1188 * worth being tenser.)
1190 * In this case we needn't worry about marking subcommitted children as
1191 * aborted, because they didn't mark themselves as subcommitted in the
1192 * first place; see the optimization in RecordSubTransactionCommit.
1194 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1196 START_CRIT_SECTION();
1199 * We only need to log the abort in XLOG if the transaction made any
1200 * transaction-controlled XLOG entries or will delete files.
1202 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1204 XLogRecData rdata[3];
1206 xl_xact_abort xlrec;
1209 xlrec.xtime = time(NULL);
1210 xlrec.nrels = nrels;
1211 xlrec.nsubxacts = nchildren;
1212 rdata[0].data = (char *) (&xlrec);
1213 rdata[0].len = MinSizeOfXactAbort;
1214 rdata[0].buffer = InvalidBuffer;
1215 /* dump rels to delete */
1218 rdata[0].next = &(rdata[1]);
1219 rdata[1].data = (char *) rels;
1220 rdata[1].len = nrels * sizeof(RelFileNode);
1221 rdata[1].buffer = InvalidBuffer;
1224 /* dump committed child Xids */
1227 rdata[lastrdata].next = &(rdata[2]);
1228 rdata[2].data = (char *) children;
1229 rdata[2].len = nchildren * sizeof(TransactionId);
1230 rdata[2].buffer = InvalidBuffer;
1233 rdata[lastrdata].next = NULL;
1235 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1237 /* Must flush if we are deleting files... */
1243 * Mark the transaction aborted in clog. This is not absolutely
1244 * necessary but XactLockTableWait makes use of it to avoid waiting
1245 * for already-aborted subtransactions.
1247 TransactionIdAbort(xid);
1248 TransactionIdAbortTree(nchildren, children);
1254 * We can immediately remove failed XIDs from PGPROC's cache of running
1255 * child XIDs. It's easiest to do it here while we have the child XID
1256 * array at hand, even though in the main-transaction case the equivalent
1257 * work happens just after return from RecordTransactionAbort.
1259 XidCacheRemoveRunningXids(xid, nchildren, children);
1261 /* And clean up local data */
1268 /* ----------------------------------------------------------------
1269 * CleanupTransaction stuff
1270 * ----------------------------------------------------------------
1277 AtCleanup_Memory(void)
1280 * Now that we're "out" of a transaction, have the system allocate things
1281 * in the top memory context instead of per-transaction contexts.
1283 MemoryContextSwitchTo(TopMemoryContext);
1285 Assert(CurrentTransactionState->parent == NULL);
1288 * Release all transaction-local memory.
1290 if (TopTransactionContext != NULL)
1291 MemoryContextDelete(TopTransactionContext);
1292 TopTransactionContext = NULL;
1293 CurTransactionContext = NULL;
1294 CurrentTransactionState->curTransactionContext = NULL;
1298 /* ----------------------------------------------------------------
1299 * CleanupSubTransaction stuff
1300 * ----------------------------------------------------------------
1304 * AtSubCleanup_Memory
1307 AtSubCleanup_Memory(void)
1309 TransactionState s = CurrentTransactionState;
1311 Assert(s->parent != NULL);
1313 /* Make sure we're not in an about-to-be-deleted context */
1314 MemoryContextSwitchTo(s->parent->curTransactionContext);
1315 CurTransactionContext = s->parent->curTransactionContext;
1318 * Delete the subxact local memory contexts. Its CurTransactionContext can
1319 * go too (note this also kills CurTransactionContexts from any children
1322 if (s->curTransactionContext)
1323 MemoryContextDelete(s->curTransactionContext);
1324 s->curTransactionContext = NULL;
1327 /* ----------------------------------------------------------------
1328 * interface routines
1329 * ----------------------------------------------------------------
1336 StartTransaction(void)
1341 * Let's just make sure the state stack is empty
1343 s = &TopTransactionStateData;
1344 CurrentTransactionState = s;
1347 * check the current transaction state
1349 if (s->state != TRANS_DEFAULT)
1350 elog(WARNING, "StartTransaction while in %s state",
1351 TransStateAsString(s->state));
1354 * set the current transaction state information appropriately during
1357 s->state = TRANS_START;
1358 s->transactionId = InvalidTransactionId; /* until assigned */
1361 * Make sure we've freed any old snapshot, and reset xact state variables
1364 XactIsoLevel = DefaultXactIsoLevel;
1365 XactReadOnly = DefaultXactReadOnly;
1368 * reinitialize within-transaction counters
1370 s->subTransactionId = TopSubTransactionId;
1371 currentSubTransactionId = TopSubTransactionId;
1372 currentCommandId = FirstCommandId;
1375 * must initialize resource-management stuff first
1378 AtStart_ResourceOwner();
1381 * generate a new transaction id
1383 s->transactionId = GetNewTransactionId(false);
1385 XactLockTableInsert(s->transactionId);
1387 PG_TRACE1 (transaction__start, s->transactionId);
1390 * set transaction_timestamp() (a/k/a now()). We want this to be the
1391 * same as the first command's statement_timestamp(), so don't do a
1392 * fresh GetCurrentTimestamp() call (which'd be expensive anyway).
1394 xactStartTimestamp = stmtStartTimestamp;
1397 * initialize current transaction state fields
1399 s->nestingLevel = 1;
1403 * You might expect to see "s->currentUser = GetUserId();" here, but you
1404 * won't because it doesn't work during startup; the userid isn't set yet
1405 * during a backend's first transaction start. We only use the
1406 * currentUser field in sub-transaction state structs.
1408 * prevXactReadOnly is also valid only in sub-transactions.
1412 * initialize other subsystems for new transaction
1416 AfterTriggerBeginXact();
1419 * done with start processing, set current transaction state to "in
1422 s->state = TRANS_INPROGRESS;
1424 ShowTransactionState("StartTransaction");
1431 * NB: if you change this routine, better look at PrepareTransaction too!
1434 CommitTransaction(void)
1436 TransactionState s = CurrentTransactionState;
1438 ShowTransactionState("CommitTransaction");
1441 * check the current transaction state
1443 if (s->state != TRANS_INPROGRESS)
1444 elog(WARNING, "CommitTransaction while in %s state",
1445 TransStateAsString(s->state));
1446 Assert(s->parent == NULL);
1449 * Do pre-commit processing (most of this stuff requires database access,
1450 * and in fact could still cause an error...)
1452 * It is possible for CommitHoldablePortals to invoke functions that queue
1453 * deferred triggers, and it's also possible that triggers create holdable
1454 * cursors. So we have to loop until there's nothing left to do.
1459 * Fire all currently pending deferred triggers.
1461 AfterTriggerFireDeferred();
1464 * Convert any open holdable cursors into static portals. If there
1465 * weren't any, we are done ... otherwise loop back to check if they
1466 * queued deferred triggers. Lather, rinse, repeat.
1468 if (!CommitHoldablePortals())
1472 /* Now we can shut down the deferred-trigger manager */
1473 AfterTriggerEndXact(true);
1475 /* Close any open regular cursors */
1479 * Let ON COMMIT management do its thing (must happen after closing
1480 * cursors, to avoid dangling-reference problems)
1482 PreCommit_on_commit_actions();
1484 /* close large objects before lower-level cleanup */
1485 AtEOXact_LargeObject(true);
1487 /* NOTIFY commit must come before lower-level cleanup */
1491 * Update flat files if we changed pg_database, pg_authid or
1492 * pg_auth_members. This should be the last step before commit.
1494 AtEOXact_UpdateFlatFiles(true);
1496 /* Prevent cancel/die interrupt while cleaning up */
1500 * set the current transaction state information appropriately during
1503 s->state = TRANS_COMMIT;
1506 * Here is where we really truly commit.
1508 RecordTransactionCommit();
1511 * Let others know about no transaction in progress by me. Note that
1512 * this must be done _before_ releasing locks we hold and _after_
1513 * RecordTransactionCommit.
1515 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1516 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1517 * xid 1 is doing commit while xid 2 gets snapshot.
1518 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1519 * xid 0 as running as well, or it will be able to see two tuple versions
1520 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1523 * Note: MyProc may be null during bootstrap.
1528 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1529 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1530 MyProc->xid = InvalidTransactionId;
1531 MyProc->xmin = InvalidTransactionId;
1533 /* Clear the subtransaction-XID cache too while holding the lock */
1534 MyProc->subxids.nxids = 0;
1535 MyProc->subxids.overflowed = false;
1537 LWLockRelease(ProcArrayLock);
1540 PG_TRACE1 (transaction__commit, s->transactionId);
1543 * This is all post-commit cleanup. Note that if an error is raised here,
1544 * it's too late to abort the transaction. This should be just
1545 * noncritical resource releasing.
1547 * The ordering of operations is not entirely random. The idea is:
1548 * release resources visible to other backends (eg, files, buffer pins);
1549 * then release locks; then release backend-local resources. We want to
1550 * release locks at the point where any backend waiting for us will see
1551 * our transaction as being fully cleaned up.
1553 * Resources that can be associated with individual queries are handled by
1554 * the ResourceOwner mechanism. The other calls here are for backend-wide
1558 CallXactCallbacks(XACT_EVENT_COMMIT);
1560 ResourceOwnerRelease(TopTransactionResourceOwner,
1561 RESOURCE_RELEASE_BEFORE_LOCKS,
1564 /* Check we've released all buffer pins */
1565 AtEOXact_Buffers(true);
1567 /* Clean up the relation cache */
1568 AtEOXact_RelationCache(true);
1571 * Make catalog changes visible to all backends. This has to happen after
1572 * relcache references are dropped (see comments for
1573 * AtEOXact_RelationCache), but before locks are released (if anyone is
1574 * waiting for lock on a relation we've modified, we want them to know
1575 * about the catalog change before they start using the relation).
1577 AtEOXact_Inval(true);
1580 * Likewise, dropping of files deleted during the transaction is best done
1581 * after releasing relcache and buffer pins. (This is not strictly
1582 * necessary during commit, since such pins should have been released
1583 * already, but this ordering is definitely critical during abort.)
1585 smgrDoPendingDeletes(true);
1587 AtEOXact_MultiXact();
1589 ResourceOwnerRelease(TopTransactionResourceOwner,
1590 RESOURCE_RELEASE_LOCKS,
1592 ResourceOwnerRelease(TopTransactionResourceOwner,
1593 RESOURCE_RELEASE_AFTER_LOCKS,
1596 /* Check we've released all catcache entries */
1597 AtEOXact_CatCache(true);
1599 AtEOXact_GUC(true, false);
1601 AtEOXact_on_commit_actions(true);
1602 AtEOXact_Namespace(true);
1603 /* smgrcommit already done */
1605 pgstat_count_xact_commit();
1607 CurrentResourceOwner = NULL;
1608 ResourceOwnerDelete(TopTransactionResourceOwner);
1609 s->curTransactionOwner = NULL;
1610 CurTransactionResourceOwner = NULL;
1611 TopTransactionResourceOwner = NULL;
1615 s->transactionId = InvalidTransactionId;
1616 s->subTransactionId = InvalidSubTransactionId;
1617 s->nestingLevel = 0;
1621 * done with commit processing, set current transaction state back to
1624 s->state = TRANS_DEFAULT;
1626 RESUME_INTERRUPTS();
1631 * PrepareTransaction
1633 * NB: if you change this routine, better look at CommitTransaction too!
1636 PrepareTransaction(void)
1638 TransactionState s = CurrentTransactionState;
1639 TransactionId xid = GetCurrentTransactionId();
1640 GlobalTransaction gxact;
1641 TimestampTz prepared_at;
1643 ShowTransactionState("PrepareTransaction");
1646 * check the current transaction state
1648 if (s->state != TRANS_INPROGRESS)
1649 elog(WARNING, "PrepareTransaction while in %s state",
1650 TransStateAsString(s->state));
1651 Assert(s->parent == NULL);
1654 * Do pre-commit processing (most of this stuff requires database access,
1655 * and in fact could still cause an error...)
1657 * It is possible for PrepareHoldablePortals to invoke functions that
1658 * queue deferred triggers, and it's also possible that triggers create
1659 * holdable cursors. So we have to loop until there's nothing left to do.
1664 * Fire all currently pending deferred triggers.
1666 AfterTriggerFireDeferred();
1669 * Convert any open holdable cursors into static portals. If there
1670 * weren't any, we are done ... otherwise loop back to check if they
1671 * queued deferred triggers. Lather, rinse, repeat.
1673 if (!PrepareHoldablePortals())
1677 /* Now we can shut down the deferred-trigger manager */
1678 AfterTriggerEndXact(true);
1680 /* Close any open regular cursors */
1684 * Let ON COMMIT management do its thing (must happen after closing
1685 * cursors, to avoid dangling-reference problems)
1687 PreCommit_on_commit_actions();
1689 /* close large objects before lower-level cleanup */
1690 AtEOXact_LargeObject(true);
1692 /* NOTIFY and flatfiles will be handled below */
1694 /* Prevent cancel/die interrupt while cleaning up */
1698 * set the current transaction state information appropriately during
1699 * prepare processing
1701 s->state = TRANS_PREPARE;
1703 prepared_at = GetCurrentTimestamp();
1705 /* Tell bufmgr and smgr to prepare for commit */
1709 * Reserve the GID for this transaction. This could fail if the requested
1710 * GID is invalid or already in use.
1712 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1713 GetUserId(), MyDatabaseId);
1717 * Collect data for the 2PC state file. Note that in general, no actual
1718 * state change should happen in the called modules during this step,
1719 * since it's still possible to fail before commit, and in that case we
1720 * want transaction abort to be able to clean up. (In particular, the
1721 * AtPrepare routines may error out if they find cases they cannot
1722 * handle.) State cleanup should happen in the PostPrepare routines
1723 * below. However, some modules can go ahead and clear state here because
1724 * they wouldn't do anything with it during abort anyway.
1726 * Note: because the 2PC state file records will be replayed in the same
1727 * order they are made, the order of these calls has to match the order in
1728 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1729 * PREPARED; in particular, pay attention to whether things should happen
1730 * before or after releasing the transaction's locks.
1732 StartPrepare(gxact);
1735 AtPrepare_UpdateFlatFiles();
1740 * Here is where we really truly prepare.
1742 * We have to record transaction prepares even if we didn't make any
1743 * updates, because the transaction manager might get confused if we lose
1744 * a global transaction.
1749 * Now we clean up backend-internal state and release internal resources.
1752 /* Break the chain of back-links in the XLOG records I output */
1753 MyLastRecPtr.xrecoff = 0;
1754 MyXactMadeXLogEntry = false;
1755 MyXactMadeTempRelUpdate = false;
1758 * Let others know about no transaction in progress by me. This has to be
1759 * done *after* the prepared transaction has been marked valid, else
1760 * someone may think it is unlocked and recyclable.
1763 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1764 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1765 MyProc->xid = InvalidTransactionId;
1766 MyProc->xmin = InvalidTransactionId;
1768 /* Clear the subtransaction-XID cache too while holding the lock */
1769 MyProc->subxids.nxids = 0;
1770 MyProc->subxids.overflowed = false;
1772 LWLockRelease(ProcArrayLock);
1775 * This is all post-transaction cleanup. Note that if an error is raised
1776 * here, it's too late to abort the transaction. This should be just
1777 * noncritical resource releasing. See notes in CommitTransaction.
1780 CallXactCallbacks(XACT_EVENT_PREPARE);
1782 ResourceOwnerRelease(TopTransactionResourceOwner,
1783 RESOURCE_RELEASE_BEFORE_LOCKS,
1786 /* Check we've released all buffer pins */
1787 AtEOXact_Buffers(true);
1789 /* Clean up the relation cache */
1790 AtEOXact_RelationCache(true);
1792 /* notify and flatfiles don't need a postprepare call */
1794 PostPrepare_Inval();
1798 AtEOXact_MultiXact();
1800 PostPrepare_Locks(xid);
1802 ResourceOwnerRelease(TopTransactionResourceOwner,
1803 RESOURCE_RELEASE_LOCKS,
1805 ResourceOwnerRelease(TopTransactionResourceOwner,
1806 RESOURCE_RELEASE_AFTER_LOCKS,
1809 /* Check we've released all catcache entries */
1810 AtEOXact_CatCache(true);
1812 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1813 AtEOXact_GUC(true, false);
1815 AtEOXact_on_commit_actions(true);
1816 AtEOXact_Namespace(true);
1817 /* smgrcommit already done */
1820 CurrentResourceOwner = NULL;
1821 ResourceOwnerDelete(TopTransactionResourceOwner);
1822 s->curTransactionOwner = NULL;
1823 CurTransactionResourceOwner = NULL;
1824 TopTransactionResourceOwner = NULL;
1828 s->transactionId = InvalidTransactionId;
1829 s->subTransactionId = InvalidSubTransactionId;
1830 s->nestingLevel = 0;
1834 * done with 1st phase commit processing, set current transaction state
1837 s->state = TRANS_DEFAULT;
1839 RESUME_INTERRUPTS();
1847 AbortTransaction(void)
1849 TransactionState s = CurrentTransactionState;
1851 /* Prevent cancel/die interrupt while cleaning up */
1855 * Release any LW locks we might be holding as quickly as possible.
1856 * (Regular locks, however, must be held till we finish aborting.)
1857 * Releasing LW locks is critical since we might try to grab them again
1858 * while cleaning up!
1862 /* Clean up buffer I/O and buffer context locks, too */
1867 * Also clean up any open wait for lock, since the lock manager will choke
1868 * if we try to wait for another lock before doing this.
1873 * check the current transaction state
1875 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1876 elog(WARNING, "AbortTransaction while in %s state",
1877 TransStateAsString(s->state));
1878 Assert(s->parent == NULL);
1881 * set the current transaction state information appropriately during the
1884 s->state = TRANS_ABORT;
1886 /* Make sure we have a valid memory context and resource owner */
1888 AtAbort_ResourceOwner();
1891 * Reset user id which might have been changed transiently. We cannot use
1892 * s->currentUser, since it may not be set yet; instead rely on internal
1893 * state of miscinit.c.
1895 * (Note: it is not necessary to restore session authorization here
1896 * because that can only be changed via GUC, and GUC will take care of
1897 * rolling it back if need be. However, an error within a SECURITY
1898 * DEFINER function could send control here with the wrong current
1904 * do abort processing
1906 AfterTriggerEndXact(false);
1908 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1910 AtEOXact_UpdateFlatFiles(false);
1913 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1914 * far as assigning an XID to advertise).
1916 if (TransactionIdIsValid(s->transactionId))
1917 RecordTransactionAbort();
1920 * Let others know about no transaction in progress by me. Note that this
1921 * must be done _before_ releasing locks we hold and _after_
1922 * RecordTransactionAbort.
1926 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1927 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1928 MyProc->xid = InvalidTransactionId;
1929 MyProc->xmin = InvalidTransactionId;
1931 /* Clear the subtransaction-XID cache too while holding the lock */
1932 MyProc->subxids.nxids = 0;
1933 MyProc->subxids.overflowed = false;
1935 LWLockRelease(ProcArrayLock);
1938 PG_TRACE1 (transaction__abort, s->transactionId);
1941 * Post-abort cleanup. See notes in CommitTransaction() concerning
1945 CallXactCallbacks(XACT_EVENT_ABORT);
1947 ResourceOwnerRelease(TopTransactionResourceOwner,
1948 RESOURCE_RELEASE_BEFORE_LOCKS,
1950 AtEOXact_Buffers(false);
1951 AtEOXact_RelationCache(false);
1952 AtEOXact_Inval(false);
1953 smgrDoPendingDeletes(false);
1954 AtEOXact_MultiXact();
1955 ResourceOwnerRelease(TopTransactionResourceOwner,
1956 RESOURCE_RELEASE_LOCKS,
1958 ResourceOwnerRelease(TopTransactionResourceOwner,
1959 RESOURCE_RELEASE_AFTER_LOCKS,
1961 AtEOXact_CatCache(false);
1963 AtEOXact_GUC(false, false);
1964 AtEOXact_SPI(false);
1965 AtEOXact_on_commit_actions(false);
1966 AtEOXact_Namespace(false);
1969 pgstat_count_xact_rollback();
1972 * State remains TRANS_ABORT until CleanupTransaction().
1974 RESUME_INTERRUPTS();
1978 * CleanupTransaction
1981 CleanupTransaction(void)
1983 TransactionState s = CurrentTransactionState;
1986 * State should still be TRANS_ABORT from AbortTransaction().
1988 if (s->state != TRANS_ABORT)
1989 elog(FATAL, "CleanupTransaction: unexpected state %s",
1990 TransStateAsString(s->state));
1993 * do abort cleanup processing
1995 AtCleanup_Portals(); /* now safe to release portal memory */
1997 CurrentResourceOwner = NULL; /* and resource owner */
1998 if (TopTransactionResourceOwner)
1999 ResourceOwnerDelete(TopTransactionResourceOwner);
2000 s->curTransactionOwner = NULL;
2001 CurTransactionResourceOwner = NULL;
2002 TopTransactionResourceOwner = NULL;
2004 AtCleanup_Memory(); /* and transaction memory */
2006 s->transactionId = InvalidTransactionId;
2007 s->subTransactionId = InvalidSubTransactionId;
2008 s->nestingLevel = 0;
2012 * done with abort processing, set current transaction state back to
2015 s->state = TRANS_DEFAULT;
2019 * StartTransactionCommand
2022 StartTransactionCommand(void)
2024 TransactionState s = CurrentTransactionState;
2026 switch (s->blockState)
2029 * if we aren't in a transaction block, we just do our usual start
2032 case TBLOCK_DEFAULT:
2034 s->blockState = TBLOCK_STARTED;
2038 * We are somewhere in a transaction block or subtransaction and
2039 * about to start a new command. For now we do nothing, but
2040 * someday we may do command-local resource initialization. (Note
2041 * that any needed CommandCounterIncrement was done by the
2042 * previous CommitTransactionCommand.)
2044 case TBLOCK_INPROGRESS:
2045 case TBLOCK_SUBINPROGRESS:
2049 * Here we are in a failed transaction block (one of the commands
2050 * caused an abort) so we do nothing but remain in the abort
2051 * state. Eventually we will get a ROLLBACK command which will
2052 * get us out of this state. (It is up to other code to ensure
2053 * that no commands other than ROLLBACK will be processed in these
2057 case TBLOCK_SUBABORT:
2060 /* These cases are invalid. */
2061 case TBLOCK_STARTED:
2063 case TBLOCK_SUBBEGIN:
2066 case TBLOCK_ABORT_END:
2067 case TBLOCK_SUBABORT_END:
2068 case TBLOCK_ABORT_PENDING:
2069 case TBLOCK_SUBABORT_PENDING:
2070 case TBLOCK_SUBRESTART:
2071 case TBLOCK_SUBABORT_RESTART:
2072 case TBLOCK_PREPARE:
2073 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2074 BlockStateAsString(s->blockState));
2079 * We must switch to CurTransactionContext before returning. This is
2080 * already done if we called StartTransaction, otherwise not.
2082 Assert(CurTransactionContext != NULL);
2083 MemoryContextSwitchTo(CurTransactionContext);
2087 * CommitTransactionCommand
2090 CommitTransactionCommand(void)
2092 TransactionState s = CurrentTransactionState;
2094 switch (s->blockState)
2097 * This shouldn't happen, because it means the previous
2098 * StartTransactionCommand didn't set the STARTED state
2101 case TBLOCK_DEFAULT:
2102 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2103 BlockStateAsString(s->blockState));
2107 * If we aren't in a transaction block, just do our usual
2108 * transaction commit, and return to the idle state.
2110 case TBLOCK_STARTED:
2111 CommitTransaction();
2112 s->blockState = TBLOCK_DEFAULT;
2116 * We are completing a "BEGIN TRANSACTION" command, so we change
2117 * to the "transaction block in progress" state and return. (We
2118 * assume the BEGIN did nothing to the database, so we need no
2119 * CommandCounterIncrement.)
2122 s->blockState = TBLOCK_INPROGRESS;
2126 * This is the case when we have finished executing a command
2127 * someplace within a transaction block. We increment the command
2128 * counter and return.
2130 case TBLOCK_INPROGRESS:
2131 case TBLOCK_SUBINPROGRESS:
2132 CommandCounterIncrement();
2136 * We are completing a "COMMIT" command. Do it and return to the
2140 CommitTransaction();
2141 s->blockState = TBLOCK_DEFAULT;
2145 * Here we are in the middle of a transaction block but one of the
2146 * commands caused an abort so we do nothing but remain in the
2147 * abort state. Eventually we will get a ROLLBACK comand.
2150 case TBLOCK_SUBABORT:
2154 * Here we were in an aborted transaction block and we just got
2155 * the ROLLBACK command from the user, so clean up the
2156 * already-aborted transaction and return to the idle state.
2158 case TBLOCK_ABORT_END:
2159 CleanupTransaction();
2160 s->blockState = TBLOCK_DEFAULT;
2164 * Here we were in a perfectly good transaction block but the user
2165 * told us to ROLLBACK anyway. We have to abort the transaction
2166 * and then clean up.
2168 case TBLOCK_ABORT_PENDING:
2170 CleanupTransaction();
2171 s->blockState = TBLOCK_DEFAULT;
2175 * We are completing a "PREPARE TRANSACTION" command. Do it and
2176 * return to the idle state.
2178 case TBLOCK_PREPARE:
2179 PrepareTransaction();
2180 s->blockState = TBLOCK_DEFAULT;
2184 * We were just issued a SAVEPOINT inside a transaction block.
2185 * Start a subtransaction. (DefineSavepoint already did
2186 * PushTransaction, so as to have someplace to put the SUBBEGIN
2189 case TBLOCK_SUBBEGIN:
2190 StartSubTransaction();
2191 s->blockState = TBLOCK_SUBINPROGRESS;
2195 * We were issued a COMMIT or RELEASE command, so we end the
2196 * current subtransaction and return to the parent transaction.
2197 * The parent might be ended too, so repeat till we are all the
2198 * way out or find an INPROGRESS transaction.
2203 CommitSubTransaction();
2204 s = CurrentTransactionState; /* changed by pop */
2205 } while (s->blockState == TBLOCK_SUBEND);
2206 /* If we had a COMMIT command, finish off the main xact too */
2207 if (s->blockState == TBLOCK_END)
2209 Assert(s->parent == NULL);
2210 CommitTransaction();
2211 s->blockState = TBLOCK_DEFAULT;
2213 else if (s->blockState == TBLOCK_PREPARE)
2215 Assert(s->parent == NULL);
2216 PrepareTransaction();
2217 s->blockState = TBLOCK_DEFAULT;
2221 Assert(s->blockState == TBLOCK_INPROGRESS ||
2222 s->blockState == TBLOCK_SUBINPROGRESS);
2227 * The current already-failed subtransaction is ending due to a
2228 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2229 * examine the parent (which could be in any of several states).
2231 case TBLOCK_SUBABORT_END:
2232 CleanupSubTransaction();
2233 CommitTransactionCommand();
2237 * As above, but it's not dead yet, so abort first.
2239 case TBLOCK_SUBABORT_PENDING:
2240 AbortSubTransaction();
2241 CleanupSubTransaction();
2242 CommitTransactionCommand();
2246 * The current subtransaction is the target of a ROLLBACK TO
2247 * command. Abort and pop it, then start a new subtransaction
2248 * with the same name.
2250 case TBLOCK_SUBRESTART:
2255 /* save name and keep Cleanup from freeing it */
2258 savepointLevel = s->savepointLevel;
2260 AbortSubTransaction();
2261 CleanupSubTransaction();
2263 DefineSavepoint(NULL);
2264 s = CurrentTransactionState; /* changed by push */
2266 s->savepointLevel = savepointLevel;
2268 /* This is the same as TBLOCK_SUBBEGIN case */
2269 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2270 StartSubTransaction();
2271 s->blockState = TBLOCK_SUBINPROGRESS;
2276 * Same as above, but the subtransaction had already failed, so we
2277 * don't need AbortSubTransaction.
2279 case TBLOCK_SUBABORT_RESTART:
2284 /* save name and keep Cleanup from freeing it */
2287 savepointLevel = s->savepointLevel;
2289 CleanupSubTransaction();
2291 DefineSavepoint(NULL);
2292 s = CurrentTransactionState; /* changed by push */
2294 s->savepointLevel = savepointLevel;
2296 /* This is the same as TBLOCK_SUBBEGIN case */
2297 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2298 StartSubTransaction();
2299 s->blockState = TBLOCK_SUBINPROGRESS;
2306 * AbortCurrentTransaction
2309 AbortCurrentTransaction(void)
2311 TransactionState s = CurrentTransactionState;
2313 switch (s->blockState)
2315 case TBLOCK_DEFAULT:
2316 if (s->state == TRANS_DEFAULT)
2318 /* we are idle, so nothing to do */
2323 * We can get here after an error during transaction start
2324 * (state will be TRANS_START). Need to clean up the
2325 * incompletely started transaction. First, adjust the
2326 * low-level state to suppress warning message from
2329 if (s->state == TRANS_START)
2330 s->state = TRANS_INPROGRESS;
2332 CleanupTransaction();
2337 * if we aren't in a transaction block, we just do the basic abort
2338 * & cleanup transaction.
2340 case TBLOCK_STARTED:
2342 CleanupTransaction();
2343 s->blockState = TBLOCK_DEFAULT;
2347 * If we are in TBLOCK_BEGIN it means something screwed up right
2348 * after reading "BEGIN TRANSACTION". We assume that the user
2349 * will interpret the error as meaning the BEGIN failed to get him
2350 * into a transaction block, so we should abort and return to idle
2355 CleanupTransaction();
2356 s->blockState = TBLOCK_DEFAULT;
2360 * We are somewhere in a transaction block and we've gotten a
2361 * failure, so we abort the transaction and set up the persistent
2362 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2364 case TBLOCK_INPROGRESS:
2366 s->blockState = TBLOCK_ABORT;
2367 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2371 * Here, we failed while trying to COMMIT. Clean up the
2372 * transaction and return to idle state (we do not want to stay in
2377 CleanupTransaction();
2378 s->blockState = TBLOCK_DEFAULT;
2382 * Here, we are already in an aborted transaction state and are
2383 * waiting for a ROLLBACK, but for some reason we failed again! So
2384 * we just remain in the abort state.
2387 case TBLOCK_SUBABORT:
2391 * We are in a failed transaction and we got the ROLLBACK command.
2392 * We have already aborted, we just need to cleanup and go to idle
2395 case TBLOCK_ABORT_END:
2396 CleanupTransaction();
2397 s->blockState = TBLOCK_DEFAULT;
2401 * We are in a live transaction and we got a ROLLBACK command.
2402 * Abort, cleanup, go to idle state.
2404 case TBLOCK_ABORT_PENDING:
2406 CleanupTransaction();
2407 s->blockState = TBLOCK_DEFAULT;
2411 * Here, we failed while trying to PREPARE. Clean up the
2412 * transaction and return to idle state (we do not want to stay in
2415 case TBLOCK_PREPARE:
2417 CleanupTransaction();
2418 s->blockState = TBLOCK_DEFAULT;
2422 * We got an error inside a subtransaction. Abort just the
2423 * subtransaction, and go to the persistent SUBABORT state until
2426 case TBLOCK_SUBINPROGRESS:
2427 AbortSubTransaction();
2428 s->blockState = TBLOCK_SUBABORT;
2432 * If we failed while trying to create a subtransaction, clean up
2433 * the broken subtransaction and abort the parent. The same
2434 * applies if we get a failure while ending a subtransaction.
2436 case TBLOCK_SUBBEGIN:
2438 case TBLOCK_SUBABORT_PENDING:
2439 case TBLOCK_SUBRESTART:
2440 AbortSubTransaction();
2441 CleanupSubTransaction();
2442 AbortCurrentTransaction();
2446 * Same as above, except the Abort() was already done.
2448 case TBLOCK_SUBABORT_END:
2449 case TBLOCK_SUBABORT_RESTART:
2450 CleanupSubTransaction();
2451 AbortCurrentTransaction();
2457 * PreventTransactionChain
2459 * This routine is to be called by statements that must not run inside
2460 * a transaction block, typically because they have non-rollback-able
2461 * side effects or do internal commits.
2463 * If we have already started a transaction block, issue an error; also issue
2464 * an error if we appear to be running inside a user-defined function (which
2465 * could issue more commands and possibly cause a failure after the statement
2466 * completes). Subtransactions are verboten too.
2468 * stmtNode: pointer to parameter block for statement; this is used in
2469 * a very klugy way to determine whether we are inside a function.
2470 * stmtType: statement type name for error messages.
2473 PreventTransactionChain(void *stmtNode, const char *stmtType)
2476 * xact block already started?
2478 if (IsTransactionBlock())
2480 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2481 /* translator: %s represents an SQL statement name */
2482 errmsg("%s cannot run inside a transaction block",
2488 if (IsSubTransaction())
2490 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2491 /* translator: %s represents an SQL statement name */
2492 errmsg("%s cannot run inside a subtransaction",
2496 * Are we inside a function call? If the statement's parameter block was
2497 * allocated in QueryContext, assume it is an interactive command.
2498 * Otherwise assume it is coming from a function.
2500 if (!MemoryContextContains(QueryContext, stmtNode))
2502 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2503 /* translator: %s represents an SQL statement name */
2504 errmsg("%s cannot be executed from a function", stmtType)));
2506 /* If we got past IsTransactionBlock test, should be in default state */
2507 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2508 CurrentTransactionState->blockState != TBLOCK_STARTED)
2509 elog(FATAL, "cannot prevent transaction chain");
2514 * RequireTransactionChain
2516 * This routine is to be called by statements that must run inside
2517 * a transaction block, because they have no effects that persist past
2518 * transaction end (and so calling them outside a transaction block
2519 * is presumably an error). DECLARE CURSOR is an example.
2521 * If we appear to be running inside a user-defined function, we do not
2522 * issue an error, since the function could issue more commands that make
2523 * use of the current statement's results. Likewise subtransactions.
2524 * Thus this is an inverse for PreventTransactionChain.
2526 * stmtNode: pointer to parameter block for statement; this is used in
2527 * a very klugy way to determine whether we are inside a function.
2528 * stmtType: statement type name for error messages.
2531 RequireTransactionChain(void *stmtNode, const char *stmtType)
2534 * xact block already started?
2536 if (IsTransactionBlock())
2542 if (IsSubTransaction())
2546 * Are we inside a function call? If the statement's parameter block was
2547 * allocated in QueryContext, assume it is an interactive command.
2548 * Otherwise assume it is coming from a function.
2550 if (!MemoryContextContains(QueryContext, stmtNode))
2553 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2554 /* translator: %s represents an SQL statement name */
2555 errmsg("%s may only be used in transaction blocks",
2560 * IsInTransactionChain
2562 * This routine is for statements that need to behave differently inside
2563 * a transaction block than when running as single commands. ANALYZE is
2564 * currently the only example.
2566 * stmtNode: pointer to parameter block for statement; this is used in
2567 * a very klugy way to determine whether we are inside a function.
2570 IsInTransactionChain(void *stmtNode)
2573 * Return true on same conditions that would make PreventTransactionChain
2576 if (IsTransactionBlock())
2579 if (IsSubTransaction())
2582 if (!MemoryContextContains(QueryContext, stmtNode))
2585 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2586 CurrentTransactionState->blockState != TBLOCK_STARTED)
2594 * Register or deregister callback functions for start- and end-of-xact
2597 * These functions are intended for use by dynamically loaded modules.
2598 * For built-in modules we generally just hardwire the appropriate calls
2599 * (mainly because it's easier to control the order that way, where needed).
2601 * At transaction end, the callback occurs post-commit or post-abort, so the
2602 * callback functions can only do noncritical cleanup.
2605 RegisterXactCallback(XactCallback callback, void *arg)
2607 XactCallbackItem *item;
2609 item = (XactCallbackItem *)
2610 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2611 item->callback = callback;
2613 item->next = Xact_callbacks;
2614 Xact_callbacks = item;
2618 UnregisterXactCallback(XactCallback callback, void *arg)
2620 XactCallbackItem *item;
2621 XactCallbackItem *prev;
2624 for (item = Xact_callbacks; item; prev = item, item = item->next)
2626 if (item->callback == callback && item->arg == arg)
2629 prev->next = item->next;
2631 Xact_callbacks = item->next;
2639 CallXactCallbacks(XactEvent event)
2641 XactCallbackItem *item;
2643 for (item = Xact_callbacks; item; item = item->next)
2644 (*item->callback) (event, item->arg);
2649 * Register or deregister callback functions for start- and end-of-subxact
2652 * Pretty much same as above, but for subtransaction events.
2654 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2655 * so the callback functions can only do noncritical cleanup. At
2656 * subtransaction start, the callback is called when the subtransaction has
2657 * finished initializing.
2660 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2662 SubXactCallbackItem *item;
2664 item = (SubXactCallbackItem *)
2665 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2666 item->callback = callback;
2668 item->next = SubXact_callbacks;
2669 SubXact_callbacks = item;
2673 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2675 SubXactCallbackItem *item;
2676 SubXactCallbackItem *prev;
2679 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2681 if (item->callback == callback && item->arg == arg)
2684 prev->next = item->next;
2686 SubXact_callbacks = item->next;
2694 CallSubXactCallbacks(SubXactEvent event,
2695 SubTransactionId mySubid,
2696 SubTransactionId parentSubid)
2698 SubXactCallbackItem *item;
2700 for (item = SubXact_callbacks; item; item = item->next)
2701 (*item->callback) (event, mySubid, parentSubid, item->arg);
2705 /* ----------------------------------------------------------------
2706 * transaction block support
2707 * ----------------------------------------------------------------
2711 * BeginTransactionBlock
2712 * This executes a BEGIN command.
2715 BeginTransactionBlock(void)
2717 TransactionState s = CurrentTransactionState;
2719 switch (s->blockState)
2722 * We are not inside a transaction block, so allow one to begin.
2724 case TBLOCK_STARTED:
2725 s->blockState = TBLOCK_BEGIN;
2729 * Already a transaction block in progress.
2731 case TBLOCK_INPROGRESS:
2732 case TBLOCK_SUBINPROGRESS:
2734 case TBLOCK_SUBABORT:
2736 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2737 errmsg("there is already a transaction in progress")));
2740 /* These cases are invalid. */
2741 case TBLOCK_DEFAULT:
2743 case TBLOCK_SUBBEGIN:
2746 case TBLOCK_ABORT_END:
2747 case TBLOCK_SUBABORT_END:
2748 case TBLOCK_ABORT_PENDING:
2749 case TBLOCK_SUBABORT_PENDING:
2750 case TBLOCK_SUBRESTART:
2751 case TBLOCK_SUBABORT_RESTART:
2752 case TBLOCK_PREPARE:
2753 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2754 BlockStateAsString(s->blockState));
2760 * PrepareTransactionBlock
2761 * This executes a PREPARE command.
2763 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2764 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2766 * Note that we don't actually do anything here except change blockState.
2767 * The real work will be done in the upcoming PrepareTransaction().
2768 * We do it this way because it's not convenient to change memory context,
2769 * resource owner, etc while executing inside a Portal.
2772 PrepareTransactionBlock(char *gid)
2777 /* Set up to commit the current transaction */
2778 result = EndTransactionBlock();
2780 /* If successful, change outer tblock state to PREPARE */
2783 s = CurrentTransactionState;
2785 while (s->parent != NULL)
2788 if (s->blockState == TBLOCK_END)
2790 /* Save GID where PrepareTransaction can find it again */
2791 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2793 s->blockState = TBLOCK_PREPARE;
2798 * ignore case where we are not in a transaction;
2799 * EndTransactionBlock already issued a warning.
2801 Assert(s->blockState == TBLOCK_STARTED);
2802 /* Don't send back a PREPARE result tag... */
2811 * EndTransactionBlock
2812 * This executes a COMMIT command.
2814 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2815 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2817 * Note that we don't actually do anything here except change blockState.
2818 * The real work will be done in the upcoming CommitTransactionCommand().
2819 * We do it this way because it's not convenient to change memory context,
2820 * resource owner, etc while executing inside a Portal.
2823 EndTransactionBlock(void)
2825 TransactionState s = CurrentTransactionState;
2826 bool result = false;
2828 switch (s->blockState)
2831 * We are in a transaction block, so tell CommitTransactionCommand
2834 case TBLOCK_INPROGRESS:
2835 s->blockState = TBLOCK_END;
2840 * We are in a failed transaction block. Tell
2841 * CommitTransactionCommand it's time to exit the block.
2844 s->blockState = TBLOCK_ABORT_END;
2848 * We are in a live subtransaction block. Set up to subcommit all
2849 * open subtransactions and then commit the main transaction.
2851 case TBLOCK_SUBINPROGRESS:
2852 while (s->parent != NULL)
2854 if (s->blockState == TBLOCK_SUBINPROGRESS)
2855 s->blockState = TBLOCK_SUBEND;
2857 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2858 BlockStateAsString(s->blockState));
2861 if (s->blockState == TBLOCK_INPROGRESS)
2862 s->blockState = TBLOCK_END;
2864 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2865 BlockStateAsString(s->blockState));
2870 * Here we are inside an aborted subtransaction. Treat the COMMIT
2871 * as ROLLBACK: set up to abort everything and exit the main
2874 case TBLOCK_SUBABORT:
2875 while (s->parent != NULL)
2877 if (s->blockState == TBLOCK_SUBINPROGRESS)
2878 s->blockState = TBLOCK_SUBABORT_PENDING;
2879 else if (s->blockState == TBLOCK_SUBABORT)
2880 s->blockState = TBLOCK_SUBABORT_END;
2882 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2883 BlockStateAsString(s->blockState));
2886 if (s->blockState == TBLOCK_INPROGRESS)
2887 s->blockState = TBLOCK_ABORT_PENDING;
2888 else if (s->blockState == TBLOCK_ABORT)
2889 s->blockState = TBLOCK_ABORT_END;
2891 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2892 BlockStateAsString(s->blockState));
2896 * The user issued COMMIT when not inside a transaction. Issue a
2897 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2898 * CommitTransactionCommand() will then close the transaction and
2899 * put us back into the default state.
2901 case TBLOCK_STARTED:
2903 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2904 errmsg("there is no transaction in progress")));
2908 /* These cases are invalid. */
2909 case TBLOCK_DEFAULT:
2911 case TBLOCK_SUBBEGIN:
2914 case TBLOCK_ABORT_END:
2915 case TBLOCK_SUBABORT_END:
2916 case TBLOCK_ABORT_PENDING:
2917 case TBLOCK_SUBABORT_PENDING:
2918 case TBLOCK_SUBRESTART:
2919 case TBLOCK_SUBABORT_RESTART:
2920 case TBLOCK_PREPARE:
2921 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2922 BlockStateAsString(s->blockState));
2930 * UserAbortTransactionBlock
2931 * This executes a ROLLBACK command.
2933 * As above, we don't actually do anything here except change blockState.
2936 UserAbortTransactionBlock(void)
2938 TransactionState s = CurrentTransactionState;
2940 switch (s->blockState)
2943 * We are inside a transaction block and we got a ROLLBACK command
2944 * from the user, so tell CommitTransactionCommand to abort and
2945 * exit the transaction block.
2947 case TBLOCK_INPROGRESS:
2948 s->blockState = TBLOCK_ABORT_PENDING;
2952 * We are inside a failed transaction block and we got a ROLLBACK
2953 * command from the user. Abort processing is already done, so
2954 * CommitTransactionCommand just has to cleanup and go back to
2958 s->blockState = TBLOCK_ABORT_END;
2962 * We are inside a subtransaction. Mark everything up to top
2963 * level as exitable.
2965 case TBLOCK_SUBINPROGRESS:
2966 case TBLOCK_SUBABORT:
2967 while (s->parent != NULL)
2969 if (s->blockState == TBLOCK_SUBINPROGRESS)
2970 s->blockState = TBLOCK_SUBABORT_PENDING;
2971 else if (s->blockState == TBLOCK_SUBABORT)
2972 s->blockState = TBLOCK_SUBABORT_END;
2974 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2975 BlockStateAsString(s->blockState));
2978 if (s->blockState == TBLOCK_INPROGRESS)
2979 s->blockState = TBLOCK_ABORT_PENDING;
2980 else if (s->blockState == TBLOCK_ABORT)
2981 s->blockState = TBLOCK_ABORT_END;
2983 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2984 BlockStateAsString(s->blockState));
2988 * The user issued ABORT when not inside a transaction. Issue a
2989 * WARNING and go to abort state. The upcoming call to
2990 * CommitTransactionCommand() will then put us back into the
2993 case TBLOCK_STARTED:
2995 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2996 errmsg("there is no transaction in progress")));
2997 s->blockState = TBLOCK_ABORT_PENDING;
3000 /* These cases are invalid. */
3001 case TBLOCK_DEFAULT:
3003 case TBLOCK_SUBBEGIN:
3006 case TBLOCK_ABORT_END:
3007 case TBLOCK_SUBABORT_END:
3008 case TBLOCK_ABORT_PENDING:
3009 case TBLOCK_SUBABORT_PENDING:
3010 case TBLOCK_SUBRESTART:
3011 case TBLOCK_SUBABORT_RESTART:
3012 case TBLOCK_PREPARE:
3013 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3014 BlockStateAsString(s->blockState));
3021 * This executes a SAVEPOINT command.
3024 DefineSavepoint(char *name)
3026 TransactionState s = CurrentTransactionState;
3028 switch (s->blockState)
3030 case TBLOCK_INPROGRESS:
3031 case TBLOCK_SUBINPROGRESS:
3032 /* Normal subtransaction start */
3034 s = CurrentTransactionState; /* changed by push */
3037 * Savepoint names, like the TransactionState block itself, live
3038 * in TopTransactionContext.
3041 s->name = MemoryContextStrdup(TopTransactionContext, name);
3044 /* These cases are invalid. */
3045 case TBLOCK_DEFAULT:
3046 case TBLOCK_STARTED:
3048 case TBLOCK_SUBBEGIN:
3052 case TBLOCK_SUBABORT:
3053 case TBLOCK_ABORT_END:
3054 case TBLOCK_SUBABORT_END:
3055 case TBLOCK_ABORT_PENDING:
3056 case TBLOCK_SUBABORT_PENDING:
3057 case TBLOCK_SUBRESTART:
3058 case TBLOCK_SUBABORT_RESTART:
3059 case TBLOCK_PREPARE:
3060 elog(FATAL, "DefineSavepoint: unexpected state %s",
3061 BlockStateAsString(s->blockState));
3068 * This executes a RELEASE command.
3070 * As above, we don't actually do anything here except change blockState.
3073 ReleaseSavepoint(List *options)
3075 TransactionState s = CurrentTransactionState;
3076 TransactionState target,
3081 switch (s->blockState)
3084 * We can't rollback to a savepoint if there is no savepoint
3087 case TBLOCK_INPROGRESS:
3089 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3090 errmsg("no such savepoint")));
3094 * We are in a non-aborted subtransaction. This is the only valid
3097 case TBLOCK_SUBINPROGRESS:
3100 /* These cases are invalid. */
3101 case TBLOCK_DEFAULT:
3102 case TBLOCK_STARTED:
3104 case TBLOCK_SUBBEGIN:
3108 case TBLOCK_SUBABORT:
3109 case TBLOCK_ABORT_END:
3110 case TBLOCK_SUBABORT_END:
3111 case TBLOCK_ABORT_PENDING:
3112 case TBLOCK_SUBABORT_PENDING:
3113 case TBLOCK_SUBRESTART:
3114 case TBLOCK_SUBABORT_RESTART:
3115 case TBLOCK_PREPARE:
3116 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3117 BlockStateAsString(s->blockState));
3121 foreach(cell, options)
3123 DefElem *elem = lfirst(cell);
3125 if (strcmp(elem->defname, "savepoint_name") == 0)
3126 name = strVal(elem->arg);
3129 Assert(PointerIsValid(name));
3131 for (target = s; PointerIsValid(target); target = target->parent)
3133 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3137 if (!PointerIsValid(target))
3139 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3140 errmsg("no such savepoint")));
3142 /* disallow crossing savepoint level boundaries */
3143 if (target->savepointLevel != s->savepointLevel)
3145 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3146 errmsg("no such savepoint")));
3149 * Mark "commit pending" all subtransactions up to the target
3150 * subtransaction. The actual commits will happen when control gets to
3151 * CommitTransactionCommand.
3153 xact = CurrentTransactionState;
3156 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3157 xact->blockState = TBLOCK_SUBEND;
3160 xact = xact->parent;
3161 Assert(PointerIsValid(xact));
3166 * RollbackToSavepoint
3167 * This executes a ROLLBACK TO <savepoint> command.
3169 * As above, we don't actually do anything here except change blockState.
3172 RollbackToSavepoint(List *options)
3174 TransactionState s = CurrentTransactionState;
3175 TransactionState target,
3180 switch (s->blockState)
3183 * We can't rollback to a savepoint if there is no savepoint
3186 case TBLOCK_INPROGRESS:
3189 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3190 errmsg("no such savepoint")));
3194 * There is at least one savepoint, so proceed.
3196 case TBLOCK_SUBINPROGRESS:
3197 case TBLOCK_SUBABORT:
3200 /* These cases are invalid. */
3201 case TBLOCK_DEFAULT:
3202 case TBLOCK_STARTED:
3204 case TBLOCK_SUBBEGIN:
3207 case TBLOCK_ABORT_END:
3208 case TBLOCK_SUBABORT_END:
3209 case TBLOCK_ABORT_PENDING:
3210 case TBLOCK_SUBABORT_PENDING:
3211 case TBLOCK_SUBRESTART:
3212 case TBLOCK_SUBABORT_RESTART:
3213 case TBLOCK_PREPARE:
3214 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3215 BlockStateAsString(s->blockState));
3219 foreach(cell, options)
3221 DefElem *elem = lfirst(cell);
3223 if (strcmp(elem->defname, "savepoint_name") == 0)
3224 name = strVal(elem->arg);
3227 Assert(PointerIsValid(name));
3229 for (target = s; PointerIsValid(target); target = target->parent)
3231 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3235 if (!PointerIsValid(target))
3237 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3238 errmsg("no such savepoint")));
3240 /* disallow crossing savepoint level boundaries */
3241 if (target->savepointLevel != s->savepointLevel)
3243 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3244 errmsg("no such savepoint")));
3247 * Mark "abort pending" all subtransactions up to the target
3248 * subtransaction. The actual aborts will happen when control gets to
3249 * CommitTransactionCommand.
3251 xact = CurrentTransactionState;
3256 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3257 xact->blockState = TBLOCK_SUBABORT_PENDING;
3258 else if (xact->blockState == TBLOCK_SUBABORT)
3259 xact->blockState = TBLOCK_SUBABORT_END;
3261 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3262 BlockStateAsString(xact->blockState));
3263 xact = xact->parent;
3264 Assert(PointerIsValid(xact));
3267 /* And mark the target as "restart pending" */
3268 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3269 xact->blockState = TBLOCK_SUBRESTART;
3270 else if (xact->blockState == TBLOCK_SUBABORT)
3271 xact->blockState = TBLOCK_SUBABORT_RESTART;
3273 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3274 BlockStateAsString(xact->blockState));
3278 * BeginInternalSubTransaction
3279 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3280 * state, and therefore it can safely be used in a function that might
3281 * be called when not inside a BEGIN block. Also, we automatically
3282 * cycle through CommitTransactionCommand/StartTransactionCommand
3283 * instead of expecting the caller to do it.
3286 BeginInternalSubTransaction(char *name)
3288 TransactionState s = CurrentTransactionState;
3290 switch (s->blockState)
3292 case TBLOCK_STARTED:
3293 case TBLOCK_INPROGRESS:
3294 case TBLOCK_SUBINPROGRESS:
3295 /* Normal subtransaction start */
3297 s = CurrentTransactionState; /* changed by push */
3300 * Savepoint names, like the TransactionState block itself, live
3301 * in TopTransactionContext.
3304 s->name = MemoryContextStrdup(TopTransactionContext, name);
3307 /* These cases are invalid. */
3308 case TBLOCK_DEFAULT:
3310 case TBLOCK_SUBBEGIN:
3314 case TBLOCK_SUBABORT:
3315 case TBLOCK_ABORT_END:
3316 case TBLOCK_SUBABORT_END:
3317 case TBLOCK_ABORT_PENDING:
3318 case TBLOCK_SUBABORT_PENDING:
3319 case TBLOCK_SUBRESTART:
3320 case TBLOCK_SUBABORT_RESTART:
3321 case TBLOCK_PREPARE:
3322 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3323 BlockStateAsString(s->blockState));
3327 CommitTransactionCommand();
3328 StartTransactionCommand();
3332 * ReleaseCurrentSubTransaction
3334 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3335 * savepoint name (if any).
3336 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3339 ReleaseCurrentSubTransaction(void)
3341 TransactionState s = CurrentTransactionState;
3343 if (s->blockState != TBLOCK_SUBINPROGRESS)
3344 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3345 BlockStateAsString(s->blockState));
3346 Assert(s->state == TRANS_INPROGRESS);
3347 MemoryContextSwitchTo(CurTransactionContext);
3348 CommitSubTransaction();
3349 s = CurrentTransactionState; /* changed by pop */
3350 Assert(s->state == TRANS_INPROGRESS);
3354 * RollbackAndReleaseCurrentSubTransaction
3356 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3357 * of its savepoint name (if any).
3358 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3361 RollbackAndReleaseCurrentSubTransaction(void)
3363 TransactionState s = CurrentTransactionState;
3365 switch (s->blockState)
3367 /* Must be in a subtransaction */
3368 case TBLOCK_SUBINPROGRESS:
3369 case TBLOCK_SUBABORT:
3372 /* These cases are invalid. */
3373 case TBLOCK_DEFAULT:
3374 case TBLOCK_STARTED:
3376 case TBLOCK_SUBBEGIN:
3377 case TBLOCK_INPROGRESS:
3381 case TBLOCK_ABORT_END:
3382 case TBLOCK_SUBABORT_END:
3383 case TBLOCK_ABORT_PENDING:
3384 case TBLOCK_SUBABORT_PENDING:
3385 case TBLOCK_SUBRESTART:
3386 case TBLOCK_SUBABORT_RESTART:
3387 case TBLOCK_PREPARE:
3388 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3389 BlockStateAsString(s->blockState));
3394 * Abort the current subtransaction, if needed.
3396 if (s->blockState == TBLOCK_SUBINPROGRESS)
3397 AbortSubTransaction();
3399 /* And clean it up, too */
3400 CleanupSubTransaction();
3402 s = CurrentTransactionState; /* changed by pop */
3403 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3404 s->blockState == TBLOCK_INPROGRESS ||
3405 s->blockState == TBLOCK_STARTED);
3409 * AbortOutOfAnyTransaction
3411 * This routine is provided for error recovery purposes. It aborts any
3412 * active transaction or transaction block, leaving the system in a known
3416 AbortOutOfAnyTransaction(void)
3418 TransactionState s = CurrentTransactionState;
3421 * Get out of any transaction or nested transaction
3425 switch (s->blockState)
3427 case TBLOCK_DEFAULT:
3428 /* Not in a transaction, do nothing */
3430 case TBLOCK_STARTED:
3432 case TBLOCK_INPROGRESS:
3434 case TBLOCK_ABORT_PENDING:
3435 case TBLOCK_PREPARE:
3436 /* In a transaction, so clean up */
3438 CleanupTransaction();
3439 s->blockState = TBLOCK_DEFAULT;
3442 case TBLOCK_ABORT_END:
3443 /* AbortTransaction already done, still need Cleanup */
3444 CleanupTransaction();
3445 s->blockState = TBLOCK_DEFAULT;
3449 * In a subtransaction, so clean it up and abort parent too
3451 case TBLOCK_SUBBEGIN:
3452 case TBLOCK_SUBINPROGRESS:
3454 case TBLOCK_SUBABORT_PENDING:
3455 case TBLOCK_SUBRESTART:
3456 AbortSubTransaction();
3457 CleanupSubTransaction();
3458 s = CurrentTransactionState; /* changed by pop */
3461 case TBLOCK_SUBABORT:
3462 case TBLOCK_SUBABORT_END:
3463 case TBLOCK_SUBABORT_RESTART:
3464 /* As above, but AbortSubTransaction already done */
3465 CleanupSubTransaction();
3466 s = CurrentTransactionState; /* changed by pop */
3469 } while (s->blockState != TBLOCK_DEFAULT);
3471 /* Should be out of all subxacts now */
3472 Assert(s->parent == NULL);
3476 * IsTransactionBlock --- are we within a transaction block?
3479 IsTransactionBlock(void)
3481 TransactionState s = CurrentTransactionState;
3483 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3490 * IsTransactionOrTransactionBlock --- are we within either a transaction
3491 * or a transaction block? (The backend is only really "idle" when this
3494 * This should match up with IsTransactionBlock and IsTransactionState.
3497 IsTransactionOrTransactionBlock(void)
3499 TransactionState s = CurrentTransactionState;
3501 if (s->blockState == TBLOCK_DEFAULT)
3508 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3511 TransactionBlockStatusCode(void)
3513 TransactionState s = CurrentTransactionState;
3515 switch (s->blockState)
3517 case TBLOCK_DEFAULT:
3518 case TBLOCK_STARTED:
3519 return 'I'; /* idle --- not in transaction */
3521 case TBLOCK_SUBBEGIN:
3522 case TBLOCK_INPROGRESS:
3523 case TBLOCK_SUBINPROGRESS:
3526 case TBLOCK_PREPARE:
3527 return 'T'; /* in transaction */
3529 case TBLOCK_SUBABORT:
3530 case TBLOCK_ABORT_END:
3531 case TBLOCK_SUBABORT_END:
3532 case TBLOCK_ABORT_PENDING:
3533 case TBLOCK_SUBABORT_PENDING:
3534 case TBLOCK_SUBRESTART:
3535 case TBLOCK_SUBABORT_RESTART:
3536 return 'E'; /* in failed transaction */
3539 /* should never get here */
3540 elog(FATAL, "invalid transaction block state: %s",
3541 BlockStateAsString(s->blockState));
3542 return 0; /* keep compiler quiet */
3549 IsSubTransaction(void)
3551 TransactionState s = CurrentTransactionState;
3553 if (s->nestingLevel >= 2)
3560 * StartSubTransaction
3562 * If you're wondering why this is separate from PushTransaction: it's because
3563 * we can't conveniently do this stuff right inside DefineSavepoint. The
3564 * SAVEPOINT utility command will be executed inside a Portal, and if we
3565 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3566 * the Portal will undo those settings. So we make DefineSavepoint just
3567 * push a dummy transaction block, and when control returns to the main
3568 * idle loop, CommitTransactionCommand will be called, and we'll come here
3569 * to finish starting the subtransaction.
3572 StartSubTransaction(void)
3574 TransactionState s = CurrentTransactionState;
3576 if (s->state != TRANS_DEFAULT)
3577 elog(WARNING, "StartSubTransaction while in %s state",
3578 TransStateAsString(s->state));
3580 s->state = TRANS_START;
3583 * Initialize subsystems for new subtransaction
3585 * must initialize resource-management stuff first
3587 AtSubStart_Memory();
3588 AtSubStart_ResourceOwner();
3590 AtSubStart_Notify();
3591 AfterTriggerBeginSubXact();
3593 s->state = TRANS_INPROGRESS;
3596 * Call start-of-subxact callbacks
3598 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3599 s->parent->subTransactionId);
3601 ShowTransactionState("StartSubTransaction");
3605 * CommitSubTransaction
3607 * The caller has to make sure to always reassign CurrentTransactionState
3608 * if it has a local pointer to it after calling this function.
3611 CommitSubTransaction(void)
3613 TransactionState s = CurrentTransactionState;
3615 ShowTransactionState("CommitSubTransaction");
3617 if (s->state != TRANS_INPROGRESS)
3618 elog(WARNING, "CommitSubTransaction while in %s state",
3619 TransStateAsString(s->state));
3621 /* Pre-commit processing goes here -- nothing to do at the moment */
3623 s->state = TRANS_COMMIT;
3625 /* Must CCI to ensure commands of subtransaction are seen as done */
3626 CommandCounterIncrement();
3628 /* Mark subtransaction as subcommitted */
3629 if (TransactionIdIsValid(s->transactionId))
3631 RecordSubTransactionCommit();
3632 AtSubCommit_childXids();
3635 /* Post-commit cleanup */
3636 AfterTriggerEndSubXact(true);
3637 AtSubCommit_Portals(s->subTransactionId,
3638 s->parent->subTransactionId,
3639 s->parent->curTransactionOwner);
3640 AtEOSubXact_LargeObject(true, s->subTransactionId,
3641 s->parent->subTransactionId);
3642 AtSubCommit_Notify();
3643 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3644 s->parent->subTransactionId);
3646 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3647 s->parent->subTransactionId);
3649 ResourceOwnerRelease(s->curTransactionOwner,
3650 RESOURCE_RELEASE_BEFORE_LOCKS,
3652 AtEOSubXact_RelationCache(true, s->subTransactionId,
3653 s->parent->subTransactionId);
3654 AtEOSubXact_Inval(true);
3658 * The only lock we actually release here is the subtransaction XID lock.
3659 * The rest just get transferred to the parent resource owner.
3661 CurrentResourceOwner = s->curTransactionOwner;
3662 if (TransactionIdIsValid(s->transactionId))
3663 XactLockTableDelete(s->transactionId);
3665 ResourceOwnerRelease(s->curTransactionOwner,
3666 RESOURCE_RELEASE_LOCKS,
3668 ResourceOwnerRelease(s->curTransactionOwner,
3669 RESOURCE_RELEASE_AFTER_LOCKS,
3672 AtEOXact_GUC(true, true);
3673 AtEOSubXact_SPI(true, s->subTransactionId);
3674 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3675 s->parent->subTransactionId);
3676 AtEOSubXact_Namespace(true, s->subTransactionId,
3677 s->parent->subTransactionId);
3678 AtEOSubXact_Files(true, s->subTransactionId,
3679 s->parent->subTransactionId);
3682 * We need to restore the upper transaction's read-only state, in case the
3683 * upper is read-write while the child is read-only; GUC will incorrectly
3684 * think it should leave the child state in place.
3686 XactReadOnly = s->prevXactReadOnly;
3688 CurrentResourceOwner = s->parent->curTransactionOwner;
3689 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3690 ResourceOwnerDelete(s->curTransactionOwner);
3691 s->curTransactionOwner = NULL;
3693 AtSubCommit_Memory();
3695 s->state = TRANS_DEFAULT;
3701 * AbortSubTransaction
3704 AbortSubTransaction(void)
3706 TransactionState s = CurrentTransactionState;
3708 ShowTransactionState("AbortSubTransaction");
3710 if (s->state != TRANS_INPROGRESS)
3711 elog(WARNING, "AbortSubTransaction while in %s state",
3712 TransStateAsString(s->state));
3716 s->state = TRANS_ABORT;
3719 * Release any LW locks we might be holding as quickly as possible.
3720 * (Regular locks, however, must be held till we finish aborting.)
3721 * Releasing LW locks is critical since we might try to grab them again
3722 * while cleaning up!
3724 * FIXME This may be incorrect --- Are there some locks we should keep?
3725 * Buffer locks, for example? I don't think so but I'm not sure.
3735 * do abort processing
3737 AtSubAbort_Memory();
3738 AtSubAbort_ResourceOwner();
3741 * We can skip all this stuff if the subxact failed before creating a
3744 if (s->curTransactionOwner)
3746 AfterTriggerEndSubXact(false);
3747 AtSubAbort_Portals(s->subTransactionId,
3748 s->parent->subTransactionId,
3749 s->parent->curTransactionOwner);
3750 AtEOSubXact_LargeObject(false, s->subTransactionId,
3751 s->parent->subTransactionId);
3752 AtSubAbort_Notify();
3753 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3754 s->parent->subTransactionId);
3756 /* Advertise the fact that we aborted in pg_clog. */
3757 if (TransactionIdIsValid(s->transactionId))
3759 RecordSubTransactionAbort();
3760 AtSubAbort_childXids();
3763 /* Post-abort cleanup */
3764 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3765 s->parent->subTransactionId);
3767 ResourceOwnerRelease(s->curTransactionOwner,
3768 RESOURCE_RELEASE_BEFORE_LOCKS,
3770 AtEOSubXact_RelationCache(false, s->subTransactionId,
3771 s->parent->subTransactionId);
3772 AtEOSubXact_Inval(false);
3774 ResourceOwnerRelease(s->curTransactionOwner,
3775 RESOURCE_RELEASE_LOCKS,
3777 ResourceOwnerRelease(s->curTransactionOwner,
3778 RESOURCE_RELEASE_AFTER_LOCKS,
3781 AtEOXact_GUC(false, true);
3782 AtEOSubXact_SPI(false, s->subTransactionId);
3783 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3784 s->parent->subTransactionId);
3785 AtEOSubXact_Namespace(false, s->subTransactionId,
3786 s->parent->subTransactionId);
3787 AtEOSubXact_Files(false, s->subTransactionId,
3788 s->parent->subTransactionId);
3792 * Reset user id which might have been changed transiently. Here we want
3793 * to restore to the userid that was current at subxact entry. (As in
3794 * AbortTransaction, we need not worry about the session userid.)
3796 * Must do this after AtEOXact_GUC to handle the case where we entered the
3797 * subxact inside a SECURITY DEFINER function (hence current and session
3798 * userids were different) and then session auth was changed inside the
3799 * subxact. GUC will reset both current and session userids to the
3800 * entry-time session userid. This is right in every other scenario so it
3801 * seems simplest to let GUC do that and fix it here.
3803 SetUserId(s->currentUser);
3806 * Restore the upper transaction's read-only state, too. This should be
3807 * redundant with GUC's cleanup but we may as well do it for consistency
3808 * with the commit case.
3810 XactReadOnly = s->prevXactReadOnly;
3812 RESUME_INTERRUPTS();
3816 * CleanupSubTransaction
3818 * The caller has to make sure to always reassign CurrentTransactionState
3819 * if it has a local pointer to it after calling this function.
3822 CleanupSubTransaction(void)
3824 TransactionState s = CurrentTransactionState;
3826 ShowTransactionState("CleanupSubTransaction");
3828 if (s->state != TRANS_ABORT)
3829 elog(WARNING, "CleanupSubTransaction while in %s state",
3830 TransStateAsString(s->state));
3832 AtSubCleanup_Portals(s->subTransactionId);
3834 CurrentResourceOwner = s->parent->curTransactionOwner;
3835 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3836 if (s->curTransactionOwner)
3837 ResourceOwnerDelete(s->curTransactionOwner);
3838 s->curTransactionOwner = NULL;
3840 AtSubCleanup_Memory();
3842 s->state = TRANS_DEFAULT;
3849 * Create transaction state stack entry for a subtransaction
3851 * The caller has to make sure to always reassign CurrentTransactionState
3852 * if it has a local pointer to it after calling this function.
3855 PushTransaction(void)
3857 TransactionState p = CurrentTransactionState;
3862 * At present, GetUserId cannot fail, but let's not assume that. Get the
3863 * ID before entering the critical code sequence.
3865 currentUser = GetUserId();
3868 * We keep subtransaction state nodes in TopTransactionContext.
3870 s = (TransactionState)
3871 MemoryContextAllocZero(TopTransactionContext,
3872 sizeof(TransactionStateData));
3875 * Assign a subtransaction ID, watching out for counter wraparound.
3877 currentSubTransactionId += 1;
3878 if (currentSubTransactionId == InvalidSubTransactionId)
3880 currentSubTransactionId -= 1;
3883 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3884 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3888 * We can now stack a minimally valid subtransaction without fear of
3891 s->transactionId = InvalidTransactionId; /* until assigned */
3892 s->subTransactionId = currentSubTransactionId;
3894 s->nestingLevel = p->nestingLevel + 1;
3895 s->savepointLevel = p->savepointLevel;
3896 s->state = TRANS_DEFAULT;
3897 s->blockState = TBLOCK_SUBBEGIN;
3898 s->currentUser = currentUser;
3899 s->prevXactReadOnly = XactReadOnly;
3901 CurrentTransactionState = s;
3904 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3905 * with the subtransaction from here on out; in particular they should not
3906 * assume that it necessarily has a transaction context, resource owner,
3913 * Pop back to parent transaction state
3915 * The caller has to make sure to always reassign CurrentTransactionState
3916 * if it has a local pointer to it after calling this function.
3919 PopTransaction(void)
3921 TransactionState s = CurrentTransactionState;
3923 if (s->state != TRANS_DEFAULT)
3924 elog(WARNING, "PopTransaction while in %s state",
3925 TransStateAsString(s->state));
3927 if (s->parent == NULL)
3928 elog(FATAL, "PopTransaction with no parent");
3930 CurrentTransactionState = s->parent;
3932 /* Let's just make sure CurTransactionContext is good */
3933 CurTransactionContext = s->parent->curTransactionContext;
3934 MemoryContextSwitchTo(CurTransactionContext);
3936 /* Ditto for ResourceOwner links */
3937 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3938 CurrentResourceOwner = s->parent->curTransactionOwner;
3940 /* Free the old child structure */
3947 * ShowTransactionState
3951 ShowTransactionState(const char *str)
3953 /* skip work if message will definitely not be printed */
3954 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3956 elog(DEBUG3, "%s", str);
3957 ShowTransactionStateRec(CurrentTransactionState);
3962 * ShowTransactionStateRec
3963 * Recursive subroutine for ShowTransactionState
3966 ShowTransactionStateRec(TransactionState s)
3969 ShowTransactionStateRec(s->parent);
3971 /* use ereport to suppress computation if msg will not be printed */
3973 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3974 PointerIsValid(s->name) ? s->name : "unnamed",
3975 BlockStateAsString(s->blockState),
3976 TransStateAsString(s->state),
3977 (unsigned int) s->transactionId,
3978 (unsigned int) s->subTransactionId,
3979 (unsigned int) currentCommandId,
3981 nodeToString(s->childXids))));
3985 * BlockStateAsString
3989 BlockStateAsString(TBlockState blockState)
3993 case TBLOCK_DEFAULT:
3995 case TBLOCK_STARTED:
3999 case TBLOCK_INPROGRESS:
4000 return "INPROGRESS";
4005 case TBLOCK_ABORT_END:
4007 case TBLOCK_ABORT_PENDING:
4008 return "ABORT PEND";
4009 case TBLOCK_PREPARE:
4011 case TBLOCK_SUBBEGIN:
4013 case TBLOCK_SUBINPROGRESS:
4014 return "SUB INPROGRS";
4017 case TBLOCK_SUBABORT:
4019 case TBLOCK_SUBABORT_END:
4020 return "SUB ABORT END";
4021 case TBLOCK_SUBABORT_PENDING:
4022 return "SUB ABRT PEND";
4023 case TBLOCK_SUBRESTART:
4024 return "SUB RESTART";
4025 case TBLOCK_SUBABORT_RESTART:
4026 return "SUB AB RESTRT";
4028 return "UNRECOGNIZED";
4032 * TransStateAsString
4036 TransStateAsString(TransState state)
4044 case TRANS_INPROGRESS:
4053 return "UNRECOGNIZED";
4057 * xactGetCommittedChildren
4059 * Gets the list of committed children of the current transaction. The return
4060 * value is the number of child transactions. *children is set to point to a
4061 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4065 xactGetCommittedChildren(TransactionId **ptr)
4067 TransactionState s = CurrentTransactionState;
4069 TransactionId *children;
4072 nchildren = list_length(s->childXids);
4079 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4082 foreach(p, s->childXids)
4084 TransactionId child = lfirst_xid(p);
4086 *children++ = child;
4093 * XLOG support routines
4097 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4099 TransactionId *sub_xids;
4100 TransactionId max_xid;
4103 TransactionIdCommit(xid);
4105 /* Mark committed subtransactions as committed */
4106 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4107 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4109 /* Make sure nextXid is beyond any XID mentioned in the record */
4111 for (i = 0; i < xlrec->nsubxacts; i++)
4113 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4114 max_xid = sub_xids[i];
4116 if (TransactionIdFollowsOrEquals(max_xid,
4117 ShmemVariableCache->nextXid))
4119 ShmemVariableCache->nextXid = max_xid;
4120 TransactionIdAdvance(ShmemVariableCache->nextXid);
4123 /* Make sure files supposed to be dropped are dropped */
4124 for (i = 0; i < xlrec->nrels; i++)
4126 XLogDropRelation(xlrec->xnodes[i]);
4127 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4132 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4134 TransactionId *sub_xids;
4135 TransactionId max_xid;
4138 TransactionIdAbort(xid);
4140 /* Mark subtransactions as aborted */
4141 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4142 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4144 /* Make sure nextXid is beyond any XID mentioned in the record */
4146 for (i = 0; i < xlrec->nsubxacts; i++)
4148 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4149 max_xid = sub_xids[i];
4151 if (TransactionIdFollowsOrEquals(max_xid,
4152 ShmemVariableCache->nextXid))
4154 ShmemVariableCache->nextXid = max_xid;
4155 TransactionIdAdvance(ShmemVariableCache->nextXid);
4158 /* Make sure files supposed to be dropped are dropped */
4159 for (i = 0; i < xlrec->nrels; i++)
4161 XLogDropRelation(xlrec->xnodes[i]);
4162 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4167 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4169 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4171 if (info == XLOG_XACT_COMMIT)
4173 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4175 xact_redo_commit(xlrec, record->xl_xid);
4177 else if (info == XLOG_XACT_ABORT)
4179 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4181 xact_redo_abort(xlrec, record->xl_xid);
4183 else if (info == XLOG_XACT_PREPARE)
4185 /* the record contents are exactly the 2PC file */
4186 RecreateTwoPhaseFile(record->xl_xid,
4187 XLogRecGetData(record), record->xl_len);
4189 else if (info == XLOG_XACT_COMMIT_PREPARED)
4191 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4193 xact_redo_commit(&xlrec->crec, xlrec->xid);
4194 RemoveTwoPhaseFile(xlrec->xid, false);
4196 else if (info == XLOG_XACT_ABORT_PREPARED)
4198 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4200 xact_redo_abort(&xlrec->arec, xlrec->xid);
4201 RemoveTwoPhaseFile(xlrec->xid, false);
4204 elog(PANIC, "xact_redo: unknown op code %u", info);
4208 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4210 struct tm *tm = localtime(&xlrec->xtime);
4213 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4214 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4215 tm->tm_hour, tm->tm_min, tm->tm_sec);
4216 if (xlrec->nrels > 0)
4218 appendStringInfo(buf, "; rels:");
4219 for (i = 0; i < xlrec->nrels; i++)
4221 RelFileNode rnode = xlrec->xnodes[i];
4223 appendStringInfo(buf, " %u/%u/%u",
4224 rnode.spcNode, rnode.dbNode, rnode.relNode);
4227 if (xlrec->nsubxacts > 0)
4229 TransactionId *xacts = (TransactionId *)
4230 &xlrec->xnodes[xlrec->nrels];
4232 appendStringInfo(buf, "; subxacts:");
4233 for (i = 0; i < xlrec->nsubxacts; i++)
4234 appendStringInfo(buf, " %u", xacts[i]);
4239 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4241 struct tm *tm = localtime(&xlrec->xtime);
4244 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4245 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4246 tm->tm_hour, tm->tm_min, tm->tm_sec);
4247 if (xlrec->nrels > 0)
4249 appendStringInfo(buf, "; rels:");
4250 for (i = 0; i < xlrec->nrels; i++)
4252 RelFileNode rnode = xlrec->xnodes[i];
4254 appendStringInfo(buf, " %u/%u/%u",
4255 rnode.spcNode, rnode.dbNode, rnode.relNode);
4258 if (xlrec->nsubxacts > 0)
4260 TransactionId *xacts = (TransactionId *)
4261 &xlrec->xnodes[xlrec->nrels];
4263 appendStringInfo(buf, "; subxacts:");
4264 for (i = 0; i < xlrec->nsubxacts; i++)
4265 appendStringInfo(buf, " %u", xacts[i]);
4270 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4272 uint8 info = xl_info & ~XLR_INFO_MASK;
4274 if (info == XLOG_XACT_COMMIT)
4276 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4278 appendStringInfo(buf, "commit: ");
4279 xact_desc_commit(buf, xlrec);
4281 else if (info == XLOG_XACT_ABORT)
4283 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4285 appendStringInfo(buf, "abort: ");
4286 xact_desc_abort(buf, xlrec);
4288 else if (info == XLOG_XACT_PREPARE)
4290 appendStringInfo(buf, "prepare");
4292 else if (info == XLOG_XACT_COMMIT_PREPARED)
4294 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4296 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4297 xact_desc_commit(buf, &xlrec->crec);
4299 else if (info == XLOG_XACT_ABORT_PREPARED)
4301 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4303 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4304 xact_desc_abort(buf, &xlrec->arec);
4307 appendStringInfo(buf, "UNKNOWN");