1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.232 2007/02/01 19:10:25 momjian 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 * CurrentTransactionState always points to the current transaction state
130 * block. It will point to TopTransactionStateData when not in a
131 * transaction at all, or when in a top-level transaction.
133 static TransactionStateData TopTransactionStateData = {
134 0, /* transaction id */
135 0, /* subtransaction id */
136 NULL, /* savepoint name */
137 0, /* savepoint level */
138 TRANS_DEFAULT, /* transaction state */
139 TBLOCK_DEFAULT, /* transaction block state from the client
141 0, /* nesting level */
142 NULL, /* cur transaction context */
143 NULL, /* cur transaction resource owner */
144 NIL, /* subcommitted child Xids */
145 0, /* entry-time current userid */
146 false, /* entry-time xact r/o state */
147 NULL /* link to parent state block */
150 static TransactionState CurrentTransactionState = &TopTransactionStateData;
153 * The subtransaction ID and command ID assignment counters are global
154 * to a whole transaction, so we do not keep them in the state stack.
156 static SubTransactionId currentSubTransactionId;
157 static CommandId currentCommandId;
160 * xactStartTimestamp is the value of transaction_timestamp().
161 * stmtStartTimestamp is the value of statement_timestamp().
162 * These do not change as we enter and exit subtransactions, so we don't
163 * keep them inside the TransactionState stack.
165 static TimestampTz xactStartTimestamp;
166 static TimestampTz stmtStartTimestamp;
169 * GID to be used for preparing the current transaction. This is also
170 * global to a whole transaction, so we don't keep it in the state stack.
172 static char *prepareGID;
175 * Private context for transaction-abort work --- we reserve space for this
176 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
177 * when we've run out of memory.
179 static MemoryContext TransactionAbortContext = NULL;
182 * List of add-on start- and end-of-xact callbacks
184 typedef struct XactCallbackItem
186 struct XactCallbackItem *next;
187 XactCallback callback;
191 static XactCallbackItem *Xact_callbacks = NULL;
194 * List of add-on start- and end-of-subxact callbacks
196 typedef struct SubXactCallbackItem
198 struct SubXactCallbackItem *next;
199 SubXactCallback callback;
201 } SubXactCallbackItem;
203 static SubXactCallbackItem *SubXact_callbacks = NULL;
206 /* local function prototypes */
207 static void AssignSubTransactionId(TransactionState s);
208 static void AbortTransaction(void);
209 static void AtAbort_Memory(void);
210 static void AtCleanup_Memory(void);
211 static void AtAbort_ResourceOwner(void);
212 static void AtCommit_LocalCache(void);
213 static void AtCommit_Memory(void);
214 static void AtStart_Cache(void);
215 static void AtStart_Memory(void);
216 static void AtStart_ResourceOwner(void);
217 static void CallXactCallbacks(XactEvent event);
218 static void CallSubXactCallbacks(SubXactEvent event,
219 SubTransactionId mySubid,
220 SubTransactionId parentSubid);
221 static void CleanupTransaction(void);
222 static void CommitTransaction(void);
223 static void RecordTransactionAbort(void);
224 static void StartTransaction(void);
226 static void RecordSubTransactionCommit(void);
227 static void StartSubTransaction(void);
228 static void CommitSubTransaction(void);
229 static void AbortSubTransaction(void);
230 static void CleanupSubTransaction(void);
231 static void PushTransaction(void);
232 static void PopTransaction(void);
234 static void AtSubAbort_Memory(void);
235 static void AtSubCleanup_Memory(void);
236 static void AtSubAbort_ResourceOwner(void);
237 static void AtSubCommit_Memory(void);
238 static void AtSubStart_Memory(void);
239 static void AtSubStart_ResourceOwner(void);
241 static void ShowTransactionState(const char *str);
242 static void ShowTransactionStateRec(TransactionState state);
243 static const char *BlockStateAsString(TBlockState blockState);
244 static const char *TransStateAsString(TransState state);
247 /* ----------------------------------------------------------------
248 * transaction state accessors
249 * ----------------------------------------------------------------
255 * This returns true if we are currently running a query
256 * within an executing transaction.
259 IsTransactionState(void)
261 TransactionState s = CurrentTransactionState;
269 case TRANS_INPROGRESS:
280 * Shouldn't get here, but lint is not happy without this...
286 * IsAbortedTransactionBlockState
288 * This returns true if we are currently running a query
289 * within an aborted transaction block.
292 IsAbortedTransactionBlockState(void)
294 TransactionState s = CurrentTransactionState;
296 if (s->blockState == TBLOCK_ABORT ||
297 s->blockState == TBLOCK_SUBABORT)
305 * GetTopTransactionId
307 * Get the ID of the main transaction, even if we are currently inside
311 GetTopTransactionId(void)
313 return TopTransactionStateData.transactionId;
318 * GetCurrentTransactionId
320 * We do not assign XIDs to subtransactions until/unless this is called.
321 * When we do assign an XID to a subtransaction, recursively make sure
322 * its parent has one as well (this maintains the invariant that a child
323 * transaction has an XID following its parent's).
326 GetCurrentTransactionId(void)
328 TransactionState s = CurrentTransactionState;
330 if (!TransactionIdIsValid(s->transactionId))
331 AssignSubTransactionId(s);
333 return s->transactionId;
337 AssignSubTransactionId(TransactionState s)
339 ResourceOwner currentOwner;
341 Assert(s->parent != NULL);
342 Assert(s->state == TRANS_INPROGRESS);
343 if (!TransactionIdIsValid(s->parent->transactionId))
344 AssignSubTransactionId(s->parent);
347 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
349 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
350 * shared storage other than PG_PROC; because if there's no room for it in
351 * PG_PROC, the subtrans entry is needed to ensure that other backends see
352 * the Xid as "running". See GetNewTransactionId.
354 s->transactionId = GetNewTransactionId(true);
356 SubTransSetParent(s->transactionId, s->parent->transactionId);
359 * Acquire lock on the transaction XID. (We assume this cannot block.) We
360 * have to be sure that the lock is assigned to the transaction's
363 currentOwner = CurrentResourceOwner;
366 CurrentResourceOwner = s->curTransactionOwner;
368 XactLockTableInsert(s->transactionId);
372 /* Ensure CurrentResourceOwner is restored on error */
373 CurrentResourceOwner = currentOwner;
377 CurrentResourceOwner = currentOwner;
382 * GetCurrentTransactionIdIfAny
384 * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
385 * if we are currently not in a transaction, or in a transaction or
386 * subtransaction that has not yet assigned itself an XID.
389 GetCurrentTransactionIdIfAny(void)
391 TransactionState s = CurrentTransactionState;
393 return s->transactionId;
398 * GetCurrentSubTransactionId
401 GetCurrentSubTransactionId(void)
403 TransactionState s = CurrentTransactionState;
405 return s->subTransactionId;
410 * GetCurrentCommandId
413 GetCurrentCommandId(void)
415 /* this is global to a transaction, not subtransaction-local */
416 return currentCommandId;
420 * GetCurrentTransactionStartTimestamp
423 GetCurrentTransactionStartTimestamp(void)
425 return xactStartTimestamp;
429 * GetCurrentStatementStartTimestamp
432 GetCurrentStatementStartTimestamp(void)
434 return stmtStartTimestamp;
438 * SetCurrentStatementStartTimestamp
441 SetCurrentStatementStartTimestamp(void)
443 stmtStartTimestamp = GetCurrentTimestamp();
447 * GetCurrentTransactionNestLevel
449 * Note: this will return zero when not inside any transaction, one when
450 * inside a top-level transaction, etc.
453 GetCurrentTransactionNestLevel(void)
455 TransactionState s = CurrentTransactionState;
457 return s->nestingLevel;
462 * TransactionIdIsCurrentTransactionId
465 TransactionIdIsCurrentTransactionId(TransactionId xid)
470 * We always say that BootstrapTransactionId is "not my transaction ID"
471 * even when it is (ie, during bootstrap). Along with the fact that
472 * transam.c always treats BootstrapTransactionId as already committed,
473 * this causes the tqual.c routines to see all tuples as committed, which
474 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
475 * it never updates or deletes them, so all tuples can be presumed good
478 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
479 * not my transaction ID, so we can just return "false" immediately for
480 * any non-normal XID.
482 if (!TransactionIdIsNormal(xid))
486 * We will return true for the Xid of the current subtransaction, any of
487 * its subcommitted children, any of its parents, or any of their
488 * previously subcommitted children. However, a transaction being aborted
489 * is no longer "current", even though it may still have an entry on the
492 for (s = CurrentTransactionState; s != NULL; s = s->parent)
496 if (s->state == TRANS_ABORT)
498 if (!TransactionIdIsValid(s->transactionId))
499 continue; /* it can't have any child XIDs either */
500 if (TransactionIdEquals(xid, s->transactionId))
502 foreach(cell, s->childXids)
504 if (TransactionIdEquals(xid, lfirst_xid(cell)))
514 * CommandCounterIncrement
517 CommandCounterIncrement(void)
519 currentCommandId += 1;
520 if (currentCommandId == FirstCommandId) /* check for overflow */
522 currentCommandId -= 1;
524 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
525 errmsg("cannot have more than 2^32-1 commands in a transaction")));
528 /* Propagate new command ID into static snapshots, if set */
529 if (SerializableSnapshot)
530 SerializableSnapshot->curcid = currentCommandId;
532 LatestSnapshot->curcid = currentCommandId;
535 * make cache changes visible to me.
537 AtCommit_LocalCache();
542 /* ----------------------------------------------------------------
543 * StartTransaction stuff
544 * ----------------------------------------------------------------
553 AcceptInvalidationMessages();
562 TransactionState s = CurrentTransactionState;
565 * If this is the first time through, create a private context for
566 * AbortTransaction to work in. By reserving some space now, we can
567 * insulate AbortTransaction from out-of-memory scenarios. Like
568 * ErrorContext, we set it up with slow growth rate and a nonzero
569 * minimum size, so that space will be reserved immediately.
571 if (TransactionAbortContext == NULL)
572 TransactionAbortContext =
573 AllocSetContextCreate(TopMemoryContext,
574 "TransactionAbortContext",
580 * We shouldn't have a transaction context already.
582 Assert(TopTransactionContext == NULL);
585 * Create a toplevel context for the transaction.
587 TopTransactionContext =
588 AllocSetContextCreate(TopMemoryContext,
589 "TopTransactionContext",
590 ALLOCSET_DEFAULT_MINSIZE,
591 ALLOCSET_DEFAULT_INITSIZE,
592 ALLOCSET_DEFAULT_MAXSIZE);
595 * In a top-level transaction, CurTransactionContext is the same as
596 * TopTransactionContext.
598 CurTransactionContext = TopTransactionContext;
599 s->curTransactionContext = CurTransactionContext;
601 /* Make the CurTransactionContext active. */
602 MemoryContextSwitchTo(CurTransactionContext);
606 * AtStart_ResourceOwner
609 AtStart_ResourceOwner(void)
611 TransactionState s = CurrentTransactionState;
614 * We shouldn't have a transaction resource owner already.
616 Assert(TopTransactionResourceOwner == NULL);
619 * Create a toplevel resource owner for the transaction.
621 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
623 TopTransactionResourceOwner = s->curTransactionOwner;
624 CurTransactionResourceOwner = s->curTransactionOwner;
625 CurrentResourceOwner = s->curTransactionOwner;
628 /* ----------------------------------------------------------------
629 * StartSubTransaction stuff
630 * ----------------------------------------------------------------
637 AtSubStart_Memory(void)
639 TransactionState s = CurrentTransactionState;
641 Assert(CurTransactionContext != NULL);
644 * Create a CurTransactionContext, which will be used to hold data that
645 * survives subtransaction commit but disappears on subtransaction abort.
646 * We make it a child of the immediate parent's CurTransactionContext.
648 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
649 "CurTransactionContext",
650 ALLOCSET_DEFAULT_MINSIZE,
651 ALLOCSET_DEFAULT_INITSIZE,
652 ALLOCSET_DEFAULT_MAXSIZE);
653 s->curTransactionContext = CurTransactionContext;
655 /* Make the CurTransactionContext active. */
656 MemoryContextSwitchTo(CurTransactionContext);
660 * AtSubStart_ResourceOwner
663 AtSubStart_ResourceOwner(void)
665 TransactionState s = CurrentTransactionState;
667 Assert(s->parent != NULL);
670 * Create a resource owner for the subtransaction. We make it a child of
671 * the immediate parent's resource owner.
673 s->curTransactionOwner =
674 ResourceOwnerCreate(s->parent->curTransactionOwner,
677 CurTransactionResourceOwner = s->curTransactionOwner;
678 CurrentResourceOwner = s->curTransactionOwner;
681 /* ----------------------------------------------------------------
682 * CommitTransaction stuff
683 * ----------------------------------------------------------------
687 * RecordTransactionCommit
690 RecordTransactionCommit(void)
695 TransactionId *children;
697 /* Get data needed for commit record */
698 nrels = smgrGetPendingDeletes(true, &rels);
699 nchildren = xactGetCommittedChildren(&children);
702 * If we made neither any XLOG entries nor any temp-rel updates, and have
703 * no files to be deleted, we can omit recording the transaction commit at
704 * all. (This test includes the effects of subtransactions, so the
705 * presence of committed subxacts need not alone force a write.)
707 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
709 TransactionId xid = GetCurrentTransactionId();
713 /* Tell bufmgr and smgr to prepare for commit */
716 START_CRIT_SECTION();
719 * If our transaction made any transaction-controlled XLOG entries, we
720 * need to lock out checkpoint start between writing our XLOG record
721 * and updating pg_clog. Otherwise it is possible for the checkpoint
722 * to set REDO after the XLOG record but fail to flush the pg_clog
723 * update to disk, leading to loss of the transaction commit if we
724 * crash a little later. Slightly klugy fix for problem discovered
727 * (If it made no transaction-controlled XLOG entries, its XID appears
728 * nowhere in permanent storage, so no one else will ever care if it
729 * committed; so it doesn't matter if we lose the commit flag.)
731 * Note we only need a shared lock.
733 madeTCentries = (MyLastRecPtr.xrecoff != 0);
735 LWLockAcquire(CheckpointStartLock, LW_SHARED);
738 * We only need to log the commit in XLOG if the transaction made any
739 * transaction-controlled XLOG entries or will delete files.
741 if (madeTCentries || nrels > 0)
743 XLogRecData rdata[3];
745 xl_xact_commit xlrec;
747 xlrec.xtime = time(NULL);
749 xlrec.nsubxacts = nchildren;
750 rdata[0].data = (char *) (&xlrec);
751 rdata[0].len = MinSizeOfXactCommit;
752 rdata[0].buffer = InvalidBuffer;
753 /* dump rels to delete */
756 rdata[0].next = &(rdata[1]);
757 rdata[1].data = (char *) rels;
758 rdata[1].len = nrels * sizeof(RelFileNode);
759 rdata[1].buffer = InvalidBuffer;
762 /* dump committed child Xids */
765 rdata[lastrdata].next = &(rdata[2]);
766 rdata[2].data = (char *) children;
767 rdata[2].len = nchildren * sizeof(TransactionId);
768 rdata[2].buffer = InvalidBuffer;
771 rdata[lastrdata].next = NULL;
773 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
777 /* Just flush through last record written by me */
778 recptr = ProcLastRecEnd;
782 * We must flush our XLOG entries to disk if we made any XLOG entries,
783 * whether in or out of transaction control. For example, if we
784 * reported a nextval() result to the client, this ensures that any
785 * XLOG record generated by nextval will hit the disk before we report
786 * the transaction committed.
788 * Note: if we generated a commit record above, MyXactMadeXLogEntry
789 * will certainly be set now.
791 if (MyXactMadeXLogEntry)
794 * Sleep before flush! So we can flush more than one commit
795 * records per single fsync. (The idea is some other backend may
796 * do the XLogFlush while we're sleeping. This needs work still,
797 * because on most Unixen, the minimum select() delay is 10msec or
798 * more, which is way too long.)
800 * We do not sleep if enableFsync is not turned on, nor if there
801 * are fewer than CommitSiblings other backends with active
804 if (CommitDelay > 0 && enableFsync &&
805 CountActiveBackends() >= CommitSiblings)
806 pg_usleep(CommitDelay);
812 * We must mark the transaction committed in clog if its XID appears
813 * either in permanent rels or in local temporary rels. We test this
814 * by seeing if we made transaction-controlled entries *OR* local-rel
815 * tuple updates. Note that if we made only the latter, we have not
816 * emitted an XLOG record for our commit, and so in the event of a
817 * crash the clog update might be lost. This is okay because no one
818 * else will ever care whether we committed.
820 if (madeTCentries || MyXactMadeTempRelUpdate)
822 TransactionIdCommit(xid);
823 /* to avoid race conditions, the parent must commit first */
824 TransactionIdCommitTree(nchildren, children);
827 /* Unlock checkpoint lock if we acquired it */
829 LWLockRelease(CheckpointStartLock);
834 /* Break the chain of back-links in the XLOG records I output */
835 MyLastRecPtr.xrecoff = 0;
836 MyXactMadeXLogEntry = false;
837 MyXactMadeTempRelUpdate = false;
839 /* And clean up local data */
848 * AtCommit_LocalCache
851 AtCommit_LocalCache(void)
854 * Make catalog changes visible to me for the next command.
856 CommandEndInvalidationMessages();
863 AtCommit_Memory(void)
866 * Now that we're "out" of a transaction, have the system allocate things
867 * in the top memory context instead of per-transaction contexts.
869 MemoryContextSwitchTo(TopMemoryContext);
872 * Release all transaction-local memory.
874 Assert(TopTransactionContext != NULL);
875 MemoryContextDelete(TopTransactionContext);
876 TopTransactionContext = NULL;
877 CurTransactionContext = NULL;
878 CurrentTransactionState->curTransactionContext = NULL;
881 /* ----------------------------------------------------------------
882 * CommitSubTransaction stuff
883 * ----------------------------------------------------------------
890 AtSubCommit_Memory(void)
892 TransactionState s = CurrentTransactionState;
894 Assert(s->parent != NULL);
896 /* Return to parent transaction level's memory context. */
897 CurTransactionContext = s->parent->curTransactionContext;
898 MemoryContextSwitchTo(CurTransactionContext);
901 * Ordinarily we cannot throw away the child's CurTransactionContext,
902 * since the data it contains will be needed at upper commit. However, if
903 * there isn't actually anything in it, we can throw it away. This avoids
904 * a small memory leak in the common case of "trivial" subxacts.
906 if (MemoryContextIsEmpty(s->curTransactionContext))
908 MemoryContextDelete(s->curTransactionContext);
909 s->curTransactionContext = NULL;
914 * AtSubCommit_childXids
916 * Pass my own XID and my child XIDs up to my parent as committed children.
919 AtSubCommit_childXids(void)
921 TransactionState s = CurrentTransactionState;
922 MemoryContext old_cxt;
924 Assert(s->parent != NULL);
927 * We keep the child-XID lists in TopTransactionContext; this avoids
928 * setting up child-transaction contexts for what might be just a few
929 * bytes of grandchild XIDs.
931 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
933 s->parent->childXids = lappend_xid(s->parent->childXids,
936 if (s->childXids != NIL)
938 s->parent->childXids = list_concat(s->parent->childXids,
942 * list_concat doesn't free the list header for the second list; do so
943 * here to avoid memory leakage (kluge)
949 MemoryContextSwitchTo(old_cxt);
953 * RecordSubTransactionCommit
956 RecordSubTransactionCommit(void)
959 * We do not log the subcommit in XLOG; it doesn't matter until the
960 * top-level transaction commits.
962 * We must mark the subtransaction subcommitted in clog if its XID appears
963 * either in permanent rels or in local temporary rels. We test this by
964 * seeing if we made transaction-controlled entries *OR* local-rel tuple
965 * updates. (The test here actually covers the entire transaction tree so
966 * far, so it may mark subtransactions that don't really need it, but it's
967 * probably not worth being tenser. Note that if a prior subtransaction
968 * dirtied these variables, then RecordTransactionCommit will have to do
969 * the full pushup anyway...)
971 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
973 TransactionId xid = GetCurrentTransactionId();
975 /* XXX does this really need to be a critical section? */
976 START_CRIT_SECTION();
978 /* Record subtransaction subcommit */
979 TransactionIdSubCommit(xid);
985 /* ----------------------------------------------------------------
986 * AbortTransaction stuff
987 * ----------------------------------------------------------------
991 * RecordTransactionAbort
994 RecordTransactionAbort(void)
999 TransactionId *children;
1001 /* Get data needed for abort record */
1002 nrels = smgrGetPendingDeletes(false, &rels);
1003 nchildren = xactGetCommittedChildren(&children);
1006 * If we made neither any transaction-controlled XLOG entries nor any
1007 * temp-rel updates, and are not going to delete any files, we can omit
1008 * recording the transaction abort at all. No one will ever care that it
1009 * aborted. (These tests cover our whole transaction tree.)
1011 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1013 TransactionId xid = GetCurrentTransactionId();
1016 * Catch the scenario where we aborted partway through
1017 * RecordTransactionCommit ...
1019 if (TransactionIdDidCommit(xid))
1020 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1022 START_CRIT_SECTION();
1025 * We only need to log the abort in XLOG if the transaction made any
1026 * transaction-controlled XLOG entries or will delete files. (If it
1027 * made no transaction-controlled XLOG entries, its XID appears
1028 * nowhere in permanent storage, so no one else will ever care if it
1031 * We do not flush XLOG to disk unless deleting files, since the
1032 * default assumption after a crash would be that we aborted, anyway.
1033 * For the same reason, we don't need to worry about interlocking
1034 * against checkpoint start.
1036 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1038 XLogRecData rdata[3];
1040 xl_xact_abort xlrec;
1043 xlrec.xtime = time(NULL);
1044 xlrec.nrels = nrels;
1045 xlrec.nsubxacts = nchildren;
1046 rdata[0].data = (char *) (&xlrec);
1047 rdata[0].len = MinSizeOfXactAbort;
1048 rdata[0].buffer = InvalidBuffer;
1049 /* dump rels to delete */
1052 rdata[0].next = &(rdata[1]);
1053 rdata[1].data = (char *) rels;
1054 rdata[1].len = nrels * sizeof(RelFileNode);
1055 rdata[1].buffer = InvalidBuffer;
1058 /* dump committed child Xids */
1061 rdata[lastrdata].next = &(rdata[2]);
1062 rdata[2].data = (char *) children;
1063 rdata[2].len = nchildren * sizeof(TransactionId);
1064 rdata[2].buffer = InvalidBuffer;
1067 rdata[lastrdata].next = NULL;
1069 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1071 /* Must flush if we are deleting files... */
1077 * Mark the transaction aborted in clog. This is not absolutely
1078 * necessary but we may as well do it while we are here.
1080 * The ordering here isn't critical but it seems best to mark the
1081 * parent first. This assures an atomic transition of all the
1082 * subtransactions to aborted state from the point of view of
1083 * concurrent TransactionIdDidAbort calls.
1085 TransactionIdAbort(xid);
1086 TransactionIdAbortTree(nchildren, children);
1091 /* Break the chain of back-links in the XLOG records I output */
1092 MyLastRecPtr.xrecoff = 0;
1093 MyXactMadeXLogEntry = false;
1094 MyXactMadeTempRelUpdate = false;
1096 /* And clean up local data */
1107 AtAbort_Memory(void)
1110 * Switch into TransactionAbortContext, which should have some free
1111 * space even if nothing else does. We'll work in this context until
1112 * we've finished cleaning up.
1114 * It is barely possible to get here when we've not been able to create
1115 * TransactionAbortContext yet; if so use TopMemoryContext.
1117 if (TransactionAbortContext != NULL)
1118 MemoryContextSwitchTo(TransactionAbortContext);
1120 MemoryContextSwitchTo(TopMemoryContext);
1127 AtSubAbort_Memory(void)
1129 Assert(TransactionAbortContext != NULL);
1131 MemoryContextSwitchTo(TransactionAbortContext);
1136 * AtAbort_ResourceOwner
1139 AtAbort_ResourceOwner(void)
1142 * Make sure we have a valid ResourceOwner, if possible (else it will be
1143 * NULL, which is OK)
1145 CurrentResourceOwner = TopTransactionResourceOwner;
1149 * AtSubAbort_ResourceOwner
1152 AtSubAbort_ResourceOwner(void)
1154 TransactionState s = CurrentTransactionState;
1156 /* Make sure we have a valid ResourceOwner */
1157 CurrentResourceOwner = s->curTransactionOwner;
1162 * AtSubAbort_childXids
1165 AtSubAbort_childXids(void)
1167 TransactionState s = CurrentTransactionState;
1170 * We keep the child-XID lists in TopTransactionContext (see
1171 * AtSubCommit_childXids). This means we'd better free the list
1172 * explicitly at abort to avoid leakage.
1174 list_free(s->childXids);
1179 * RecordSubTransactionAbort
1182 RecordSubTransactionAbort(void)
1186 TransactionId xid = GetCurrentTransactionId();
1188 TransactionId *children;
1190 /* Get data needed for abort record */
1191 nrels = smgrGetPendingDeletes(false, &rels);
1192 nchildren = xactGetCommittedChildren(&children);
1195 * If we made neither any transaction-controlled XLOG entries nor any
1196 * temp-rel updates, and are not going to delete any files, we can omit
1197 * recording the transaction abort at all. No one will ever care that it
1198 * aborted. (These tests cover our whole transaction tree, and therefore
1199 * may mark subxacts that don't really need it, but it's probably not
1200 * worth being tenser.)
1202 * In this case we needn't worry about marking subcommitted children as
1203 * aborted, because they didn't mark themselves as subcommitted in the
1204 * first place; see the optimization in RecordSubTransactionCommit.
1206 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1208 START_CRIT_SECTION();
1211 * We only need to log the abort in XLOG if the transaction made any
1212 * transaction-controlled XLOG entries or will delete files.
1214 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1216 XLogRecData rdata[3];
1218 xl_xact_abort xlrec;
1221 xlrec.xtime = time(NULL);
1222 xlrec.nrels = nrels;
1223 xlrec.nsubxacts = nchildren;
1224 rdata[0].data = (char *) (&xlrec);
1225 rdata[0].len = MinSizeOfXactAbort;
1226 rdata[0].buffer = InvalidBuffer;
1227 /* dump rels to delete */
1230 rdata[0].next = &(rdata[1]);
1231 rdata[1].data = (char *) rels;
1232 rdata[1].len = nrels * sizeof(RelFileNode);
1233 rdata[1].buffer = InvalidBuffer;
1236 /* dump committed child Xids */
1239 rdata[lastrdata].next = &(rdata[2]);
1240 rdata[2].data = (char *) children;
1241 rdata[2].len = nchildren * sizeof(TransactionId);
1242 rdata[2].buffer = InvalidBuffer;
1245 rdata[lastrdata].next = NULL;
1247 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1249 /* Must flush if we are deleting files... */
1255 * Mark the transaction aborted in clog. This is not absolutely
1256 * necessary but XactLockTableWait makes use of it to avoid waiting
1257 * for already-aborted subtransactions.
1259 TransactionIdAbort(xid);
1260 TransactionIdAbortTree(nchildren, children);
1266 * We can immediately remove failed XIDs from PGPROC's cache of running
1267 * child XIDs. It's easiest to do it here while we have the child XID
1268 * array at hand, even though in the main-transaction case the equivalent
1269 * work happens just after return from RecordTransactionAbort.
1271 XidCacheRemoveRunningXids(xid, nchildren, children);
1273 /* And clean up local data */
1280 /* ----------------------------------------------------------------
1281 * CleanupTransaction stuff
1282 * ----------------------------------------------------------------
1289 AtCleanup_Memory(void)
1291 Assert(CurrentTransactionState->parent == NULL);
1294 * Now that we're "out" of a transaction, have the system allocate things
1295 * in the top memory context instead of per-transaction contexts.
1297 MemoryContextSwitchTo(TopMemoryContext);
1300 * Clear the special abort context for next time.
1302 if (TransactionAbortContext != NULL)
1303 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1306 * Release all transaction-local memory.
1308 if (TopTransactionContext != NULL)
1309 MemoryContextDelete(TopTransactionContext);
1310 TopTransactionContext = NULL;
1311 CurTransactionContext = NULL;
1312 CurrentTransactionState->curTransactionContext = NULL;
1316 /* ----------------------------------------------------------------
1317 * CleanupSubTransaction stuff
1318 * ----------------------------------------------------------------
1322 * AtSubCleanup_Memory
1325 AtSubCleanup_Memory(void)
1327 TransactionState s = CurrentTransactionState;
1329 Assert(s->parent != NULL);
1331 /* Make sure we're not in an about-to-be-deleted context */
1332 MemoryContextSwitchTo(s->parent->curTransactionContext);
1333 CurTransactionContext = s->parent->curTransactionContext;
1336 * Clear the special abort context for next time.
1338 if (TransactionAbortContext != NULL)
1339 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1342 * Delete the subxact local memory contexts. Its CurTransactionContext can
1343 * go too (note this also kills CurTransactionContexts from any children
1346 if (s->curTransactionContext)
1347 MemoryContextDelete(s->curTransactionContext);
1348 s->curTransactionContext = NULL;
1351 /* ----------------------------------------------------------------
1352 * interface routines
1353 * ----------------------------------------------------------------
1360 StartTransaction(void)
1365 * Let's just make sure the state stack is empty
1367 s = &TopTransactionStateData;
1368 CurrentTransactionState = s;
1371 * check the current transaction state
1373 if (s->state != TRANS_DEFAULT)
1374 elog(WARNING, "StartTransaction while in %s state",
1375 TransStateAsString(s->state));
1378 * set the current transaction state information appropriately during
1381 s->state = TRANS_START;
1382 s->transactionId = InvalidTransactionId; /* until assigned */
1385 * Make sure we've freed any old snapshot, and reset xact state variables
1388 XactIsoLevel = DefaultXactIsoLevel;
1389 XactReadOnly = DefaultXactReadOnly;
1392 * reinitialize within-transaction counters
1394 s->subTransactionId = TopSubTransactionId;
1395 currentSubTransactionId = TopSubTransactionId;
1396 currentCommandId = FirstCommandId;
1399 * must initialize resource-management stuff first
1402 AtStart_ResourceOwner();
1405 * generate a new transaction id
1407 s->transactionId = GetNewTransactionId(false);
1409 XactLockTableInsert(s->transactionId);
1411 PG_TRACE1(transaction__start, s->transactionId);
1414 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1415 * as the first command's statement_timestamp(), so don't do a fresh
1416 * GetCurrentTimestamp() call (which'd be expensive anyway).
1418 xactStartTimestamp = stmtStartTimestamp;
1419 pgstat_report_txn_timestamp(xactStartTimestamp);
1422 * initialize current transaction state fields
1424 s->nestingLevel = 1;
1428 * You might expect to see "s->currentUser = GetUserId();" here, but you
1429 * won't because it doesn't work during startup; the userid isn't set yet
1430 * during a backend's first transaction start. We only use the
1431 * currentUser field in sub-transaction state structs.
1433 * prevXactReadOnly is also valid only in sub-transactions.
1437 * initialize other subsystems for new transaction
1441 AfterTriggerBeginXact();
1444 * done with start processing, set current transaction state to "in
1447 s->state = TRANS_INPROGRESS;
1449 ShowTransactionState("StartTransaction");
1456 * NB: if you change this routine, better look at PrepareTransaction too!
1459 CommitTransaction(void)
1461 TransactionState s = CurrentTransactionState;
1463 ShowTransactionState("CommitTransaction");
1466 * check the current transaction state
1468 if (s->state != TRANS_INPROGRESS)
1469 elog(WARNING, "CommitTransaction while in %s state",
1470 TransStateAsString(s->state));
1471 Assert(s->parent == NULL);
1474 * Do pre-commit processing (most of this stuff requires database access,
1475 * and in fact could still cause an error...)
1477 * It is possible for CommitHoldablePortals to invoke functions that queue
1478 * deferred triggers, and it's also possible that triggers create holdable
1479 * cursors. So we have to loop until there's nothing left to do.
1484 * Fire all currently pending deferred triggers.
1486 AfterTriggerFireDeferred();
1489 * Convert any open holdable cursors into static portals. If there
1490 * weren't any, we are done ... otherwise loop back to check if they
1491 * queued deferred triggers. Lather, rinse, repeat.
1493 if (!CommitHoldablePortals())
1497 /* Now we can shut down the deferred-trigger manager */
1498 AfterTriggerEndXact(true);
1500 /* Close any open regular cursors */
1504 * Let ON COMMIT management do its thing (must happen after closing
1505 * cursors, to avoid dangling-reference problems)
1507 PreCommit_on_commit_actions();
1509 /* close large objects before lower-level cleanup */
1510 AtEOXact_LargeObject(true);
1512 /* NOTIFY commit must come before lower-level cleanup */
1516 * Update flat files if we changed pg_database, pg_authid or
1517 * pg_auth_members. This should be the last step before commit.
1519 AtEOXact_UpdateFlatFiles(true);
1521 /* Prevent cancel/die interrupt while cleaning up */
1525 * set the current transaction state information appropriately during
1528 s->state = TRANS_COMMIT;
1531 * Here is where we really truly commit.
1533 RecordTransactionCommit();
1536 * Let others know about no transaction in progress by me. Note that
1537 * this must be done _before_ releasing locks we hold and _after_
1538 * RecordTransactionCommit.
1540 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1541 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1542 * xid 1 is doing commit while xid 2 gets snapshot.
1543 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1544 * xid 0 as running as well, or it will be able to see two tuple versions
1545 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1548 * Note: MyProc may be null during bootstrap.
1553 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1554 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1555 MyProc->xid = InvalidTransactionId;
1556 MyProc->xmin = InvalidTransactionId;
1557 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1559 /* Clear the subtransaction-XID cache too while holding the lock */
1560 MyProc->subxids.nxids = 0;
1561 MyProc->subxids.overflowed = false;
1563 LWLockRelease(ProcArrayLock);
1566 PG_TRACE1(transaction__commit, s->transactionId);
1569 * This is all post-commit cleanup. Note that if an error is raised here,
1570 * it's too late to abort the transaction. This should be just
1571 * noncritical resource releasing.
1573 * The ordering of operations is not entirely random. The idea is:
1574 * release resources visible to other backends (eg, files, buffer pins);
1575 * then release locks; then release backend-local resources. We want to
1576 * release locks at the point where any backend waiting for us will see
1577 * our transaction as being fully cleaned up.
1579 * Resources that can be associated with individual queries are handled by
1580 * the ResourceOwner mechanism. The other calls here are for backend-wide
1584 CallXactCallbacks(XACT_EVENT_COMMIT);
1586 ResourceOwnerRelease(TopTransactionResourceOwner,
1587 RESOURCE_RELEASE_BEFORE_LOCKS,
1590 /* Check we've released all buffer pins */
1591 AtEOXact_Buffers(true);
1593 /* Clean up the relation cache */
1594 AtEOXact_RelationCache(true);
1597 * Make catalog changes visible to all backends. This has to happen after
1598 * relcache references are dropped (see comments for
1599 * AtEOXact_RelationCache), but before locks are released (if anyone is
1600 * waiting for lock on a relation we've modified, we want them to know
1601 * about the catalog change before they start using the relation).
1603 AtEOXact_Inval(true);
1606 * Likewise, dropping of files deleted during the transaction is best done
1607 * after releasing relcache and buffer pins. (This is not strictly
1608 * necessary during commit, since such pins should have been released
1609 * already, but this ordering is definitely critical during abort.)
1611 smgrDoPendingDeletes(true);
1613 AtEOXact_MultiXact();
1615 ResourceOwnerRelease(TopTransactionResourceOwner,
1616 RESOURCE_RELEASE_LOCKS,
1618 ResourceOwnerRelease(TopTransactionResourceOwner,
1619 RESOURCE_RELEASE_AFTER_LOCKS,
1622 /* Check we've released all catcache entries */
1623 AtEOXact_CatCache(true);
1625 AtEOXact_GUC(true, false);
1627 AtEOXact_on_commit_actions(true);
1628 AtEOXact_Namespace(true);
1629 /* smgrcommit already done */
1631 pgstat_count_xact_commit();
1632 pgstat_report_txn_timestamp(0);
1634 CurrentResourceOwner = NULL;
1635 ResourceOwnerDelete(TopTransactionResourceOwner);
1636 s->curTransactionOwner = NULL;
1637 CurTransactionResourceOwner = NULL;
1638 TopTransactionResourceOwner = NULL;
1642 s->transactionId = InvalidTransactionId;
1643 s->subTransactionId = InvalidSubTransactionId;
1644 s->nestingLevel = 0;
1648 * done with commit processing, set current transaction state back to
1651 s->state = TRANS_DEFAULT;
1653 RESUME_INTERRUPTS();
1658 * PrepareTransaction
1660 * NB: if you change this routine, better look at CommitTransaction too!
1663 PrepareTransaction(void)
1665 TransactionState s = CurrentTransactionState;
1666 TransactionId xid = GetCurrentTransactionId();
1667 GlobalTransaction gxact;
1668 TimestampTz prepared_at;
1670 ShowTransactionState("PrepareTransaction");
1673 * check the current transaction state
1675 if (s->state != TRANS_INPROGRESS)
1676 elog(WARNING, "PrepareTransaction while in %s state",
1677 TransStateAsString(s->state));
1678 Assert(s->parent == NULL);
1681 * Do pre-commit processing (most of this stuff requires database access,
1682 * and in fact could still cause an error...)
1684 * It is possible for PrepareHoldablePortals to invoke functions that
1685 * queue deferred triggers, and it's also possible that triggers create
1686 * holdable cursors. So we have to loop until there's nothing left to do.
1691 * Fire all currently pending deferred triggers.
1693 AfterTriggerFireDeferred();
1696 * Convert any open holdable cursors into static portals. If there
1697 * weren't any, we are done ... otherwise loop back to check if they
1698 * queued deferred triggers. Lather, rinse, repeat.
1700 if (!PrepareHoldablePortals())
1704 /* Now we can shut down the deferred-trigger manager */
1705 AfterTriggerEndXact(true);
1707 /* Close any open regular cursors */
1711 * Let ON COMMIT management do its thing (must happen after closing
1712 * cursors, to avoid dangling-reference problems)
1714 PreCommit_on_commit_actions();
1716 /* close large objects before lower-level cleanup */
1717 AtEOXact_LargeObject(true);
1719 /* NOTIFY and flatfiles will be handled below */
1721 /* Prevent cancel/die interrupt while cleaning up */
1725 * set the current transaction state information appropriately during
1726 * prepare processing
1728 s->state = TRANS_PREPARE;
1730 prepared_at = GetCurrentTimestamp();
1732 /* Tell bufmgr and smgr to prepare for commit */
1736 * Reserve the GID for this transaction. This could fail if the requested
1737 * GID is invalid or already in use.
1739 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1740 GetUserId(), MyDatabaseId);
1744 * Collect data for the 2PC state file. Note that in general, no actual
1745 * state change should happen in the called modules during this step,
1746 * since it's still possible to fail before commit, and in that case we
1747 * want transaction abort to be able to clean up. (In particular, the
1748 * AtPrepare routines may error out if they find cases they cannot
1749 * handle.) State cleanup should happen in the PostPrepare routines
1750 * below. However, some modules can go ahead and clear state here because
1751 * they wouldn't do anything with it during abort anyway.
1753 * Note: because the 2PC state file records will be replayed in the same
1754 * order they are made, the order of these calls has to match the order in
1755 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1756 * PREPARED; in particular, pay attention to whether things should happen
1757 * before or after releasing the transaction's locks.
1759 StartPrepare(gxact);
1762 AtPrepare_UpdateFlatFiles();
1767 * Here is where we really truly prepare.
1769 * We have to record transaction prepares even if we didn't make any
1770 * updates, because the transaction manager might get confused if we lose
1771 * a global transaction.
1776 * Now we clean up backend-internal state and release internal resources.
1779 /* Break the chain of back-links in the XLOG records I output */
1780 MyLastRecPtr.xrecoff = 0;
1781 MyXactMadeXLogEntry = false;
1782 MyXactMadeTempRelUpdate = false;
1785 * Let others know about no transaction in progress by me. This has to be
1786 * done *after* the prepared transaction has been marked valid, else
1787 * someone may think it is unlocked and recyclable.
1790 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1791 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1792 MyProc->xid = InvalidTransactionId;
1793 MyProc->xmin = InvalidTransactionId;
1794 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1796 /* Clear the subtransaction-XID cache too while holding the lock */
1797 MyProc->subxids.nxids = 0;
1798 MyProc->subxids.overflowed = false;
1800 LWLockRelease(ProcArrayLock);
1803 * This is all post-transaction cleanup. Note that if an error is raised
1804 * here, it's too late to abort the transaction. This should be just
1805 * noncritical resource releasing. See notes in CommitTransaction.
1808 CallXactCallbacks(XACT_EVENT_PREPARE);
1810 ResourceOwnerRelease(TopTransactionResourceOwner,
1811 RESOURCE_RELEASE_BEFORE_LOCKS,
1814 /* Check we've released all buffer pins */
1815 AtEOXact_Buffers(true);
1817 /* Clean up the relation cache */
1818 AtEOXact_RelationCache(true);
1820 /* notify and flatfiles don't need a postprepare call */
1822 PostPrepare_Inval();
1826 AtEOXact_MultiXact();
1828 PostPrepare_Locks(xid);
1830 ResourceOwnerRelease(TopTransactionResourceOwner,
1831 RESOURCE_RELEASE_LOCKS,
1833 ResourceOwnerRelease(TopTransactionResourceOwner,
1834 RESOURCE_RELEASE_AFTER_LOCKS,
1837 /* Check we've released all catcache entries */
1838 AtEOXact_CatCache(true);
1840 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1841 AtEOXact_GUC(true, false);
1843 AtEOXact_on_commit_actions(true);
1844 AtEOXact_Namespace(true);
1845 /* smgrcommit already done */
1848 CurrentResourceOwner = NULL;
1849 ResourceOwnerDelete(TopTransactionResourceOwner);
1850 s->curTransactionOwner = NULL;
1851 CurTransactionResourceOwner = NULL;
1852 TopTransactionResourceOwner = NULL;
1856 s->transactionId = InvalidTransactionId;
1857 s->subTransactionId = InvalidSubTransactionId;
1858 s->nestingLevel = 0;
1862 * done with 1st phase commit processing, set current transaction state
1865 s->state = TRANS_DEFAULT;
1867 RESUME_INTERRUPTS();
1875 AbortTransaction(void)
1877 TransactionState s = CurrentTransactionState;
1879 /* Prevent cancel/die interrupt while cleaning up */
1882 /* Make sure we have a valid memory context and resource owner */
1884 AtAbort_ResourceOwner();
1887 * Release any LW locks we might be holding as quickly as possible.
1888 * (Regular locks, however, must be held till we finish aborting.)
1889 * Releasing LW locks is critical since we might try to grab them again
1890 * while cleaning up!
1894 /* Clean up buffer I/O and buffer context locks, too */
1899 * Also clean up any open wait for lock, since the lock manager will choke
1900 * if we try to wait for another lock before doing this.
1905 * check the current transaction state
1907 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1908 elog(WARNING, "AbortTransaction while in %s state",
1909 TransStateAsString(s->state));
1910 Assert(s->parent == NULL);
1913 * set the current transaction state information appropriately during the
1916 s->state = TRANS_ABORT;
1919 * Reset user id which might have been changed transiently. We cannot use
1920 * s->currentUser, since it may not be set yet; instead rely on internal
1921 * state of miscinit.c.
1923 * (Note: it is not necessary to restore session authorization here
1924 * because that can only be changed via GUC, and GUC will take care of
1925 * rolling it back if need be. However, an error within a SECURITY
1926 * DEFINER function could send control here with the wrong current
1932 * do abort processing
1934 AfterTriggerEndXact(false);
1936 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1938 AtEOXact_UpdateFlatFiles(false);
1941 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1942 * far as assigning an XID to advertise).
1944 if (TransactionIdIsValid(s->transactionId))
1945 RecordTransactionAbort();
1948 * Let others know about no transaction in progress by me. Note that this
1949 * must be done _before_ releasing locks we hold and _after_
1950 * RecordTransactionAbort.
1954 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1955 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1956 MyProc->xid = InvalidTransactionId;
1957 MyProc->xmin = InvalidTransactionId;
1958 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1960 /* Clear the subtransaction-XID cache too while holding the lock */
1961 MyProc->subxids.nxids = 0;
1962 MyProc->subxids.overflowed = false;
1964 LWLockRelease(ProcArrayLock);
1967 PG_TRACE1(transaction__abort, s->transactionId);
1970 * Post-abort cleanup. See notes in CommitTransaction() concerning
1974 CallXactCallbacks(XACT_EVENT_ABORT);
1976 ResourceOwnerRelease(TopTransactionResourceOwner,
1977 RESOURCE_RELEASE_BEFORE_LOCKS,
1979 AtEOXact_Buffers(false);
1980 AtEOXact_RelationCache(false);
1981 AtEOXact_Inval(false);
1982 smgrDoPendingDeletes(false);
1983 AtEOXact_MultiXact();
1984 ResourceOwnerRelease(TopTransactionResourceOwner,
1985 RESOURCE_RELEASE_LOCKS,
1987 ResourceOwnerRelease(TopTransactionResourceOwner,
1988 RESOURCE_RELEASE_AFTER_LOCKS,
1990 AtEOXact_CatCache(false);
1992 AtEOXact_GUC(false, false);
1993 AtEOXact_SPI(false);
1994 AtEOXact_on_commit_actions(false);
1995 AtEOXact_Namespace(false);
1998 pgstat_count_xact_rollback();
1999 pgstat_report_txn_timestamp(0);
2002 * State remains TRANS_ABORT until CleanupTransaction().
2004 RESUME_INTERRUPTS();
2008 * CleanupTransaction
2011 CleanupTransaction(void)
2013 TransactionState s = CurrentTransactionState;
2016 * State should still be TRANS_ABORT from AbortTransaction().
2018 if (s->state != TRANS_ABORT)
2019 elog(FATAL, "CleanupTransaction: unexpected state %s",
2020 TransStateAsString(s->state));
2023 * do abort cleanup processing
2025 AtCleanup_Portals(); /* now safe to release portal memory */
2027 CurrentResourceOwner = NULL; /* and resource owner */
2028 if (TopTransactionResourceOwner)
2029 ResourceOwnerDelete(TopTransactionResourceOwner);
2030 s->curTransactionOwner = NULL;
2031 CurTransactionResourceOwner = NULL;
2032 TopTransactionResourceOwner = NULL;
2034 AtCleanup_Memory(); /* and transaction memory */
2036 s->transactionId = InvalidTransactionId;
2037 s->subTransactionId = InvalidSubTransactionId;
2038 s->nestingLevel = 0;
2042 * done with abort processing, set current transaction state back to
2045 s->state = TRANS_DEFAULT;
2049 * StartTransactionCommand
2052 StartTransactionCommand(void)
2054 TransactionState s = CurrentTransactionState;
2056 switch (s->blockState)
2059 * if we aren't in a transaction block, we just do our usual start
2062 case TBLOCK_DEFAULT:
2064 s->blockState = TBLOCK_STARTED;
2068 * We are somewhere in a transaction block or subtransaction and
2069 * about to start a new command. For now we do nothing, but
2070 * someday we may do command-local resource initialization. (Note
2071 * that any needed CommandCounterIncrement was done by the
2072 * previous CommitTransactionCommand.)
2074 case TBLOCK_INPROGRESS:
2075 case TBLOCK_SUBINPROGRESS:
2079 * Here we are in a failed transaction block (one of the commands
2080 * caused an abort) so we do nothing but remain in the abort
2081 * state. Eventually we will get a ROLLBACK command which will
2082 * get us out of this state. (It is up to other code to ensure
2083 * that no commands other than ROLLBACK will be processed in these
2087 case TBLOCK_SUBABORT:
2090 /* These cases are invalid. */
2091 case TBLOCK_STARTED:
2093 case TBLOCK_SUBBEGIN:
2096 case TBLOCK_ABORT_END:
2097 case TBLOCK_SUBABORT_END:
2098 case TBLOCK_ABORT_PENDING:
2099 case TBLOCK_SUBABORT_PENDING:
2100 case TBLOCK_SUBRESTART:
2101 case TBLOCK_SUBABORT_RESTART:
2102 case TBLOCK_PREPARE:
2103 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2104 BlockStateAsString(s->blockState));
2109 * We must switch to CurTransactionContext before returning. This is
2110 * already done if we called StartTransaction, otherwise not.
2112 Assert(CurTransactionContext != NULL);
2113 MemoryContextSwitchTo(CurTransactionContext);
2117 * CommitTransactionCommand
2120 CommitTransactionCommand(void)
2122 TransactionState s = CurrentTransactionState;
2124 switch (s->blockState)
2127 * This shouldn't happen, because it means the previous
2128 * StartTransactionCommand didn't set the STARTED state
2131 case TBLOCK_DEFAULT:
2132 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2133 BlockStateAsString(s->blockState));
2137 * If we aren't in a transaction block, just do our usual
2138 * transaction commit, and return to the idle state.
2140 case TBLOCK_STARTED:
2141 CommitTransaction();
2142 s->blockState = TBLOCK_DEFAULT;
2146 * We are completing a "BEGIN TRANSACTION" command, so we change
2147 * to the "transaction block in progress" state and return. (We
2148 * assume the BEGIN did nothing to the database, so we need no
2149 * CommandCounterIncrement.)
2152 s->blockState = TBLOCK_INPROGRESS;
2156 * This is the case when we have finished executing a command
2157 * someplace within a transaction block. We increment the command
2158 * counter and return.
2160 case TBLOCK_INPROGRESS:
2161 case TBLOCK_SUBINPROGRESS:
2162 CommandCounterIncrement();
2166 * We are completing a "COMMIT" command. Do it and return to the
2170 CommitTransaction();
2171 s->blockState = TBLOCK_DEFAULT;
2175 * Here we are in the middle of a transaction block but one of the
2176 * commands caused an abort so we do nothing but remain in the
2177 * abort state. Eventually we will get a ROLLBACK comand.
2180 case TBLOCK_SUBABORT:
2184 * Here we were in an aborted transaction block and we just got
2185 * the ROLLBACK command from the user, so clean up the
2186 * already-aborted transaction and return to the idle state.
2188 case TBLOCK_ABORT_END:
2189 CleanupTransaction();
2190 s->blockState = TBLOCK_DEFAULT;
2194 * Here we were in a perfectly good transaction block but the user
2195 * told us to ROLLBACK anyway. We have to abort the transaction
2196 * and then clean up.
2198 case TBLOCK_ABORT_PENDING:
2200 CleanupTransaction();
2201 s->blockState = TBLOCK_DEFAULT;
2205 * We are completing a "PREPARE TRANSACTION" command. Do it and
2206 * return to the idle state.
2208 case TBLOCK_PREPARE:
2209 PrepareTransaction();
2210 s->blockState = TBLOCK_DEFAULT;
2214 * We were just issued a SAVEPOINT inside a transaction block.
2215 * Start a subtransaction. (DefineSavepoint already did
2216 * PushTransaction, so as to have someplace to put the SUBBEGIN
2219 case TBLOCK_SUBBEGIN:
2220 StartSubTransaction();
2221 s->blockState = TBLOCK_SUBINPROGRESS;
2225 * We were issued a COMMIT or RELEASE command, so we end the
2226 * current subtransaction and return to the parent transaction.
2227 * The parent might be ended too, so repeat till we are all the
2228 * way out or find an INPROGRESS transaction.
2233 CommitSubTransaction();
2234 s = CurrentTransactionState; /* changed by pop */
2235 } while (s->blockState == TBLOCK_SUBEND);
2236 /* If we had a COMMIT command, finish off the main xact too */
2237 if (s->blockState == TBLOCK_END)
2239 Assert(s->parent == NULL);
2240 CommitTransaction();
2241 s->blockState = TBLOCK_DEFAULT;
2243 else if (s->blockState == TBLOCK_PREPARE)
2245 Assert(s->parent == NULL);
2246 PrepareTransaction();
2247 s->blockState = TBLOCK_DEFAULT;
2251 Assert(s->blockState == TBLOCK_INPROGRESS ||
2252 s->blockState == TBLOCK_SUBINPROGRESS);
2257 * The current already-failed subtransaction is ending due to a
2258 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2259 * examine the parent (which could be in any of several states).
2261 case TBLOCK_SUBABORT_END:
2262 CleanupSubTransaction();
2263 CommitTransactionCommand();
2267 * As above, but it's not dead yet, so abort first.
2269 case TBLOCK_SUBABORT_PENDING:
2270 AbortSubTransaction();
2271 CleanupSubTransaction();
2272 CommitTransactionCommand();
2276 * The current subtransaction is the target of a ROLLBACK TO
2277 * command. Abort and pop it, then start a new subtransaction
2278 * with the same name.
2280 case TBLOCK_SUBRESTART:
2285 /* save name and keep Cleanup from freeing it */
2288 savepointLevel = s->savepointLevel;
2290 AbortSubTransaction();
2291 CleanupSubTransaction();
2293 DefineSavepoint(NULL);
2294 s = CurrentTransactionState; /* changed by push */
2296 s->savepointLevel = savepointLevel;
2298 /* This is the same as TBLOCK_SUBBEGIN case */
2299 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2300 StartSubTransaction();
2301 s->blockState = TBLOCK_SUBINPROGRESS;
2306 * Same as above, but the subtransaction had already failed, so we
2307 * don't need AbortSubTransaction.
2309 case TBLOCK_SUBABORT_RESTART:
2314 /* save name and keep Cleanup from freeing it */
2317 savepointLevel = s->savepointLevel;
2319 CleanupSubTransaction();
2321 DefineSavepoint(NULL);
2322 s = CurrentTransactionState; /* changed by push */
2324 s->savepointLevel = savepointLevel;
2326 /* This is the same as TBLOCK_SUBBEGIN case */
2327 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2328 StartSubTransaction();
2329 s->blockState = TBLOCK_SUBINPROGRESS;
2336 * AbortCurrentTransaction
2339 AbortCurrentTransaction(void)
2341 TransactionState s = CurrentTransactionState;
2343 switch (s->blockState)
2345 case TBLOCK_DEFAULT:
2346 if (s->state == TRANS_DEFAULT)
2348 /* we are idle, so nothing to do */
2353 * We can get here after an error during transaction start
2354 * (state will be TRANS_START). Need to clean up the
2355 * incompletely started transaction. First, adjust the
2356 * low-level state to suppress warning message from
2359 if (s->state == TRANS_START)
2360 s->state = TRANS_INPROGRESS;
2362 CleanupTransaction();
2367 * if we aren't in a transaction block, we just do the basic abort
2368 * & cleanup transaction.
2370 case TBLOCK_STARTED:
2372 CleanupTransaction();
2373 s->blockState = TBLOCK_DEFAULT;
2377 * If we are in TBLOCK_BEGIN it means something screwed up right
2378 * after reading "BEGIN TRANSACTION". We assume that the user
2379 * will interpret the error as meaning the BEGIN failed to get him
2380 * into a transaction block, so we should abort and return to idle
2385 CleanupTransaction();
2386 s->blockState = TBLOCK_DEFAULT;
2390 * We are somewhere in a transaction block and we've gotten a
2391 * failure, so we abort the transaction and set up the persistent
2392 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2394 case TBLOCK_INPROGRESS:
2396 s->blockState = TBLOCK_ABORT;
2397 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2401 * Here, we failed while trying to COMMIT. Clean up the
2402 * transaction and return to idle state (we do not want to stay in
2407 CleanupTransaction();
2408 s->blockState = TBLOCK_DEFAULT;
2412 * Here, we are already in an aborted transaction state and are
2413 * waiting for a ROLLBACK, but for some reason we failed again! So
2414 * we just remain in the abort state.
2417 case TBLOCK_SUBABORT:
2421 * We are in a failed transaction and we got the ROLLBACK command.
2422 * We have already aborted, we just need to cleanup and go to idle
2425 case TBLOCK_ABORT_END:
2426 CleanupTransaction();
2427 s->blockState = TBLOCK_DEFAULT;
2431 * We are in a live transaction and we got a ROLLBACK command.
2432 * Abort, cleanup, go to idle state.
2434 case TBLOCK_ABORT_PENDING:
2436 CleanupTransaction();
2437 s->blockState = TBLOCK_DEFAULT;
2441 * Here, we failed while trying to PREPARE. Clean up the
2442 * transaction and return to idle state (we do not want to stay in
2445 case TBLOCK_PREPARE:
2447 CleanupTransaction();
2448 s->blockState = TBLOCK_DEFAULT;
2452 * We got an error inside a subtransaction. Abort just the
2453 * subtransaction, and go to the persistent SUBABORT state until
2456 case TBLOCK_SUBINPROGRESS:
2457 AbortSubTransaction();
2458 s->blockState = TBLOCK_SUBABORT;
2462 * If we failed while trying to create a subtransaction, clean up
2463 * the broken subtransaction and abort the parent. The same
2464 * applies if we get a failure while ending a subtransaction.
2466 case TBLOCK_SUBBEGIN:
2468 case TBLOCK_SUBABORT_PENDING:
2469 case TBLOCK_SUBRESTART:
2470 AbortSubTransaction();
2471 CleanupSubTransaction();
2472 AbortCurrentTransaction();
2476 * Same as above, except the Abort() was already done.
2478 case TBLOCK_SUBABORT_END:
2479 case TBLOCK_SUBABORT_RESTART:
2480 CleanupSubTransaction();
2481 AbortCurrentTransaction();
2487 * PreventTransactionChain
2489 * This routine is to be called by statements that must not run inside
2490 * a transaction block, typically because they have non-rollback-able
2491 * side effects or do internal commits.
2493 * If we have already started a transaction block, issue an error; also issue
2494 * an error if we appear to be running inside a user-defined function (which
2495 * could issue more commands and possibly cause a failure after the statement
2496 * completes). Subtransactions are verboten too.
2498 * stmtNode: pointer to parameter block for statement; this is used in
2499 * a very klugy way to determine whether we are inside a function.
2500 * stmtType: statement type name for error messages.
2503 PreventTransactionChain(void *stmtNode, const char *stmtType)
2506 * xact block already started?
2508 if (IsTransactionBlock())
2510 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2511 /* translator: %s represents an SQL statement name */
2512 errmsg("%s cannot run inside a transaction block",
2518 if (IsSubTransaction())
2520 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2521 /* translator: %s represents an SQL statement name */
2522 errmsg("%s cannot run inside a subtransaction",
2526 * Are we inside a function call? If the statement's parameter block was
2527 * allocated in QueryContext, assume it is an interactive command.
2528 * Otherwise assume it is coming from a function.
2530 if (!MemoryContextContains(QueryContext, stmtNode))
2532 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2533 /* translator: %s represents an SQL statement name */
2534 errmsg("%s cannot be executed from a function", stmtType)));
2536 /* If we got past IsTransactionBlock test, should be in default state */
2537 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2538 CurrentTransactionState->blockState != TBLOCK_STARTED)
2539 elog(FATAL, "cannot prevent transaction chain");
2544 * RequireTransactionChain
2546 * This routine is to be called by statements that must run inside
2547 * a transaction block, because they have no effects that persist past
2548 * transaction end (and so calling them outside a transaction block
2549 * is presumably an error). DECLARE CURSOR is an example.
2551 * If we appear to be running inside a user-defined function, we do not
2552 * issue an error, since the function could issue more commands that make
2553 * use of the current statement's results. Likewise subtransactions.
2554 * Thus this is an inverse for PreventTransactionChain.
2556 * stmtNode: pointer to parameter block for statement; this is used in
2557 * a very klugy way to determine whether we are inside a function.
2558 * stmtType: statement type name for error messages.
2561 RequireTransactionChain(void *stmtNode, const char *stmtType)
2564 * xact block already started?
2566 if (IsTransactionBlock())
2572 if (IsSubTransaction())
2576 * Are we inside a function call? If the statement's parameter block was
2577 * allocated in QueryContext, assume it is an interactive command.
2578 * Otherwise assume it is coming from a function.
2580 if (!MemoryContextContains(QueryContext, stmtNode))
2583 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2584 /* translator: %s represents an SQL statement name */
2585 errmsg("%s can only be used in transaction blocks",
2590 * IsInTransactionChain
2592 * This routine is for statements that need to behave differently inside
2593 * a transaction block than when running as single commands. ANALYZE is
2594 * currently the only example.
2596 * stmtNode: pointer to parameter block for statement; this is used in
2597 * a very klugy way to determine whether we are inside a function.
2600 IsInTransactionChain(void *stmtNode)
2603 * Return true on same conditions that would make PreventTransactionChain
2606 if (IsTransactionBlock())
2609 if (IsSubTransaction())
2612 if (!MemoryContextContains(QueryContext, stmtNode))
2615 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2616 CurrentTransactionState->blockState != TBLOCK_STARTED)
2624 * Register or deregister callback functions for start- and end-of-xact
2627 * These functions are intended for use by dynamically loaded modules.
2628 * For built-in modules we generally just hardwire the appropriate calls
2629 * (mainly because it's easier to control the order that way, where needed).
2631 * At transaction end, the callback occurs post-commit or post-abort, so the
2632 * callback functions can only do noncritical cleanup.
2635 RegisterXactCallback(XactCallback callback, void *arg)
2637 XactCallbackItem *item;
2639 item = (XactCallbackItem *)
2640 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2641 item->callback = callback;
2643 item->next = Xact_callbacks;
2644 Xact_callbacks = item;
2648 UnregisterXactCallback(XactCallback callback, void *arg)
2650 XactCallbackItem *item;
2651 XactCallbackItem *prev;
2654 for (item = Xact_callbacks; item; prev = item, item = item->next)
2656 if (item->callback == callback && item->arg == arg)
2659 prev->next = item->next;
2661 Xact_callbacks = item->next;
2669 CallXactCallbacks(XactEvent event)
2671 XactCallbackItem *item;
2673 for (item = Xact_callbacks; item; item = item->next)
2674 (*item->callback) (event, item->arg);
2679 * Register or deregister callback functions for start- and end-of-subxact
2682 * Pretty much same as above, but for subtransaction events.
2684 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2685 * so the callback functions can only do noncritical cleanup. At
2686 * subtransaction start, the callback is called when the subtransaction has
2687 * finished initializing.
2690 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2692 SubXactCallbackItem *item;
2694 item = (SubXactCallbackItem *)
2695 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2696 item->callback = callback;
2698 item->next = SubXact_callbacks;
2699 SubXact_callbacks = item;
2703 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2705 SubXactCallbackItem *item;
2706 SubXactCallbackItem *prev;
2709 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2711 if (item->callback == callback && item->arg == arg)
2714 prev->next = item->next;
2716 SubXact_callbacks = item->next;
2724 CallSubXactCallbacks(SubXactEvent event,
2725 SubTransactionId mySubid,
2726 SubTransactionId parentSubid)
2728 SubXactCallbackItem *item;
2730 for (item = SubXact_callbacks; item; item = item->next)
2731 (*item->callback) (event, mySubid, parentSubid, item->arg);
2735 /* ----------------------------------------------------------------
2736 * transaction block support
2737 * ----------------------------------------------------------------
2741 * BeginTransactionBlock
2742 * This executes a BEGIN command.
2745 BeginTransactionBlock(void)
2747 TransactionState s = CurrentTransactionState;
2749 switch (s->blockState)
2752 * We are not inside a transaction block, so allow one to begin.
2754 case TBLOCK_STARTED:
2755 s->blockState = TBLOCK_BEGIN;
2759 * Already a transaction block in progress.
2761 case TBLOCK_INPROGRESS:
2762 case TBLOCK_SUBINPROGRESS:
2764 case TBLOCK_SUBABORT:
2766 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2767 errmsg("there is already a transaction in progress")));
2770 /* These cases are invalid. */
2771 case TBLOCK_DEFAULT:
2773 case TBLOCK_SUBBEGIN:
2776 case TBLOCK_ABORT_END:
2777 case TBLOCK_SUBABORT_END:
2778 case TBLOCK_ABORT_PENDING:
2779 case TBLOCK_SUBABORT_PENDING:
2780 case TBLOCK_SUBRESTART:
2781 case TBLOCK_SUBABORT_RESTART:
2782 case TBLOCK_PREPARE:
2783 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2784 BlockStateAsString(s->blockState));
2790 * PrepareTransactionBlock
2791 * This executes a PREPARE command.
2793 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2794 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2796 * Note that we don't actually do anything here except change blockState.
2797 * The real work will be done in the upcoming PrepareTransaction().
2798 * We do it this way because it's not convenient to change memory context,
2799 * resource owner, etc while executing inside a Portal.
2802 PrepareTransactionBlock(char *gid)
2807 /* Set up to commit the current transaction */
2808 result = EndTransactionBlock();
2810 /* If successful, change outer tblock state to PREPARE */
2813 s = CurrentTransactionState;
2815 while (s->parent != NULL)
2818 if (s->blockState == TBLOCK_END)
2820 /* Save GID where PrepareTransaction can find it again */
2821 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2823 s->blockState = TBLOCK_PREPARE;
2828 * ignore case where we are not in a transaction;
2829 * EndTransactionBlock already issued a warning.
2831 Assert(s->blockState == TBLOCK_STARTED);
2832 /* Don't send back a PREPARE result tag... */
2841 * EndTransactionBlock
2842 * This executes a COMMIT command.
2844 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2845 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2847 * Note that we don't actually do anything here except change blockState.
2848 * The real work will be done in the upcoming CommitTransactionCommand().
2849 * We do it this way because it's not convenient to change memory context,
2850 * resource owner, etc while executing inside a Portal.
2853 EndTransactionBlock(void)
2855 TransactionState s = CurrentTransactionState;
2856 bool result = false;
2858 switch (s->blockState)
2861 * We are in a transaction block, so tell CommitTransactionCommand
2864 case TBLOCK_INPROGRESS:
2865 s->blockState = TBLOCK_END;
2870 * We are in a failed transaction block. Tell
2871 * CommitTransactionCommand it's time to exit the block.
2874 s->blockState = TBLOCK_ABORT_END;
2878 * We are in a live subtransaction block. Set up to subcommit all
2879 * open subtransactions and then commit the main transaction.
2881 case TBLOCK_SUBINPROGRESS:
2882 while (s->parent != NULL)
2884 if (s->blockState == TBLOCK_SUBINPROGRESS)
2885 s->blockState = TBLOCK_SUBEND;
2887 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2888 BlockStateAsString(s->blockState));
2891 if (s->blockState == TBLOCK_INPROGRESS)
2892 s->blockState = TBLOCK_END;
2894 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2895 BlockStateAsString(s->blockState));
2900 * Here we are inside an aborted subtransaction. Treat the COMMIT
2901 * as ROLLBACK: set up to abort everything and exit the main
2904 case TBLOCK_SUBABORT:
2905 while (s->parent != NULL)
2907 if (s->blockState == TBLOCK_SUBINPROGRESS)
2908 s->blockState = TBLOCK_SUBABORT_PENDING;
2909 else if (s->blockState == TBLOCK_SUBABORT)
2910 s->blockState = TBLOCK_SUBABORT_END;
2912 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2913 BlockStateAsString(s->blockState));
2916 if (s->blockState == TBLOCK_INPROGRESS)
2917 s->blockState = TBLOCK_ABORT_PENDING;
2918 else if (s->blockState == TBLOCK_ABORT)
2919 s->blockState = TBLOCK_ABORT_END;
2921 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2922 BlockStateAsString(s->blockState));
2926 * The user issued COMMIT when not inside a transaction. Issue a
2927 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2928 * CommitTransactionCommand() will then close the transaction and
2929 * put us back into the default state.
2931 case TBLOCK_STARTED:
2933 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2934 errmsg("there is no transaction in progress")));
2938 /* These cases are invalid. */
2939 case TBLOCK_DEFAULT:
2941 case TBLOCK_SUBBEGIN:
2944 case TBLOCK_ABORT_END:
2945 case TBLOCK_SUBABORT_END:
2946 case TBLOCK_ABORT_PENDING:
2947 case TBLOCK_SUBABORT_PENDING:
2948 case TBLOCK_SUBRESTART:
2949 case TBLOCK_SUBABORT_RESTART:
2950 case TBLOCK_PREPARE:
2951 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2952 BlockStateAsString(s->blockState));
2960 * UserAbortTransactionBlock
2961 * This executes a ROLLBACK command.
2963 * As above, we don't actually do anything here except change blockState.
2966 UserAbortTransactionBlock(void)
2968 TransactionState s = CurrentTransactionState;
2970 switch (s->blockState)
2973 * We are inside a transaction block and we got a ROLLBACK command
2974 * from the user, so tell CommitTransactionCommand to abort and
2975 * exit the transaction block.
2977 case TBLOCK_INPROGRESS:
2978 s->blockState = TBLOCK_ABORT_PENDING;
2982 * We are inside a failed transaction block and we got a ROLLBACK
2983 * command from the user. Abort processing is already done, so
2984 * CommitTransactionCommand just has to cleanup and go back to
2988 s->blockState = TBLOCK_ABORT_END;
2992 * We are inside a subtransaction. Mark everything up to top
2993 * level as exitable.
2995 case TBLOCK_SUBINPROGRESS:
2996 case TBLOCK_SUBABORT:
2997 while (s->parent != NULL)
2999 if (s->blockState == TBLOCK_SUBINPROGRESS)
3000 s->blockState = TBLOCK_SUBABORT_PENDING;
3001 else if (s->blockState == TBLOCK_SUBABORT)
3002 s->blockState = TBLOCK_SUBABORT_END;
3004 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3005 BlockStateAsString(s->blockState));
3008 if (s->blockState == TBLOCK_INPROGRESS)
3009 s->blockState = TBLOCK_ABORT_PENDING;
3010 else if (s->blockState == TBLOCK_ABORT)
3011 s->blockState = TBLOCK_ABORT_END;
3013 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3014 BlockStateAsString(s->blockState));
3018 * The user issued ABORT when not inside a transaction. Issue a
3019 * WARNING and go to abort state. The upcoming call to
3020 * CommitTransactionCommand() will then put us back into the
3023 case TBLOCK_STARTED:
3025 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3026 errmsg("there is no transaction in progress")));
3027 s->blockState = TBLOCK_ABORT_PENDING;
3030 /* These cases are invalid. */
3031 case TBLOCK_DEFAULT:
3033 case TBLOCK_SUBBEGIN:
3036 case TBLOCK_ABORT_END:
3037 case TBLOCK_SUBABORT_END:
3038 case TBLOCK_ABORT_PENDING:
3039 case TBLOCK_SUBABORT_PENDING:
3040 case TBLOCK_SUBRESTART:
3041 case TBLOCK_SUBABORT_RESTART:
3042 case TBLOCK_PREPARE:
3043 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3044 BlockStateAsString(s->blockState));
3051 * This executes a SAVEPOINT command.
3054 DefineSavepoint(char *name)
3056 TransactionState s = CurrentTransactionState;
3058 switch (s->blockState)
3060 case TBLOCK_INPROGRESS:
3061 case TBLOCK_SUBINPROGRESS:
3062 /* Normal subtransaction start */
3064 s = CurrentTransactionState; /* changed by push */
3067 * Savepoint names, like the TransactionState block itself, live
3068 * in TopTransactionContext.
3071 s->name = MemoryContextStrdup(TopTransactionContext, name);
3074 /* These cases are invalid. */
3075 case TBLOCK_DEFAULT:
3076 case TBLOCK_STARTED:
3078 case TBLOCK_SUBBEGIN:
3082 case TBLOCK_SUBABORT:
3083 case TBLOCK_ABORT_END:
3084 case TBLOCK_SUBABORT_END:
3085 case TBLOCK_ABORT_PENDING:
3086 case TBLOCK_SUBABORT_PENDING:
3087 case TBLOCK_SUBRESTART:
3088 case TBLOCK_SUBABORT_RESTART:
3089 case TBLOCK_PREPARE:
3090 elog(FATAL, "DefineSavepoint: unexpected state %s",
3091 BlockStateAsString(s->blockState));
3098 * This executes a RELEASE command.
3100 * As above, we don't actually do anything here except change blockState.
3103 ReleaseSavepoint(List *options)
3105 TransactionState s = CurrentTransactionState;
3106 TransactionState target,
3111 switch (s->blockState)
3114 * We can't rollback to a savepoint if there is no savepoint
3117 case TBLOCK_INPROGRESS:
3119 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3120 errmsg("no such savepoint")));
3124 * We are in a non-aborted subtransaction. This is the only valid
3127 case TBLOCK_SUBINPROGRESS:
3130 /* These cases are invalid. */
3131 case TBLOCK_DEFAULT:
3132 case TBLOCK_STARTED:
3134 case TBLOCK_SUBBEGIN:
3138 case TBLOCK_SUBABORT:
3139 case TBLOCK_ABORT_END:
3140 case TBLOCK_SUBABORT_END:
3141 case TBLOCK_ABORT_PENDING:
3142 case TBLOCK_SUBABORT_PENDING:
3143 case TBLOCK_SUBRESTART:
3144 case TBLOCK_SUBABORT_RESTART:
3145 case TBLOCK_PREPARE:
3146 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3147 BlockStateAsString(s->blockState));
3151 foreach(cell, options)
3153 DefElem *elem = lfirst(cell);
3155 if (strcmp(elem->defname, "savepoint_name") == 0)
3156 name = strVal(elem->arg);
3159 Assert(PointerIsValid(name));
3161 for (target = s; PointerIsValid(target); target = target->parent)
3163 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3167 if (!PointerIsValid(target))
3169 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3170 errmsg("no such savepoint")));
3172 /* disallow crossing savepoint level boundaries */
3173 if (target->savepointLevel != s->savepointLevel)
3175 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3176 errmsg("no such savepoint")));
3179 * Mark "commit pending" all subtransactions up to the target
3180 * subtransaction. The actual commits will happen when control gets to
3181 * CommitTransactionCommand.
3183 xact = CurrentTransactionState;
3186 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3187 xact->blockState = TBLOCK_SUBEND;
3190 xact = xact->parent;
3191 Assert(PointerIsValid(xact));
3196 * RollbackToSavepoint
3197 * This executes a ROLLBACK TO <savepoint> command.
3199 * As above, we don't actually do anything here except change blockState.
3202 RollbackToSavepoint(List *options)
3204 TransactionState s = CurrentTransactionState;
3205 TransactionState target,
3210 switch (s->blockState)
3213 * We can't rollback to a savepoint if there is no savepoint
3216 case TBLOCK_INPROGRESS:
3219 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3220 errmsg("no such savepoint")));
3224 * There is at least one savepoint, so proceed.
3226 case TBLOCK_SUBINPROGRESS:
3227 case TBLOCK_SUBABORT:
3230 /* These cases are invalid. */
3231 case TBLOCK_DEFAULT:
3232 case TBLOCK_STARTED:
3234 case TBLOCK_SUBBEGIN:
3237 case TBLOCK_ABORT_END:
3238 case TBLOCK_SUBABORT_END:
3239 case TBLOCK_ABORT_PENDING:
3240 case TBLOCK_SUBABORT_PENDING:
3241 case TBLOCK_SUBRESTART:
3242 case TBLOCK_SUBABORT_RESTART:
3243 case TBLOCK_PREPARE:
3244 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3245 BlockStateAsString(s->blockState));
3249 foreach(cell, options)
3251 DefElem *elem = lfirst(cell);
3253 if (strcmp(elem->defname, "savepoint_name") == 0)
3254 name = strVal(elem->arg);
3257 Assert(PointerIsValid(name));
3259 for (target = s; PointerIsValid(target); target = target->parent)
3261 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3265 if (!PointerIsValid(target))
3267 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3268 errmsg("no such savepoint")));
3270 /* disallow crossing savepoint level boundaries */
3271 if (target->savepointLevel != s->savepointLevel)
3273 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3274 errmsg("no such savepoint")));
3277 * Mark "abort pending" all subtransactions up to the target
3278 * subtransaction. The actual aborts will happen when control gets to
3279 * CommitTransactionCommand.
3281 xact = CurrentTransactionState;
3286 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3287 xact->blockState = TBLOCK_SUBABORT_PENDING;
3288 else if (xact->blockState == TBLOCK_SUBABORT)
3289 xact->blockState = TBLOCK_SUBABORT_END;
3291 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3292 BlockStateAsString(xact->blockState));
3293 xact = xact->parent;
3294 Assert(PointerIsValid(xact));
3297 /* And mark the target as "restart pending" */
3298 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3299 xact->blockState = TBLOCK_SUBRESTART;
3300 else if (xact->blockState == TBLOCK_SUBABORT)
3301 xact->blockState = TBLOCK_SUBABORT_RESTART;
3303 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3304 BlockStateAsString(xact->blockState));
3308 * BeginInternalSubTransaction
3309 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3310 * state, and therefore it can safely be used in a function that might
3311 * be called when not inside a BEGIN block. Also, we automatically
3312 * cycle through CommitTransactionCommand/StartTransactionCommand
3313 * instead of expecting the caller to do it.
3316 BeginInternalSubTransaction(char *name)
3318 TransactionState s = CurrentTransactionState;
3320 switch (s->blockState)
3322 case TBLOCK_STARTED:
3323 case TBLOCK_INPROGRESS:
3324 case TBLOCK_SUBINPROGRESS:
3325 /* Normal subtransaction start */
3327 s = CurrentTransactionState; /* changed by push */
3330 * Savepoint names, like the TransactionState block itself, live
3331 * in TopTransactionContext.
3334 s->name = MemoryContextStrdup(TopTransactionContext, name);
3337 /* These cases are invalid. */
3338 case TBLOCK_DEFAULT:
3340 case TBLOCK_SUBBEGIN:
3344 case TBLOCK_SUBABORT:
3345 case TBLOCK_ABORT_END:
3346 case TBLOCK_SUBABORT_END:
3347 case TBLOCK_ABORT_PENDING:
3348 case TBLOCK_SUBABORT_PENDING:
3349 case TBLOCK_SUBRESTART:
3350 case TBLOCK_SUBABORT_RESTART:
3351 case TBLOCK_PREPARE:
3352 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3353 BlockStateAsString(s->blockState));
3357 CommitTransactionCommand();
3358 StartTransactionCommand();
3362 * ReleaseCurrentSubTransaction
3364 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3365 * savepoint name (if any).
3366 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3369 ReleaseCurrentSubTransaction(void)
3371 TransactionState s = CurrentTransactionState;
3373 if (s->blockState != TBLOCK_SUBINPROGRESS)
3374 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3375 BlockStateAsString(s->blockState));
3376 Assert(s->state == TRANS_INPROGRESS);
3377 MemoryContextSwitchTo(CurTransactionContext);
3378 CommitSubTransaction();
3379 s = CurrentTransactionState; /* changed by pop */
3380 Assert(s->state == TRANS_INPROGRESS);
3384 * RollbackAndReleaseCurrentSubTransaction
3386 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3387 * of its savepoint name (if any).
3388 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3391 RollbackAndReleaseCurrentSubTransaction(void)
3393 TransactionState s = CurrentTransactionState;
3395 switch (s->blockState)
3397 /* Must be in a subtransaction */
3398 case TBLOCK_SUBINPROGRESS:
3399 case TBLOCK_SUBABORT:
3402 /* These cases are invalid. */
3403 case TBLOCK_DEFAULT:
3404 case TBLOCK_STARTED:
3406 case TBLOCK_SUBBEGIN:
3407 case TBLOCK_INPROGRESS:
3411 case TBLOCK_ABORT_END:
3412 case TBLOCK_SUBABORT_END:
3413 case TBLOCK_ABORT_PENDING:
3414 case TBLOCK_SUBABORT_PENDING:
3415 case TBLOCK_SUBRESTART:
3416 case TBLOCK_SUBABORT_RESTART:
3417 case TBLOCK_PREPARE:
3418 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3419 BlockStateAsString(s->blockState));
3424 * Abort the current subtransaction, if needed.
3426 if (s->blockState == TBLOCK_SUBINPROGRESS)
3427 AbortSubTransaction();
3429 /* And clean it up, too */
3430 CleanupSubTransaction();
3432 s = CurrentTransactionState; /* changed by pop */
3433 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3434 s->blockState == TBLOCK_INPROGRESS ||
3435 s->blockState == TBLOCK_STARTED);
3439 * AbortOutOfAnyTransaction
3441 * This routine is provided for error recovery purposes. It aborts any
3442 * active transaction or transaction block, leaving the system in a known
3446 AbortOutOfAnyTransaction(void)
3448 TransactionState s = CurrentTransactionState;
3451 * Get out of any transaction or nested transaction
3455 switch (s->blockState)
3457 case TBLOCK_DEFAULT:
3458 /* Not in a transaction, do nothing */
3460 case TBLOCK_STARTED:
3462 case TBLOCK_INPROGRESS:
3464 case TBLOCK_ABORT_PENDING:
3465 case TBLOCK_PREPARE:
3466 /* In a transaction, so clean up */
3468 CleanupTransaction();
3469 s->blockState = TBLOCK_DEFAULT;
3472 case TBLOCK_ABORT_END:
3473 /* AbortTransaction already done, still need Cleanup */
3474 CleanupTransaction();
3475 s->blockState = TBLOCK_DEFAULT;
3479 * In a subtransaction, so clean it up and abort parent too
3481 case TBLOCK_SUBBEGIN:
3482 case TBLOCK_SUBINPROGRESS:
3484 case TBLOCK_SUBABORT_PENDING:
3485 case TBLOCK_SUBRESTART:
3486 AbortSubTransaction();
3487 CleanupSubTransaction();
3488 s = CurrentTransactionState; /* changed by pop */
3491 case TBLOCK_SUBABORT:
3492 case TBLOCK_SUBABORT_END:
3493 case TBLOCK_SUBABORT_RESTART:
3494 /* As above, but AbortSubTransaction already done */
3495 CleanupSubTransaction();
3496 s = CurrentTransactionState; /* changed by pop */
3499 } while (s->blockState != TBLOCK_DEFAULT);
3501 /* Should be out of all subxacts now */
3502 Assert(s->parent == NULL);
3506 * IsTransactionBlock --- are we within a transaction block?
3509 IsTransactionBlock(void)
3511 TransactionState s = CurrentTransactionState;
3513 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3520 * IsTransactionOrTransactionBlock --- are we within either a transaction
3521 * or a transaction block? (The backend is only really "idle" when this
3524 * This should match up with IsTransactionBlock and IsTransactionState.
3527 IsTransactionOrTransactionBlock(void)
3529 TransactionState s = CurrentTransactionState;
3531 if (s->blockState == TBLOCK_DEFAULT)
3538 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3541 TransactionBlockStatusCode(void)
3543 TransactionState s = CurrentTransactionState;
3545 switch (s->blockState)
3547 case TBLOCK_DEFAULT:
3548 case TBLOCK_STARTED:
3549 return 'I'; /* idle --- not in transaction */
3551 case TBLOCK_SUBBEGIN:
3552 case TBLOCK_INPROGRESS:
3553 case TBLOCK_SUBINPROGRESS:
3556 case TBLOCK_PREPARE:
3557 return 'T'; /* in transaction */
3559 case TBLOCK_SUBABORT:
3560 case TBLOCK_ABORT_END:
3561 case TBLOCK_SUBABORT_END:
3562 case TBLOCK_ABORT_PENDING:
3563 case TBLOCK_SUBABORT_PENDING:
3564 case TBLOCK_SUBRESTART:
3565 case TBLOCK_SUBABORT_RESTART:
3566 return 'E'; /* in failed transaction */
3569 /* should never get here */
3570 elog(FATAL, "invalid transaction block state: %s",
3571 BlockStateAsString(s->blockState));
3572 return 0; /* keep compiler quiet */
3579 IsSubTransaction(void)
3581 TransactionState s = CurrentTransactionState;
3583 if (s->nestingLevel >= 2)
3590 * StartSubTransaction
3592 * If you're wondering why this is separate from PushTransaction: it's because
3593 * we can't conveniently do this stuff right inside DefineSavepoint. The
3594 * SAVEPOINT utility command will be executed inside a Portal, and if we
3595 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3596 * the Portal will undo those settings. So we make DefineSavepoint just
3597 * push a dummy transaction block, and when control returns to the main
3598 * idle loop, CommitTransactionCommand will be called, and we'll come here
3599 * to finish starting the subtransaction.
3602 StartSubTransaction(void)
3604 TransactionState s = CurrentTransactionState;
3606 if (s->state != TRANS_DEFAULT)
3607 elog(WARNING, "StartSubTransaction while in %s state",
3608 TransStateAsString(s->state));
3610 s->state = TRANS_START;
3613 * Initialize subsystems for new subtransaction
3615 * must initialize resource-management stuff first
3617 AtSubStart_Memory();
3618 AtSubStart_ResourceOwner();
3620 AtSubStart_Notify();
3621 AfterTriggerBeginSubXact();
3623 s->state = TRANS_INPROGRESS;
3626 * Call start-of-subxact callbacks
3628 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3629 s->parent->subTransactionId);
3631 ShowTransactionState("StartSubTransaction");
3635 * CommitSubTransaction
3637 * The caller has to make sure to always reassign CurrentTransactionState
3638 * if it has a local pointer to it after calling this function.
3641 CommitSubTransaction(void)
3643 TransactionState s = CurrentTransactionState;
3645 ShowTransactionState("CommitSubTransaction");
3647 if (s->state != TRANS_INPROGRESS)
3648 elog(WARNING, "CommitSubTransaction while in %s state",
3649 TransStateAsString(s->state));
3651 /* Pre-commit processing goes here -- nothing to do at the moment */
3653 s->state = TRANS_COMMIT;
3655 /* Must CCI to ensure commands of subtransaction are seen as done */
3656 CommandCounterIncrement();
3658 /* Mark subtransaction as subcommitted */
3659 if (TransactionIdIsValid(s->transactionId))
3661 RecordSubTransactionCommit();
3662 AtSubCommit_childXids();
3665 /* Post-commit cleanup */
3666 AfterTriggerEndSubXact(true);
3667 AtSubCommit_Portals(s->subTransactionId,
3668 s->parent->subTransactionId,
3669 s->parent->curTransactionOwner);
3670 AtEOSubXact_LargeObject(true, s->subTransactionId,
3671 s->parent->subTransactionId);
3672 AtSubCommit_Notify();
3673 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3674 s->parent->subTransactionId);
3676 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3677 s->parent->subTransactionId);
3679 ResourceOwnerRelease(s->curTransactionOwner,
3680 RESOURCE_RELEASE_BEFORE_LOCKS,
3682 AtEOSubXact_RelationCache(true, s->subTransactionId,
3683 s->parent->subTransactionId);
3684 AtEOSubXact_Inval(true);
3688 * The only lock we actually release here is the subtransaction XID lock.
3689 * The rest just get transferred to the parent resource owner.
3691 CurrentResourceOwner = s->curTransactionOwner;
3692 if (TransactionIdIsValid(s->transactionId))
3693 XactLockTableDelete(s->transactionId);
3695 ResourceOwnerRelease(s->curTransactionOwner,
3696 RESOURCE_RELEASE_LOCKS,
3698 ResourceOwnerRelease(s->curTransactionOwner,
3699 RESOURCE_RELEASE_AFTER_LOCKS,
3702 AtEOXact_GUC(true, true);
3703 AtEOSubXact_SPI(true, s->subTransactionId);
3704 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3705 s->parent->subTransactionId);
3706 AtEOSubXact_Namespace(true, s->subTransactionId,
3707 s->parent->subTransactionId);
3708 AtEOSubXact_Files(true, s->subTransactionId,
3709 s->parent->subTransactionId);
3712 * We need to restore the upper transaction's read-only state, in case the
3713 * upper is read-write while the child is read-only; GUC will incorrectly
3714 * think it should leave the child state in place.
3716 XactReadOnly = s->prevXactReadOnly;
3718 CurrentResourceOwner = s->parent->curTransactionOwner;
3719 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3720 ResourceOwnerDelete(s->curTransactionOwner);
3721 s->curTransactionOwner = NULL;
3723 AtSubCommit_Memory();
3725 s->state = TRANS_DEFAULT;
3731 * AbortSubTransaction
3734 AbortSubTransaction(void)
3736 TransactionState s = CurrentTransactionState;
3738 /* Prevent cancel/die interrupt while cleaning up */
3741 /* Make sure we have a valid memory context and resource owner */
3742 AtSubAbort_Memory();
3743 AtSubAbort_ResourceOwner();
3746 * Release any LW locks we might be holding as quickly as possible.
3747 * (Regular locks, however, must be held till we finish aborting.)
3748 * Releasing LW locks is critical since we might try to grab them again
3749 * while cleaning up!
3751 * FIXME This may be incorrect --- Are there some locks we should keep?
3752 * Buffer locks, for example? I don't think so but I'm not sure.
3762 * check the current transaction state
3764 ShowTransactionState("AbortSubTransaction");
3766 if (s->state != TRANS_INPROGRESS)
3767 elog(WARNING, "AbortSubTransaction while in %s state",
3768 TransStateAsString(s->state));
3770 s->state = TRANS_ABORT;
3773 * We can skip all this stuff if the subxact failed before creating a
3776 if (s->curTransactionOwner)
3778 AfterTriggerEndSubXact(false);
3779 AtSubAbort_Portals(s->subTransactionId,
3780 s->parent->subTransactionId,
3781 s->parent->curTransactionOwner);
3782 AtEOSubXact_LargeObject(false, s->subTransactionId,
3783 s->parent->subTransactionId);
3784 AtSubAbort_Notify();
3785 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3786 s->parent->subTransactionId);
3788 /* Advertise the fact that we aborted in pg_clog. */
3789 if (TransactionIdIsValid(s->transactionId))
3791 RecordSubTransactionAbort();
3792 AtSubAbort_childXids();
3795 /* Post-abort cleanup */
3796 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3797 s->parent->subTransactionId);
3799 ResourceOwnerRelease(s->curTransactionOwner,
3800 RESOURCE_RELEASE_BEFORE_LOCKS,
3802 AtEOSubXact_RelationCache(false, s->subTransactionId,
3803 s->parent->subTransactionId);
3804 AtEOSubXact_Inval(false);
3806 ResourceOwnerRelease(s->curTransactionOwner,
3807 RESOURCE_RELEASE_LOCKS,
3809 ResourceOwnerRelease(s->curTransactionOwner,
3810 RESOURCE_RELEASE_AFTER_LOCKS,
3813 AtEOXact_GUC(false, true);
3814 AtEOSubXact_SPI(false, s->subTransactionId);
3815 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3816 s->parent->subTransactionId);
3817 AtEOSubXact_Namespace(false, s->subTransactionId,
3818 s->parent->subTransactionId);
3819 AtEOSubXact_Files(false, s->subTransactionId,
3820 s->parent->subTransactionId);
3824 * Reset user id which might have been changed transiently. Here we want
3825 * to restore to the userid that was current at subxact entry. (As in
3826 * AbortTransaction, we need not worry about the session userid.)
3828 * Must do this after AtEOXact_GUC to handle the case where we entered the
3829 * subxact inside a SECURITY DEFINER function (hence current and session
3830 * userids were different) and then session auth was changed inside the
3831 * subxact. GUC will reset both current and session userids to the
3832 * entry-time session userid. This is right in every other scenario so it
3833 * seems simplest to let GUC do that and fix it here.
3835 SetUserId(s->currentUser);
3838 * Restore the upper transaction's read-only state, too. This should be
3839 * redundant with GUC's cleanup but we may as well do it for consistency
3840 * with the commit case.
3842 XactReadOnly = s->prevXactReadOnly;
3844 RESUME_INTERRUPTS();
3848 * CleanupSubTransaction
3850 * The caller has to make sure to always reassign CurrentTransactionState
3851 * if it has a local pointer to it after calling this function.
3854 CleanupSubTransaction(void)
3856 TransactionState s = CurrentTransactionState;
3858 ShowTransactionState("CleanupSubTransaction");
3860 if (s->state != TRANS_ABORT)
3861 elog(WARNING, "CleanupSubTransaction while in %s state",
3862 TransStateAsString(s->state));
3864 AtSubCleanup_Portals(s->subTransactionId);
3866 CurrentResourceOwner = s->parent->curTransactionOwner;
3867 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3868 if (s->curTransactionOwner)
3869 ResourceOwnerDelete(s->curTransactionOwner);
3870 s->curTransactionOwner = NULL;
3872 AtSubCleanup_Memory();
3874 s->state = TRANS_DEFAULT;
3881 * Create transaction state stack entry for a subtransaction
3883 * The caller has to make sure to always reassign CurrentTransactionState
3884 * if it has a local pointer to it after calling this function.
3887 PushTransaction(void)
3889 TransactionState p = CurrentTransactionState;
3894 * At present, GetUserId cannot fail, but let's not assume that. Get the
3895 * ID before entering the critical code sequence.
3897 currentUser = GetUserId();
3900 * We keep subtransaction state nodes in TopTransactionContext.
3902 s = (TransactionState)
3903 MemoryContextAllocZero(TopTransactionContext,
3904 sizeof(TransactionStateData));
3907 * Assign a subtransaction ID, watching out for counter wraparound.
3909 currentSubTransactionId += 1;
3910 if (currentSubTransactionId == InvalidSubTransactionId)
3912 currentSubTransactionId -= 1;
3915 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3916 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3920 * We can now stack a minimally valid subtransaction without fear of
3923 s->transactionId = InvalidTransactionId; /* until assigned */
3924 s->subTransactionId = currentSubTransactionId;
3926 s->nestingLevel = p->nestingLevel + 1;
3927 s->savepointLevel = p->savepointLevel;
3928 s->state = TRANS_DEFAULT;
3929 s->blockState = TBLOCK_SUBBEGIN;
3930 s->currentUser = currentUser;
3931 s->prevXactReadOnly = XactReadOnly;
3933 CurrentTransactionState = s;
3936 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3937 * with the subtransaction from here on out; in particular they should not
3938 * assume that it necessarily has a transaction context, resource owner,
3945 * Pop back to parent transaction state
3947 * The caller has to make sure to always reassign CurrentTransactionState
3948 * if it has a local pointer to it after calling this function.
3951 PopTransaction(void)
3953 TransactionState s = CurrentTransactionState;
3955 if (s->state != TRANS_DEFAULT)
3956 elog(WARNING, "PopTransaction while in %s state",
3957 TransStateAsString(s->state));
3959 if (s->parent == NULL)
3960 elog(FATAL, "PopTransaction with no parent");
3962 CurrentTransactionState = s->parent;
3964 /* Let's just make sure CurTransactionContext is good */
3965 CurTransactionContext = s->parent->curTransactionContext;
3966 MemoryContextSwitchTo(CurTransactionContext);
3968 /* Ditto for ResourceOwner links */
3969 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3970 CurrentResourceOwner = s->parent->curTransactionOwner;
3972 /* Free the old child structure */
3979 * ShowTransactionState
3983 ShowTransactionState(const char *str)
3985 /* skip work if message will definitely not be printed */
3986 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3988 elog(DEBUG3, "%s", str);
3989 ShowTransactionStateRec(CurrentTransactionState);
3994 * ShowTransactionStateRec
3995 * Recursive subroutine for ShowTransactionState
3998 ShowTransactionStateRec(TransactionState s)
4001 ShowTransactionStateRec(s->parent);
4003 /* use ereport to suppress computation if msg will not be printed */
4005 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
4006 PointerIsValid(s->name) ? s->name : "unnamed",
4007 BlockStateAsString(s->blockState),
4008 TransStateAsString(s->state),
4009 (unsigned int) s->transactionId,
4010 (unsigned int) s->subTransactionId,
4011 (unsigned int) currentCommandId,
4013 nodeToString(s->childXids))));
4017 * BlockStateAsString
4021 BlockStateAsString(TBlockState blockState)
4025 case TBLOCK_DEFAULT:
4027 case TBLOCK_STARTED:
4031 case TBLOCK_INPROGRESS:
4032 return "INPROGRESS";
4037 case TBLOCK_ABORT_END:
4039 case TBLOCK_ABORT_PENDING:
4040 return "ABORT PEND";
4041 case TBLOCK_PREPARE:
4043 case TBLOCK_SUBBEGIN:
4045 case TBLOCK_SUBINPROGRESS:
4046 return "SUB INPROGRS";
4049 case TBLOCK_SUBABORT:
4051 case TBLOCK_SUBABORT_END:
4052 return "SUB ABORT END";
4053 case TBLOCK_SUBABORT_PENDING:
4054 return "SUB ABRT PEND";
4055 case TBLOCK_SUBRESTART:
4056 return "SUB RESTART";
4057 case TBLOCK_SUBABORT_RESTART:
4058 return "SUB AB RESTRT";
4060 return "UNRECOGNIZED";
4064 * TransStateAsString
4068 TransStateAsString(TransState state)
4076 case TRANS_INPROGRESS:
4085 return "UNRECOGNIZED";
4089 * xactGetCommittedChildren
4091 * Gets the list of committed children of the current transaction. The return
4092 * value is the number of child transactions. *children is set to point to a
4093 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4097 xactGetCommittedChildren(TransactionId **ptr)
4099 TransactionState s = CurrentTransactionState;
4101 TransactionId *children;
4104 nchildren = list_length(s->childXids);
4111 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4114 foreach(p, s->childXids)
4116 TransactionId child = lfirst_xid(p);
4118 *children++ = child;
4125 * XLOG support routines
4129 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4131 TransactionId *sub_xids;
4132 TransactionId max_xid;
4135 TransactionIdCommit(xid);
4137 /* Mark committed subtransactions as committed */
4138 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4139 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4141 /* Make sure nextXid is beyond any XID mentioned in the record */
4143 for (i = 0; i < xlrec->nsubxacts; i++)
4145 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4146 max_xid = sub_xids[i];
4148 if (TransactionIdFollowsOrEquals(max_xid,
4149 ShmemVariableCache->nextXid))
4151 ShmemVariableCache->nextXid = max_xid;
4152 TransactionIdAdvance(ShmemVariableCache->nextXid);
4155 /* Make sure files supposed to be dropped are dropped */
4156 for (i = 0; i < xlrec->nrels; i++)
4158 XLogDropRelation(xlrec->xnodes[i]);
4159 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4164 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4166 TransactionId *sub_xids;
4167 TransactionId max_xid;
4170 TransactionIdAbort(xid);
4172 /* Mark subtransactions as aborted */
4173 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4174 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4176 /* Make sure nextXid is beyond any XID mentioned in the record */
4178 for (i = 0; i < xlrec->nsubxacts; i++)
4180 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4181 max_xid = sub_xids[i];
4183 if (TransactionIdFollowsOrEquals(max_xid,
4184 ShmemVariableCache->nextXid))
4186 ShmemVariableCache->nextXid = max_xid;
4187 TransactionIdAdvance(ShmemVariableCache->nextXid);
4190 /* Make sure files supposed to be dropped are dropped */
4191 for (i = 0; i < xlrec->nrels; i++)
4193 XLogDropRelation(xlrec->xnodes[i]);
4194 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4199 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4201 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4203 if (info == XLOG_XACT_COMMIT)
4205 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4207 xact_redo_commit(xlrec, record->xl_xid);
4209 else if (info == XLOG_XACT_ABORT)
4211 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4213 xact_redo_abort(xlrec, record->xl_xid);
4215 else if (info == XLOG_XACT_PREPARE)
4217 /* the record contents are exactly the 2PC file */
4218 RecreateTwoPhaseFile(record->xl_xid,
4219 XLogRecGetData(record), record->xl_len);
4221 else if (info == XLOG_XACT_COMMIT_PREPARED)
4223 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4225 xact_redo_commit(&xlrec->crec, xlrec->xid);
4226 RemoveTwoPhaseFile(xlrec->xid, false);
4228 else if (info == XLOG_XACT_ABORT_PREPARED)
4230 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4232 xact_redo_abort(&xlrec->arec, xlrec->xid);
4233 RemoveTwoPhaseFile(xlrec->xid, false);
4236 elog(PANIC, "xact_redo: unknown op code %u", info);
4240 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4242 struct tm *tm = localtime(&xlrec->xtime);
4245 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4246 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4247 tm->tm_hour, tm->tm_min, tm->tm_sec);
4248 if (xlrec->nrels > 0)
4250 appendStringInfo(buf, "; rels:");
4251 for (i = 0; i < xlrec->nrels; i++)
4253 RelFileNode rnode = xlrec->xnodes[i];
4255 appendStringInfo(buf, " %u/%u/%u",
4256 rnode.spcNode, rnode.dbNode, rnode.relNode);
4259 if (xlrec->nsubxacts > 0)
4261 TransactionId *xacts = (TransactionId *)
4262 &xlrec->xnodes[xlrec->nrels];
4264 appendStringInfo(buf, "; subxacts:");
4265 for (i = 0; i < xlrec->nsubxacts; i++)
4266 appendStringInfo(buf, " %u", xacts[i]);
4271 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4273 struct tm *tm = localtime(&xlrec->xtime);
4276 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4277 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4278 tm->tm_hour, tm->tm_min, tm->tm_sec);
4279 if (xlrec->nrels > 0)
4281 appendStringInfo(buf, "; rels:");
4282 for (i = 0; i < xlrec->nrels; i++)
4284 RelFileNode rnode = xlrec->xnodes[i];
4286 appendStringInfo(buf, " %u/%u/%u",
4287 rnode.spcNode, rnode.dbNode, rnode.relNode);
4290 if (xlrec->nsubxacts > 0)
4292 TransactionId *xacts = (TransactionId *)
4293 &xlrec->xnodes[xlrec->nrels];
4295 appendStringInfo(buf, "; subxacts:");
4296 for (i = 0; i < xlrec->nsubxacts; i++)
4297 appendStringInfo(buf, " %u", xacts[i]);
4302 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4304 uint8 info = xl_info & ~XLR_INFO_MASK;
4306 if (info == XLOG_XACT_COMMIT)
4308 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4310 appendStringInfo(buf, "commit: ");
4311 xact_desc_commit(buf, xlrec);
4313 else if (info == XLOG_XACT_ABORT)
4315 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4317 appendStringInfo(buf, "abort: ");
4318 xact_desc_abort(buf, xlrec);
4320 else if (info == XLOG_XACT_PREPARE)
4322 appendStringInfo(buf, "prepare");
4324 else if (info == XLOG_XACT_COMMIT_PREPARED)
4326 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4328 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4329 xact_desc_commit(buf, &xlrec->crec);
4331 else if (info == XLOG_XACT_ABORT_PREPARED)
4333 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4335 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4336 xact_desc_abort(buf, &xlrec->arec);
4339 appendStringInfo(buf, "UNKNOWN");