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.246 2007/08/01 22:45:07 tgl Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
37 #include "storage/fd.h"
38 #include "storage/lmgr.h"
39 #include "storage/procarray.h"
40 #include "storage/smgr.h"
41 #include "utils/combocid.h"
42 #include "utils/flatfiles.h"
43 #include "utils/guc.h"
44 #include "utils/inval.h"
45 #include "utils/memutils.h"
46 #include "utils/relcache.h"
50 * User-tweakable parameters
52 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
55 bool DefaultXactReadOnly = false;
58 bool XactSyncCommit = true;
60 int CommitDelay = 0; /* precommit delay in microseconds */
61 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
65 * transaction states - transaction state from server perspective
67 typedef enum TransState
69 TRANS_DEFAULT, /* idle */
70 TRANS_START, /* transaction starting */
71 TRANS_INPROGRESS, /* inside a valid transaction */
72 TRANS_COMMIT, /* commit in progress */
73 TRANS_ABORT, /* abort in progress */
74 TRANS_PREPARE /* prepare in progress */
78 * transaction block states - transaction state of client queries
80 * Note: the subtransaction states are used only for non-topmost
81 * transactions; the others appear only in the topmost transaction.
83 typedef enum TBlockState
85 /* not-in-transaction-block states */
86 TBLOCK_DEFAULT, /* idle */
87 TBLOCK_STARTED, /* running single-query transaction */
89 /* transaction block states */
90 TBLOCK_BEGIN, /* starting transaction block */
91 TBLOCK_INPROGRESS, /* live transaction */
92 TBLOCK_END, /* COMMIT received */
93 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
94 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
95 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
96 TBLOCK_PREPARE, /* live xact, PREPARE received */
98 /* subtransaction states */
99 TBLOCK_SUBBEGIN, /* starting a subtransaction */
100 TBLOCK_SUBINPROGRESS, /* live subtransaction */
101 TBLOCK_SUBEND, /* RELEASE received */
102 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
103 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
104 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
105 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
106 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
110 * transaction state structure
112 typedef struct TransactionStateData
114 TransactionId transactionId; /* my XID, or Invalid if none */
115 SubTransactionId subTransactionId; /* my subxact ID */
116 char *name; /* savepoint name, if any */
117 int savepointLevel; /* savepoint level */
118 TransState state; /* low-level state */
119 TBlockState blockState; /* high-level state */
120 int nestingLevel; /* nest depth */
121 MemoryContext curTransactionContext; /* my xact-lifetime context */
122 ResourceOwner curTransactionOwner; /* my query resources */
123 List *childXids; /* subcommitted child XIDs */
124 Oid currentUser; /* subxact start current_user */
125 bool prevXactReadOnly; /* entry-time xact r/o state */
126 struct TransactionStateData *parent; /* back link to parent */
127 } TransactionStateData;
129 typedef TransactionStateData *TransactionState;
132 * CurrentTransactionState always points to the current transaction state
133 * block. It will point to TopTransactionStateData when not in a
134 * transaction at all, or when in a top-level transaction.
136 static TransactionStateData TopTransactionStateData = {
137 0, /* transaction id */
138 0, /* subtransaction id */
139 NULL, /* savepoint name */
140 0, /* savepoint level */
141 TRANS_DEFAULT, /* transaction state */
142 TBLOCK_DEFAULT, /* transaction block state from the client
144 0, /* nesting level */
145 NULL, /* cur transaction context */
146 NULL, /* cur transaction resource owner */
147 NIL, /* subcommitted child Xids */
148 0, /* entry-time current userid */
149 false, /* entry-time xact r/o state */
150 NULL /* link to parent state block */
153 static TransactionState CurrentTransactionState = &TopTransactionStateData;
156 * The subtransaction ID and command ID assignment counters are global
157 * to a whole transaction, so we do not keep them in the state stack.
159 static SubTransactionId currentSubTransactionId;
160 static CommandId currentCommandId;
163 * xactStartTimestamp is the value of transaction_timestamp().
164 * stmtStartTimestamp is the value of statement_timestamp().
165 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
166 * These do not change as we enter and exit subtransactions, so we don't
167 * keep them inside the TransactionState stack.
169 static TimestampTz xactStartTimestamp;
170 static TimestampTz stmtStartTimestamp;
171 static TimestampTz xactStopTimestamp;
174 * GID to be used for preparing the current transaction. This is also
175 * global to a whole transaction, so we don't keep it in the state stack.
177 static char *prepareGID;
180 * Some commands want to force synchronous commit.
182 static bool forceSyncCommit = false;
185 * Private context for transaction-abort work --- we reserve space for this
186 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
187 * when we've run out of memory.
189 static MemoryContext TransactionAbortContext = NULL;
192 * List of add-on start- and end-of-xact callbacks
194 typedef struct XactCallbackItem
196 struct XactCallbackItem *next;
197 XactCallback callback;
201 static XactCallbackItem *Xact_callbacks = NULL;
204 * List of add-on start- and end-of-subxact callbacks
206 typedef struct SubXactCallbackItem
208 struct SubXactCallbackItem *next;
209 SubXactCallback callback;
211 } SubXactCallbackItem;
213 static SubXactCallbackItem *SubXact_callbacks = NULL;
216 /* local function prototypes */
217 static void AssignSubTransactionId(TransactionState s);
218 static void AbortTransaction(void);
219 static void AtAbort_Memory(void);
220 static void AtCleanup_Memory(void);
221 static void AtAbort_ResourceOwner(void);
222 static void AtCommit_LocalCache(void);
223 static void AtCommit_Memory(void);
224 static void AtStart_Cache(void);
225 static void AtStart_Memory(void);
226 static void AtStart_ResourceOwner(void);
227 static void CallXactCallbacks(XactEvent event);
228 static void CallSubXactCallbacks(SubXactEvent event,
229 SubTransactionId mySubid,
230 SubTransactionId parentSubid);
231 static void CleanupTransaction(void);
232 static void CommitTransaction(void);
233 static void RecordTransactionAbort(void);
234 static void StartTransaction(void);
236 static void RecordSubTransactionCommit(void);
237 static void StartSubTransaction(void);
238 static void CommitSubTransaction(void);
239 static void AbortSubTransaction(void);
240 static void CleanupSubTransaction(void);
241 static void PushTransaction(void);
242 static void PopTransaction(void);
244 static void AtSubAbort_Memory(void);
245 static void AtSubCleanup_Memory(void);
246 static void AtSubAbort_ResourceOwner(void);
247 static void AtSubCommit_Memory(void);
248 static void AtSubStart_Memory(void);
249 static void AtSubStart_ResourceOwner(void);
251 static void ShowTransactionState(const char *str);
252 static void ShowTransactionStateRec(TransactionState state);
253 static const char *BlockStateAsString(TBlockState blockState);
254 static const char *TransStateAsString(TransState state);
257 /* ----------------------------------------------------------------
258 * transaction state accessors
259 * ----------------------------------------------------------------
265 * This returns true if we are inside a valid transaction; that is,
266 * it is safe to initiate database access, take heavyweight locks, etc.
269 IsTransactionState(void)
271 TransactionState s = CurrentTransactionState;
274 * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However,
275 * we also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
276 * TRANS_PREPARE since it might be too soon or too late within those
277 * transition states to do anything interesting. Hence, the only "valid"
278 * state is TRANS_INPROGRESS.
280 return (s->state == TRANS_INPROGRESS);
284 * IsAbortedTransactionBlockState
286 * This returns true if we are currently running a query
287 * within an aborted transaction block.
290 IsAbortedTransactionBlockState(void)
292 TransactionState s = CurrentTransactionState;
294 if (s->blockState == TBLOCK_ABORT ||
295 s->blockState == TBLOCK_SUBABORT)
303 * GetTopTransactionId
305 * Get the ID of the main transaction, even if we are currently inside
306 * a subtransaction. If we are not in a transaction at all, or if we
307 * are in transaction startup and haven't yet assigned an XID,
308 * InvalidTransactionId is returned.
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 * GetCurrentTransactionStopTimestamp
440 * We return current time if the transaction stop time hasn't been set
441 * (which can happen if we decide we don't need to log an XLOG record).
444 GetCurrentTransactionStopTimestamp(void)
446 if (xactStopTimestamp != 0)
447 return xactStopTimestamp;
448 return GetCurrentTimestamp();
452 * SetCurrentStatementStartTimestamp
455 SetCurrentStatementStartTimestamp(void)
457 stmtStartTimestamp = GetCurrentTimestamp();
461 * SetCurrentTransactionStopTimestamp
464 SetCurrentTransactionStopTimestamp(void)
466 xactStopTimestamp = GetCurrentTimestamp();
470 * GetCurrentTransactionNestLevel
472 * Note: this will return zero when not inside any transaction, one when
473 * inside a top-level transaction, etc.
476 GetCurrentTransactionNestLevel(void)
478 TransactionState s = CurrentTransactionState;
480 return s->nestingLevel;
485 * TransactionIdIsCurrentTransactionId
488 TransactionIdIsCurrentTransactionId(TransactionId xid)
493 * We always say that BootstrapTransactionId is "not my transaction ID"
494 * even when it is (ie, during bootstrap). Along with the fact that
495 * transam.c always treats BootstrapTransactionId as already committed,
496 * this causes the tqual.c routines to see all tuples as committed, which
497 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
498 * it never updates or deletes them, so all tuples can be presumed good
501 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
502 * not my transaction ID, so we can just return "false" immediately for
503 * any non-normal XID.
505 if (!TransactionIdIsNormal(xid))
509 * We will return true for the Xid of the current subtransaction, any of
510 * its subcommitted children, any of its parents, or any of their
511 * previously subcommitted children. However, a transaction being aborted
512 * is no longer "current", even though it may still have an entry on the
515 for (s = CurrentTransactionState; s != NULL; s = s->parent)
519 if (s->state == TRANS_ABORT)
521 if (!TransactionIdIsValid(s->transactionId))
522 continue; /* it can't have any child XIDs either */
523 if (TransactionIdEquals(xid, s->transactionId))
525 foreach(cell, s->childXids)
527 if (TransactionIdEquals(xid, lfirst_xid(cell)))
537 * CommandCounterIncrement
540 CommandCounterIncrement(void)
542 currentCommandId += 1;
543 if (currentCommandId == FirstCommandId) /* check for overflow */
545 currentCommandId -= 1;
547 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
548 errmsg("cannot have more than 2^32-1 commands in a transaction")));
551 /* Propagate new command ID into static snapshots, if set */
552 if (SerializableSnapshot)
553 SerializableSnapshot->curcid = currentCommandId;
555 LatestSnapshot->curcid = currentCommandId;
558 * make cache changes visible to me.
560 AtCommit_LocalCache();
567 * Interface routine to allow commands to force a synchronous commit of the
568 * current top-level transaction
571 ForceSyncCommit(void)
573 forceSyncCommit = true;
577 /* ----------------------------------------------------------------
578 * StartTransaction stuff
579 * ----------------------------------------------------------------
588 AcceptInvalidationMessages();
597 TransactionState s = CurrentTransactionState;
600 * If this is the first time through, create a private context for
601 * AbortTransaction to work in. By reserving some space now, we can
602 * insulate AbortTransaction from out-of-memory scenarios. Like
603 * ErrorContext, we set it up with slow growth rate and a nonzero
604 * minimum size, so that space will be reserved immediately.
606 if (TransactionAbortContext == NULL)
607 TransactionAbortContext =
608 AllocSetContextCreate(TopMemoryContext,
609 "TransactionAbortContext",
615 * We shouldn't have a transaction context already.
617 Assert(TopTransactionContext == NULL);
620 * Create a toplevel context for the transaction.
622 TopTransactionContext =
623 AllocSetContextCreate(TopMemoryContext,
624 "TopTransactionContext",
625 ALLOCSET_DEFAULT_MINSIZE,
626 ALLOCSET_DEFAULT_INITSIZE,
627 ALLOCSET_DEFAULT_MAXSIZE);
630 * In a top-level transaction, CurTransactionContext is the same as
631 * TopTransactionContext.
633 CurTransactionContext = TopTransactionContext;
634 s->curTransactionContext = CurTransactionContext;
636 /* Make the CurTransactionContext active. */
637 MemoryContextSwitchTo(CurTransactionContext);
641 * AtStart_ResourceOwner
644 AtStart_ResourceOwner(void)
646 TransactionState s = CurrentTransactionState;
649 * We shouldn't have a transaction resource owner already.
651 Assert(TopTransactionResourceOwner == NULL);
654 * Create a toplevel resource owner for the transaction.
656 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
658 TopTransactionResourceOwner = s->curTransactionOwner;
659 CurTransactionResourceOwner = s->curTransactionOwner;
660 CurrentResourceOwner = s->curTransactionOwner;
663 /* ----------------------------------------------------------------
664 * StartSubTransaction stuff
665 * ----------------------------------------------------------------
672 AtSubStart_Memory(void)
674 TransactionState s = CurrentTransactionState;
676 Assert(CurTransactionContext != NULL);
679 * Create a CurTransactionContext, which will be used to hold data that
680 * survives subtransaction commit but disappears on subtransaction abort.
681 * We make it a child of the immediate parent's CurTransactionContext.
683 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
684 "CurTransactionContext",
685 ALLOCSET_DEFAULT_MINSIZE,
686 ALLOCSET_DEFAULT_INITSIZE,
687 ALLOCSET_DEFAULT_MAXSIZE);
688 s->curTransactionContext = CurTransactionContext;
690 /* Make the CurTransactionContext active. */
691 MemoryContextSwitchTo(CurTransactionContext);
695 * AtSubStart_ResourceOwner
698 AtSubStart_ResourceOwner(void)
700 TransactionState s = CurrentTransactionState;
702 Assert(s->parent != NULL);
705 * Create a resource owner for the subtransaction. We make it a child of
706 * the immediate parent's resource owner.
708 s->curTransactionOwner =
709 ResourceOwnerCreate(s->parent->curTransactionOwner,
712 CurTransactionResourceOwner = s->curTransactionOwner;
713 CurrentResourceOwner = s->curTransactionOwner;
716 /* ----------------------------------------------------------------
717 * CommitTransaction stuff
718 * ----------------------------------------------------------------
722 * RecordTransactionCommit
725 RecordTransactionCommit(void)
730 TransactionId *children;
732 /* Get data needed for commit record */
733 nrels = smgrGetPendingDeletes(true, &rels);
734 nchildren = xactGetCommittedChildren(&children);
737 * If we made neither any XLOG entries nor any temp-rel updates, and have
738 * no files to be deleted, we can omit recording the transaction commit at
739 * all. (This test includes the effects of subtransactions, so the
740 * presence of committed subxacts need not alone force a write.)
742 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
744 TransactionId xid = GetCurrentTransactionId();
746 bool isAsyncCommit = false;
749 /* Tell bufmgr and smgr to prepare for commit */
752 START_CRIT_SECTION();
755 * We only need to log the commit in XLOG if the transaction made any
756 * transaction-controlled XLOG entries or will delete files.
758 madeTCentries = (MyLastRecPtr.xrecoff != 0);
759 if (madeTCentries || nrels > 0)
761 XLogRecData rdata[3];
763 xl_xact_commit xlrec;
766 * Mark ourselves as within our "commit critical section". This
767 * forces any concurrent checkpoint to wait until we've updated
768 * pg_clog. Without this, it is possible for the checkpoint to
769 * set REDO after the XLOG record but fail to flush the pg_clog
770 * update to disk, leading to loss of the transaction commit if
771 * the system crashes a little later.
773 * Note: we could, but don't bother to, set this flag in
774 * RecordTransactionAbort. That's because loss of a transaction
775 * abort is noncritical; the presumption would be that it aborted,
778 * It's safe to change the inCommit flag of our own backend
779 * without holding the ProcArrayLock, since we're the only one
780 * modifying it. This makes checkpoint's determination of which
781 * xacts are inCommit a bit fuzzy, but it doesn't matter.
783 MyProc->inCommit = true;
785 SetCurrentTransactionStopTimestamp();
786 xlrec.xact_time = xactStopTimestamp;
788 xlrec.nsubxacts = nchildren;
789 rdata[0].data = (char *) (&xlrec);
790 rdata[0].len = MinSizeOfXactCommit;
791 rdata[0].buffer = InvalidBuffer;
792 /* dump rels to delete */
795 rdata[0].next = &(rdata[1]);
796 rdata[1].data = (char *) rels;
797 rdata[1].len = nrels * sizeof(RelFileNode);
798 rdata[1].buffer = InvalidBuffer;
801 /* dump committed child Xids */
804 rdata[lastrdata].next = &(rdata[2]);
805 rdata[2].data = (char *) children;
806 rdata[2].len = nchildren * sizeof(TransactionId);
807 rdata[2].buffer = InvalidBuffer;
810 rdata[lastrdata].next = NULL;
812 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
816 /* Just flush through last record written by me */
817 recptr = ProcLastRecEnd;
821 * We must flush our XLOG entries to disk if we made any XLOG entries,
822 * whether in or out of transaction control. For example, if we
823 * reported a nextval() result to the client, this ensures that any
824 * XLOG record generated by nextval will hit the disk before we report
825 * the transaction committed.
827 * Note: if we generated a commit record above, MyXactMadeXLogEntry
828 * will certainly be set now.
830 if (MyXactMadeXLogEntry)
833 * If the user has set synchronous_commit = off, and we're
834 * not doing cleanup of any rels nor committing any command
835 * that wanted to force sync commit, then we can defer fsync.
837 if (XactSyncCommit || forceSyncCommit || nrels > 0)
840 * Synchronous commit case.
842 * Sleep before flush! So we can flush more than one commit
843 * records per single fsync. (The idea is some other backend
844 * may do the XLogFlush while we're sleeping. This needs work
845 * still, because on most Unixen, the minimum select() delay
846 * is 10msec or more, which is way too long.)
848 * We do not sleep if enableFsync is not turned on, nor if
849 * there are fewer than CommitSiblings other backends with
850 * active transactions.
852 if (CommitDelay > 0 && enableFsync &&
853 CountActiveBackends() >= CommitSiblings)
854 pg_usleep(CommitDelay);
861 * Asynchronous commit case.
863 isAsyncCommit = true;
866 * Report the latest async commit LSN, so that
867 * the WAL writer knows to flush this commit.
869 XLogSetAsyncCommitLSN(recptr);
874 * We must mark the transaction committed in clog if its XID appears
875 * either in permanent rels or in local temporary rels. We test this
876 * by seeing if we made transaction-controlled entries *OR* local-rel
877 * tuple updates. Note that if we made only the latter, we have not
878 * emitted an XLOG record for our commit, and so in the event of a
879 * crash the clog update might be lost. This is okay because no one
880 * else will ever care whether we committed.
882 * The recptr here refers to the last xlog entry by this transaction
883 * so is the correct value to use for setting the clog.
885 if (madeTCentries || MyXactMadeTempRelUpdate)
889 TransactionIdAsyncCommit(xid, recptr);
890 /* to avoid race conditions, the parent must commit first */
891 TransactionIdAsyncCommitTree(nchildren, children, recptr);
895 TransactionIdCommit(xid);
896 /* to avoid race conditions, the parent must commit first */
897 TransactionIdCommitTree(nchildren, children);
901 /* Checkpoint can proceed now */
902 MyProc->inCommit = false;
907 /* Break the chain of back-links in the XLOG records I output */
908 MyLastRecPtr.xrecoff = 0;
909 MyXactMadeXLogEntry = false;
910 MyXactMadeTempRelUpdate = false;
912 /* And clean up local data */
921 * AtCommit_LocalCache
924 AtCommit_LocalCache(void)
927 * Make catalog changes visible to me for the next command.
929 CommandEndInvalidationMessages();
936 AtCommit_Memory(void)
939 * Now that we're "out" of a transaction, have the system allocate things
940 * in the top memory context instead of per-transaction contexts.
942 MemoryContextSwitchTo(TopMemoryContext);
945 * Release all transaction-local memory.
947 Assert(TopTransactionContext != NULL);
948 MemoryContextDelete(TopTransactionContext);
949 TopTransactionContext = NULL;
950 CurTransactionContext = NULL;
951 CurrentTransactionState->curTransactionContext = NULL;
954 /* ----------------------------------------------------------------
955 * CommitSubTransaction stuff
956 * ----------------------------------------------------------------
963 AtSubCommit_Memory(void)
965 TransactionState s = CurrentTransactionState;
967 Assert(s->parent != NULL);
969 /* Return to parent transaction level's memory context. */
970 CurTransactionContext = s->parent->curTransactionContext;
971 MemoryContextSwitchTo(CurTransactionContext);
974 * Ordinarily we cannot throw away the child's CurTransactionContext,
975 * since the data it contains will be needed at upper commit. However, if
976 * there isn't actually anything in it, we can throw it away. This avoids
977 * a small memory leak in the common case of "trivial" subxacts.
979 if (MemoryContextIsEmpty(s->curTransactionContext))
981 MemoryContextDelete(s->curTransactionContext);
982 s->curTransactionContext = NULL;
987 * AtSubCommit_childXids
989 * Pass my own XID and my child XIDs up to my parent as committed children.
992 AtSubCommit_childXids(void)
994 TransactionState s = CurrentTransactionState;
995 MemoryContext old_cxt;
997 Assert(s->parent != NULL);
1000 * We keep the child-XID lists in TopTransactionContext; this avoids
1001 * setting up child-transaction contexts for what might be just a few
1002 * bytes of grandchild XIDs.
1004 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
1006 s->parent->childXids = lappend_xid(s->parent->childXids,
1009 if (s->childXids != NIL)
1011 s->parent->childXids = list_concat(s->parent->childXids,
1015 * list_concat doesn't free the list header for the second list; do so
1016 * here to avoid memory leakage (kluge)
1018 pfree(s->childXids);
1022 MemoryContextSwitchTo(old_cxt);
1026 * RecordSubTransactionCommit
1029 RecordSubTransactionCommit(void)
1032 * We do not log the subcommit in XLOG; it doesn't matter until the
1033 * top-level transaction commits.
1035 * We must mark the subtransaction subcommitted in clog if its XID appears
1036 * either in permanent rels or in local temporary rels. We test this by
1037 * seeing if we made transaction-controlled entries *OR* local-rel tuple
1038 * updates. (The test here actually covers the entire transaction tree so
1039 * far, so it may mark subtransactions that don't really need it, but it's
1040 * probably not worth being tenser. Note that if a prior subtransaction
1041 * dirtied these variables, then RecordTransactionCommit will have to do
1042 * the full pushup anyway...)
1044 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
1046 TransactionId xid = GetCurrentTransactionId();
1048 /* XXX does this really need to be a critical section? */
1049 START_CRIT_SECTION();
1051 /* Record subtransaction subcommit */
1052 TransactionIdSubCommit(xid);
1058 /* ----------------------------------------------------------------
1059 * AbortTransaction stuff
1060 * ----------------------------------------------------------------
1064 * RecordTransactionAbort
1067 RecordTransactionAbort(void)
1072 TransactionId *children;
1074 /* Get data needed for abort record */
1075 nrels = smgrGetPendingDeletes(false, &rels);
1076 nchildren = xactGetCommittedChildren(&children);
1079 * If we made neither any transaction-controlled XLOG entries nor any
1080 * temp-rel updates, and are not going to delete any files, we can omit
1081 * recording the transaction abort at all. No one will ever care that it
1082 * aborted. (These tests cover our whole transaction tree.)
1084 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1086 TransactionId xid = GetCurrentTransactionId();
1089 * Catch the scenario where we aborted partway through
1090 * RecordTransactionCommit ...
1092 if (TransactionIdDidCommit(xid))
1093 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1095 START_CRIT_SECTION();
1098 * We only need to log the abort in XLOG if the transaction made any
1099 * transaction-controlled XLOG entries or will delete files. (If it
1100 * made no transaction-controlled XLOG entries, its XID appears
1101 * nowhere in permanent storage, so no one else will ever care if it
1104 * We do not flush XLOG to disk unless deleting files, since the
1105 * default assumption after a crash would be that we aborted, anyway.
1106 * For the same reason, we don't need to worry about interlocking
1107 * against checkpoint start.
1109 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1111 XLogRecData rdata[3];
1113 xl_xact_abort xlrec;
1116 SetCurrentTransactionStopTimestamp();
1117 xlrec.xact_time = xactStopTimestamp;
1118 xlrec.nrels = nrels;
1119 xlrec.nsubxacts = nchildren;
1120 rdata[0].data = (char *) (&xlrec);
1121 rdata[0].len = MinSizeOfXactAbort;
1122 rdata[0].buffer = InvalidBuffer;
1123 /* dump rels to delete */
1126 rdata[0].next = &(rdata[1]);
1127 rdata[1].data = (char *) rels;
1128 rdata[1].len = nrels * sizeof(RelFileNode);
1129 rdata[1].buffer = InvalidBuffer;
1132 /* dump committed child Xids */
1135 rdata[lastrdata].next = &(rdata[2]);
1136 rdata[2].data = (char *) children;
1137 rdata[2].len = nchildren * sizeof(TransactionId);
1138 rdata[2].buffer = InvalidBuffer;
1141 rdata[lastrdata].next = NULL;
1143 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1145 /* Must flush if we are deleting files... */
1151 * Mark the transaction aborted in clog. This is not absolutely
1152 * necessary but we may as well do it while we are here.
1154 * The ordering here isn't critical but it seems best to mark the
1155 * parent first. This assures an atomic transition of all the
1156 * subtransactions to aborted state from the point of view of
1157 * concurrent TransactionIdDidAbort calls.
1159 TransactionIdAbort(xid);
1160 TransactionIdAbortTree(nchildren, children);
1165 /* Break the chain of back-links in the XLOG records I output */
1166 MyLastRecPtr.xrecoff = 0;
1167 MyXactMadeXLogEntry = false;
1168 MyXactMadeTempRelUpdate = false;
1170 /* And clean up local data */
1181 AtAbort_Memory(void)
1184 * Switch into TransactionAbortContext, which should have some free
1185 * space even if nothing else does. We'll work in this context until
1186 * we've finished cleaning up.
1188 * It is barely possible to get here when we've not been able to create
1189 * TransactionAbortContext yet; if so use TopMemoryContext.
1191 if (TransactionAbortContext != NULL)
1192 MemoryContextSwitchTo(TransactionAbortContext);
1194 MemoryContextSwitchTo(TopMemoryContext);
1201 AtSubAbort_Memory(void)
1203 Assert(TransactionAbortContext != NULL);
1205 MemoryContextSwitchTo(TransactionAbortContext);
1210 * AtAbort_ResourceOwner
1213 AtAbort_ResourceOwner(void)
1216 * Make sure we have a valid ResourceOwner, if possible (else it will be
1217 * NULL, which is OK)
1219 CurrentResourceOwner = TopTransactionResourceOwner;
1223 * AtSubAbort_ResourceOwner
1226 AtSubAbort_ResourceOwner(void)
1228 TransactionState s = CurrentTransactionState;
1230 /* Make sure we have a valid ResourceOwner */
1231 CurrentResourceOwner = s->curTransactionOwner;
1236 * AtSubAbort_childXids
1239 AtSubAbort_childXids(void)
1241 TransactionState s = CurrentTransactionState;
1244 * We keep the child-XID lists in TopTransactionContext (see
1245 * AtSubCommit_childXids). This means we'd better free the list
1246 * explicitly at abort to avoid leakage.
1248 list_free(s->childXids);
1253 * RecordSubTransactionAbort
1256 RecordSubTransactionAbort(void)
1260 TransactionId xid = GetCurrentTransactionId();
1262 TransactionId *children;
1264 /* Get data needed for abort record */
1265 nrels = smgrGetPendingDeletes(false, &rels);
1266 nchildren = xactGetCommittedChildren(&children);
1269 * If we made neither any transaction-controlled XLOG entries nor any
1270 * temp-rel updates, and are not going to delete any files, we can omit
1271 * recording the transaction abort at all. No one will ever care that it
1272 * aborted. (These tests cover our whole transaction tree, and therefore
1273 * may mark subxacts that don't really need it, but it's probably not
1274 * worth being tenser.)
1276 * In this case we needn't worry about marking subcommitted children as
1277 * aborted, because they didn't mark themselves as subcommitted in the
1278 * first place; see the optimization in RecordSubTransactionCommit.
1280 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1282 START_CRIT_SECTION();
1285 * We only need to log the abort in XLOG if the transaction made any
1286 * transaction-controlled XLOG entries or will delete files.
1288 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1290 XLogRecData rdata[3];
1292 xl_xact_abort xlrec;
1295 xlrec.xact_time = GetCurrentTimestamp();
1296 xlrec.nrels = nrels;
1297 xlrec.nsubxacts = nchildren;
1298 rdata[0].data = (char *) (&xlrec);
1299 rdata[0].len = MinSizeOfXactAbort;
1300 rdata[0].buffer = InvalidBuffer;
1301 /* dump rels to delete */
1304 rdata[0].next = &(rdata[1]);
1305 rdata[1].data = (char *) rels;
1306 rdata[1].len = nrels * sizeof(RelFileNode);
1307 rdata[1].buffer = InvalidBuffer;
1310 /* dump committed child Xids */
1313 rdata[lastrdata].next = &(rdata[2]);
1314 rdata[2].data = (char *) children;
1315 rdata[2].len = nchildren * sizeof(TransactionId);
1316 rdata[2].buffer = InvalidBuffer;
1319 rdata[lastrdata].next = NULL;
1321 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1323 /* Must flush if we are deleting files... */
1329 * Mark the transaction aborted in clog. This is not absolutely
1330 * necessary but XactLockTableWait makes use of it to avoid waiting
1331 * for already-aborted subtransactions.
1333 TransactionIdAbort(xid);
1334 TransactionIdAbortTree(nchildren, children);
1340 * We can immediately remove failed XIDs from PGPROC's cache of running
1341 * child XIDs. It's easiest to do it here while we have the child XID
1342 * array at hand, even though in the main-transaction case the equivalent
1343 * work happens just after return from RecordTransactionAbort.
1345 XidCacheRemoveRunningXids(xid, nchildren, children);
1347 /* And clean up local data */
1354 /* ----------------------------------------------------------------
1355 * CleanupTransaction stuff
1356 * ----------------------------------------------------------------
1363 AtCleanup_Memory(void)
1365 Assert(CurrentTransactionState->parent == NULL);
1368 * Now that we're "out" of a transaction, have the system allocate things
1369 * in the top memory context instead of per-transaction contexts.
1371 MemoryContextSwitchTo(TopMemoryContext);
1374 * Clear the special abort context for next time.
1376 if (TransactionAbortContext != NULL)
1377 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1380 * Release all transaction-local memory.
1382 if (TopTransactionContext != NULL)
1383 MemoryContextDelete(TopTransactionContext);
1384 TopTransactionContext = NULL;
1385 CurTransactionContext = NULL;
1386 CurrentTransactionState->curTransactionContext = NULL;
1390 /* ----------------------------------------------------------------
1391 * CleanupSubTransaction stuff
1392 * ----------------------------------------------------------------
1396 * AtSubCleanup_Memory
1399 AtSubCleanup_Memory(void)
1401 TransactionState s = CurrentTransactionState;
1403 Assert(s->parent != NULL);
1405 /* Make sure we're not in an about-to-be-deleted context */
1406 MemoryContextSwitchTo(s->parent->curTransactionContext);
1407 CurTransactionContext = s->parent->curTransactionContext;
1410 * Clear the special abort context for next time.
1412 if (TransactionAbortContext != NULL)
1413 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1416 * Delete the subxact local memory contexts. Its CurTransactionContext can
1417 * go too (note this also kills CurTransactionContexts from any children
1420 if (s->curTransactionContext)
1421 MemoryContextDelete(s->curTransactionContext);
1422 s->curTransactionContext = NULL;
1425 /* ----------------------------------------------------------------
1426 * interface routines
1427 * ----------------------------------------------------------------
1434 StartTransaction(void)
1439 * Let's just make sure the state stack is empty
1441 s = &TopTransactionStateData;
1442 CurrentTransactionState = s;
1445 * check the current transaction state
1447 if (s->state != TRANS_DEFAULT)
1448 elog(WARNING, "StartTransaction while in %s state",
1449 TransStateAsString(s->state));
1452 * set the current transaction state information appropriately during
1455 s->state = TRANS_START;
1456 s->transactionId = InvalidTransactionId; /* until assigned */
1459 * Make sure we've freed any old snapshot, and reset xact state variables
1462 XactIsoLevel = DefaultXactIsoLevel;
1463 XactReadOnly = DefaultXactReadOnly;
1464 forceSyncCommit = false;
1467 * reinitialize within-transaction counters
1469 s->subTransactionId = TopSubTransactionId;
1470 currentSubTransactionId = TopSubTransactionId;
1471 currentCommandId = FirstCommandId;
1474 * must initialize resource-management stuff first
1477 AtStart_ResourceOwner();
1480 * generate a new transaction id
1482 s->transactionId = GetNewTransactionId(false);
1484 XactLockTableInsert(s->transactionId);
1486 PG_TRACE1(transaction__start, s->transactionId);
1489 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1490 * as the first command's statement_timestamp(), so don't do a fresh
1491 * GetCurrentTimestamp() call (which'd be expensive anyway). Also,
1492 * mark xactStopTimestamp as unset.
1494 xactStartTimestamp = stmtStartTimestamp;
1495 xactStopTimestamp = 0;
1496 pgstat_report_txn_timestamp(xactStartTimestamp);
1499 * initialize current transaction state fields
1501 s->nestingLevel = 1;
1505 * You might expect to see "s->currentUser = GetUserId();" here, but you
1506 * won't because it doesn't work during startup; the userid isn't set yet
1507 * during a backend's first transaction start. We only use the
1508 * currentUser field in sub-transaction state structs.
1510 * prevXactReadOnly is also valid only in sub-transactions.
1514 * initialize other subsystems for new transaction
1518 AfterTriggerBeginXact();
1521 * done with start processing, set current transaction state to "in
1524 s->state = TRANS_INPROGRESS;
1526 ShowTransactionState("StartTransaction");
1533 * NB: if you change this routine, better look at PrepareTransaction too!
1536 CommitTransaction(void)
1538 TransactionState s = CurrentTransactionState;
1540 ShowTransactionState("CommitTransaction");
1543 * check the current transaction state
1545 if (s->state != TRANS_INPROGRESS)
1546 elog(WARNING, "CommitTransaction while in %s state",
1547 TransStateAsString(s->state));
1548 Assert(s->parent == NULL);
1551 * Do pre-commit processing (most of this stuff requires database access,
1552 * and in fact could still cause an error...)
1554 * It is possible for CommitHoldablePortals to invoke functions that queue
1555 * deferred triggers, and it's also possible that triggers create holdable
1556 * cursors. So we have to loop until there's nothing left to do.
1561 * Fire all currently pending deferred triggers.
1563 AfterTriggerFireDeferred();
1566 * Convert any open holdable cursors into static portals. If there
1567 * weren't any, we are done ... otherwise loop back to check if they
1568 * queued deferred triggers. Lather, rinse, repeat.
1570 if (!CommitHoldablePortals())
1574 /* Now we can shut down the deferred-trigger manager */
1575 AfterTriggerEndXact(true);
1577 /* Close any open regular cursors */
1581 * Let ON COMMIT management do its thing (must happen after closing
1582 * cursors, to avoid dangling-reference problems)
1584 PreCommit_on_commit_actions();
1586 /* close large objects before lower-level cleanup */
1587 AtEOXact_LargeObject(true);
1589 /* NOTIFY commit must come before lower-level cleanup */
1593 * Update flat files if we changed pg_database, pg_authid or
1594 * pg_auth_members. This should be the last step before commit.
1596 AtEOXact_UpdateFlatFiles(true);
1598 /* Prevent cancel/die interrupt while cleaning up */
1602 * set the current transaction state information appropriately during
1605 s->state = TRANS_COMMIT;
1608 * Here is where we really truly commit.
1610 RecordTransactionCommit();
1613 * Let others know about no transaction in progress by me. Note that
1614 * this must be done _before_ releasing locks we hold and _after_
1615 * RecordTransactionCommit.
1617 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1618 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1619 * xid 1 is doing commit while xid 2 gets snapshot.
1620 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1621 * xid 0 as running as well, or it will be able to see two tuple versions
1622 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1625 * Note: MyProc may be null during bootstrap.
1630 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1631 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1632 MyProc->xid = InvalidTransactionId;
1633 MyProc->xmin = InvalidTransactionId;
1634 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1636 /* Clear the subtransaction-XID cache too while holding the lock */
1637 MyProc->subxids.nxids = 0;
1638 MyProc->subxids.overflowed = false;
1640 LWLockRelease(ProcArrayLock);
1643 PG_TRACE1(transaction__commit, s->transactionId);
1646 * This is all post-commit cleanup. Note that if an error is raised here,
1647 * it's too late to abort the transaction. This should be just
1648 * noncritical resource releasing.
1650 * The ordering of operations is not entirely random. The idea is:
1651 * release resources visible to other backends (eg, files, buffer pins);
1652 * then release locks; then release backend-local resources. We want to
1653 * release locks at the point where any backend waiting for us will see
1654 * our transaction as being fully cleaned up.
1656 * Resources that can be associated with individual queries are handled by
1657 * the ResourceOwner mechanism. The other calls here are for backend-wide
1661 CallXactCallbacks(XACT_EVENT_COMMIT);
1663 ResourceOwnerRelease(TopTransactionResourceOwner,
1664 RESOURCE_RELEASE_BEFORE_LOCKS,
1667 /* Check we've released all buffer pins */
1668 AtEOXact_Buffers(true);
1670 /* Clean up the relation cache */
1671 AtEOXact_RelationCache(true);
1674 * Make catalog changes visible to all backends. This has to happen after
1675 * relcache references are dropped (see comments for
1676 * AtEOXact_RelationCache), but before locks are released (if anyone is
1677 * waiting for lock on a relation we've modified, we want them to know
1678 * about the catalog change before they start using the relation).
1680 AtEOXact_Inval(true);
1683 * Likewise, dropping of files deleted during the transaction is best done
1684 * after releasing relcache and buffer pins. (This is not strictly
1685 * necessary during commit, since such pins should have been released
1686 * already, but this ordering is definitely critical during abort.)
1688 smgrDoPendingDeletes(true);
1690 AtEOXact_MultiXact();
1692 ResourceOwnerRelease(TopTransactionResourceOwner,
1693 RESOURCE_RELEASE_LOCKS,
1695 ResourceOwnerRelease(TopTransactionResourceOwner,
1696 RESOURCE_RELEASE_AFTER_LOCKS,
1699 /* Check we've released all catcache entries */
1700 AtEOXact_CatCache(true);
1702 AtEOXact_GUC(true, false);
1704 AtEOXact_on_commit_actions(true);
1705 AtEOXact_Namespace(true);
1706 /* smgrcommit already done */
1708 AtEOXact_ComboCid();
1709 AtEOXact_HashTables(true);
1710 AtEOXact_PgStat(true);
1711 pgstat_report_txn_timestamp(0);
1713 CurrentResourceOwner = NULL;
1714 ResourceOwnerDelete(TopTransactionResourceOwner);
1715 s->curTransactionOwner = NULL;
1716 CurTransactionResourceOwner = NULL;
1717 TopTransactionResourceOwner = NULL;
1721 s->transactionId = InvalidTransactionId;
1722 s->subTransactionId = InvalidSubTransactionId;
1723 s->nestingLevel = 0;
1727 * done with commit processing, set current transaction state back to
1730 s->state = TRANS_DEFAULT;
1732 RESUME_INTERRUPTS();
1737 * PrepareTransaction
1739 * NB: if you change this routine, better look at CommitTransaction too!
1742 PrepareTransaction(void)
1744 TransactionState s = CurrentTransactionState;
1745 TransactionId xid = GetCurrentTransactionId();
1746 GlobalTransaction gxact;
1747 TimestampTz prepared_at;
1749 ShowTransactionState("PrepareTransaction");
1752 * check the current transaction state
1754 if (s->state != TRANS_INPROGRESS)
1755 elog(WARNING, "PrepareTransaction while in %s state",
1756 TransStateAsString(s->state));
1757 Assert(s->parent == NULL);
1760 * Do pre-commit processing (most of this stuff requires database access,
1761 * and in fact could still cause an error...)
1763 * It is possible for PrepareHoldablePortals to invoke functions that
1764 * queue deferred triggers, and it's also possible that triggers create
1765 * holdable cursors. So we have to loop until there's nothing left to do.
1770 * Fire all currently pending deferred triggers.
1772 AfterTriggerFireDeferred();
1775 * Convert any open holdable cursors into static portals. If there
1776 * weren't any, we are done ... otherwise loop back to check if they
1777 * queued deferred triggers. Lather, rinse, repeat.
1779 if (!PrepareHoldablePortals())
1783 /* Now we can shut down the deferred-trigger manager */
1784 AfterTriggerEndXact(true);
1786 /* Close any open regular cursors */
1790 * Let ON COMMIT management do its thing (must happen after closing
1791 * cursors, to avoid dangling-reference problems)
1793 PreCommit_on_commit_actions();
1795 /* close large objects before lower-level cleanup */
1796 AtEOXact_LargeObject(true);
1798 /* NOTIFY and flatfiles will be handled below */
1800 /* Prevent cancel/die interrupt while cleaning up */
1804 * set the current transaction state information appropriately during
1805 * prepare processing
1807 s->state = TRANS_PREPARE;
1809 prepared_at = GetCurrentTimestamp();
1811 /* Tell bufmgr and smgr to prepare for commit */
1815 * Reserve the GID for this transaction. This could fail if the requested
1816 * GID is invalid or already in use.
1818 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1819 GetUserId(), MyDatabaseId);
1823 * Collect data for the 2PC state file. Note that in general, no actual
1824 * state change should happen in the called modules during this step,
1825 * since it's still possible to fail before commit, and in that case we
1826 * want transaction abort to be able to clean up. (In particular, the
1827 * AtPrepare routines may error out if they find cases they cannot
1828 * handle.) State cleanup should happen in the PostPrepare routines
1829 * below. However, some modules can go ahead and clear state here because
1830 * they wouldn't do anything with it during abort anyway.
1832 * Note: because the 2PC state file records will be replayed in the same
1833 * order they are made, the order of these calls has to match the order in
1834 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1835 * PREPARED; in particular, pay attention to whether things should happen
1836 * before or after releasing the transaction's locks.
1838 StartPrepare(gxact);
1841 AtPrepare_UpdateFlatFiles();
1847 * Here is where we really truly prepare.
1849 * We have to record transaction prepares even if we didn't make any
1850 * updates, because the transaction manager might get confused if we lose
1851 * a global transaction.
1856 * Now we clean up backend-internal state and release internal resources.
1859 /* Break the chain of back-links in the XLOG records I output */
1860 MyLastRecPtr.xrecoff = 0;
1861 MyXactMadeXLogEntry = false;
1862 MyXactMadeTempRelUpdate = false;
1865 * Let others know about no transaction in progress by me. This has to be
1866 * done *after* the prepared transaction has been marked valid, else
1867 * someone may think it is unlocked and recyclable.
1870 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1871 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1872 MyProc->xid = InvalidTransactionId;
1873 MyProc->xmin = InvalidTransactionId;
1874 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
1876 /* Clear the subtransaction-XID cache too while holding the lock */
1877 MyProc->subxids.nxids = 0;
1878 MyProc->subxids.overflowed = false;
1880 LWLockRelease(ProcArrayLock);
1883 * This is all post-transaction cleanup. Note that if an error is raised
1884 * here, it's too late to abort the transaction. This should be just
1885 * noncritical resource releasing. See notes in CommitTransaction.
1888 CallXactCallbacks(XACT_EVENT_PREPARE);
1890 ResourceOwnerRelease(TopTransactionResourceOwner,
1891 RESOURCE_RELEASE_BEFORE_LOCKS,
1894 /* Check we've released all buffer pins */
1895 AtEOXact_Buffers(true);
1897 /* Clean up the relation cache */
1898 AtEOXact_RelationCache(true);
1900 /* notify and flatfiles don't need a postprepare call */
1902 PostPrepare_PgStat();
1904 PostPrepare_Inval();
1908 AtEOXact_MultiXact();
1910 PostPrepare_Locks(xid);
1912 ResourceOwnerRelease(TopTransactionResourceOwner,
1913 RESOURCE_RELEASE_LOCKS,
1915 ResourceOwnerRelease(TopTransactionResourceOwner,
1916 RESOURCE_RELEASE_AFTER_LOCKS,
1919 /* Check we've released all catcache entries */
1920 AtEOXact_CatCache(true);
1922 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1923 AtEOXact_GUC(true, false);
1925 AtEOXact_on_commit_actions(true);
1926 AtEOXact_Namespace(true);
1927 /* smgrcommit already done */
1929 AtEOXact_ComboCid();
1930 AtEOXact_HashTables(true);
1931 /* don't call AtEOXact_PgStat here */
1933 CurrentResourceOwner = NULL;
1934 ResourceOwnerDelete(TopTransactionResourceOwner);
1935 s->curTransactionOwner = NULL;
1936 CurTransactionResourceOwner = NULL;
1937 TopTransactionResourceOwner = NULL;
1941 s->transactionId = InvalidTransactionId;
1942 s->subTransactionId = InvalidSubTransactionId;
1943 s->nestingLevel = 0;
1947 * done with 1st phase commit processing, set current transaction state
1950 s->state = TRANS_DEFAULT;
1952 RESUME_INTERRUPTS();
1960 AbortTransaction(void)
1962 TransactionState s = CurrentTransactionState;
1964 /* Prevent cancel/die interrupt while cleaning up */
1967 /* Make sure we have a valid memory context and resource owner */
1969 AtAbort_ResourceOwner();
1972 * Release any LW locks we might be holding as quickly as possible.
1973 * (Regular locks, however, must be held till we finish aborting.)
1974 * Releasing LW locks is critical since we might try to grab them again
1975 * while cleaning up!
1979 /* Clean up buffer I/O and buffer context locks, too */
1984 * Also clean up any open wait for lock, since the lock manager will choke
1985 * if we try to wait for another lock before doing this.
1990 * check the current transaction state
1992 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1993 elog(WARNING, "AbortTransaction while in %s state",
1994 TransStateAsString(s->state));
1995 Assert(s->parent == NULL);
1998 * set the current transaction state information appropriately during the
2001 s->state = TRANS_ABORT;
2004 * Reset user id which might have been changed transiently. We cannot use
2005 * s->currentUser, since it may not be set yet; instead rely on internal
2006 * state of miscinit.c.
2008 * (Note: it is not necessary to restore session authorization here
2009 * because that can only be changed via GUC, and GUC will take care of
2010 * rolling it back if need be. However, an error within a SECURITY
2011 * DEFINER function could send control here with the wrong current
2017 * do abort processing
2019 AfterTriggerEndXact(false);
2021 AtEOXact_LargeObject(false); /* 'false' means it's abort */
2023 AtEOXact_UpdateFlatFiles(false);
2026 * Advertise the fact that we aborted in pg_clog (assuming that we got as
2027 * far as assigning an XID to advertise).
2029 if (TransactionIdIsValid(s->transactionId))
2030 RecordTransactionAbort();
2033 * Let others know about no transaction in progress by me. Note that this
2034 * must be done _before_ releasing locks we hold and _after_
2035 * RecordTransactionAbort.
2039 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
2040 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2041 MyProc->xid = InvalidTransactionId;
2042 MyProc->xmin = InvalidTransactionId;
2043 MyProc->inVacuum = false; /* must be cleared with xid/xmin */
2044 MyProc->inCommit = false; /* be sure this gets cleared */
2046 /* Clear the subtransaction-XID cache too while holding the lock */
2047 MyProc->subxids.nxids = 0;
2048 MyProc->subxids.overflowed = false;
2050 LWLockRelease(ProcArrayLock);
2053 PG_TRACE1(transaction__abort, s->transactionId);
2056 * Post-abort cleanup. See notes in CommitTransaction() concerning
2060 CallXactCallbacks(XACT_EVENT_ABORT);
2062 ResourceOwnerRelease(TopTransactionResourceOwner,
2063 RESOURCE_RELEASE_BEFORE_LOCKS,
2065 AtEOXact_Buffers(false);
2066 AtEOXact_RelationCache(false);
2067 AtEOXact_Inval(false);
2068 smgrDoPendingDeletes(false);
2069 AtEOXact_MultiXact();
2070 ResourceOwnerRelease(TopTransactionResourceOwner,
2071 RESOURCE_RELEASE_LOCKS,
2073 ResourceOwnerRelease(TopTransactionResourceOwner,
2074 RESOURCE_RELEASE_AFTER_LOCKS,
2076 AtEOXact_CatCache(false);
2078 AtEOXact_GUC(false, false);
2079 AtEOXact_SPI(false);
2080 AtEOXact_on_commit_actions(false);
2081 AtEOXact_Namespace(false);
2084 AtEOXact_ComboCid();
2085 AtEOXact_HashTables(false);
2086 AtEOXact_PgStat(false);
2087 pgstat_report_txn_timestamp(0);
2090 * State remains TRANS_ABORT until CleanupTransaction().
2092 RESUME_INTERRUPTS();
2096 * CleanupTransaction
2099 CleanupTransaction(void)
2101 TransactionState s = CurrentTransactionState;
2104 * State should still be TRANS_ABORT from AbortTransaction().
2106 if (s->state != TRANS_ABORT)
2107 elog(FATAL, "CleanupTransaction: unexpected state %s",
2108 TransStateAsString(s->state));
2111 * do abort cleanup processing
2113 AtCleanup_Portals(); /* now safe to release portal memory */
2115 CurrentResourceOwner = NULL; /* and resource owner */
2116 if (TopTransactionResourceOwner)
2117 ResourceOwnerDelete(TopTransactionResourceOwner);
2118 s->curTransactionOwner = NULL;
2119 CurTransactionResourceOwner = NULL;
2120 TopTransactionResourceOwner = NULL;
2122 AtCleanup_Memory(); /* and transaction memory */
2124 s->transactionId = InvalidTransactionId;
2125 s->subTransactionId = InvalidSubTransactionId;
2126 s->nestingLevel = 0;
2130 * done with abort processing, set current transaction state back to
2133 s->state = TRANS_DEFAULT;
2137 * StartTransactionCommand
2140 StartTransactionCommand(void)
2142 TransactionState s = CurrentTransactionState;
2144 switch (s->blockState)
2147 * if we aren't in a transaction block, we just do our usual start
2150 case TBLOCK_DEFAULT:
2152 s->blockState = TBLOCK_STARTED;
2156 * We are somewhere in a transaction block or subtransaction and
2157 * about to start a new command. For now we do nothing, but
2158 * someday we may do command-local resource initialization. (Note
2159 * that any needed CommandCounterIncrement was done by the
2160 * previous CommitTransactionCommand.)
2162 case TBLOCK_INPROGRESS:
2163 case TBLOCK_SUBINPROGRESS:
2167 * Here we are in a failed transaction block (one of the commands
2168 * caused an abort) so we do nothing but remain in the abort
2169 * state. Eventually we will get a ROLLBACK command which will
2170 * get us out of this state. (It is up to other code to ensure
2171 * that no commands other than ROLLBACK will be processed in these
2175 case TBLOCK_SUBABORT:
2178 /* These cases are invalid. */
2179 case TBLOCK_STARTED:
2181 case TBLOCK_SUBBEGIN:
2184 case TBLOCK_ABORT_END:
2185 case TBLOCK_SUBABORT_END:
2186 case TBLOCK_ABORT_PENDING:
2187 case TBLOCK_SUBABORT_PENDING:
2188 case TBLOCK_SUBRESTART:
2189 case TBLOCK_SUBABORT_RESTART:
2190 case TBLOCK_PREPARE:
2191 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2192 BlockStateAsString(s->blockState));
2197 * We must switch to CurTransactionContext before returning. This is
2198 * already done if we called StartTransaction, otherwise not.
2200 Assert(CurTransactionContext != NULL);
2201 MemoryContextSwitchTo(CurTransactionContext);
2205 * CommitTransactionCommand
2208 CommitTransactionCommand(void)
2210 TransactionState s = CurrentTransactionState;
2212 switch (s->blockState)
2215 * This shouldn't happen, because it means the previous
2216 * StartTransactionCommand didn't set the STARTED state
2219 case TBLOCK_DEFAULT:
2220 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2221 BlockStateAsString(s->blockState));
2225 * If we aren't in a transaction block, just do our usual
2226 * transaction commit, and return to the idle state.
2228 case TBLOCK_STARTED:
2229 CommitTransaction();
2230 s->blockState = TBLOCK_DEFAULT;
2234 * We are completing a "BEGIN TRANSACTION" command, so we change
2235 * to the "transaction block in progress" state and return. (We
2236 * assume the BEGIN did nothing to the database, so we need no
2237 * CommandCounterIncrement.)
2240 s->blockState = TBLOCK_INPROGRESS;
2244 * This is the case when we have finished executing a command
2245 * someplace within a transaction block. We increment the command
2246 * counter and return.
2248 case TBLOCK_INPROGRESS:
2249 case TBLOCK_SUBINPROGRESS:
2250 CommandCounterIncrement();
2254 * We are completing a "COMMIT" command. Do it and return to the
2258 CommitTransaction();
2259 s->blockState = TBLOCK_DEFAULT;
2263 * Here we are in the middle of a transaction block but one of the
2264 * commands caused an abort so we do nothing but remain in the
2265 * abort state. Eventually we will get a ROLLBACK comand.
2268 case TBLOCK_SUBABORT:
2272 * Here we were in an aborted transaction block and we just got
2273 * the ROLLBACK command from the user, so clean up the
2274 * already-aborted transaction and return to the idle state.
2276 case TBLOCK_ABORT_END:
2277 CleanupTransaction();
2278 s->blockState = TBLOCK_DEFAULT;
2282 * Here we were in a perfectly good transaction block but the user
2283 * told us to ROLLBACK anyway. We have to abort the transaction
2284 * and then clean up.
2286 case TBLOCK_ABORT_PENDING:
2288 CleanupTransaction();
2289 s->blockState = TBLOCK_DEFAULT;
2293 * We are completing a "PREPARE TRANSACTION" command. Do it and
2294 * return to the idle state.
2296 case TBLOCK_PREPARE:
2297 PrepareTransaction();
2298 s->blockState = TBLOCK_DEFAULT;
2302 * We were just issued a SAVEPOINT inside a transaction block.
2303 * Start a subtransaction. (DefineSavepoint already did
2304 * PushTransaction, so as to have someplace to put the SUBBEGIN
2307 case TBLOCK_SUBBEGIN:
2308 StartSubTransaction();
2309 s->blockState = TBLOCK_SUBINPROGRESS;
2313 * We were issued a COMMIT or RELEASE command, so we end the
2314 * current subtransaction and return to the parent transaction.
2315 * The parent might be ended too, so repeat till we are all the
2316 * way out or find an INPROGRESS transaction.
2321 CommitSubTransaction();
2322 s = CurrentTransactionState; /* changed by pop */
2323 } while (s->blockState == TBLOCK_SUBEND);
2324 /* If we had a COMMIT command, finish off the main xact too */
2325 if (s->blockState == TBLOCK_END)
2327 Assert(s->parent == NULL);
2328 CommitTransaction();
2329 s->blockState = TBLOCK_DEFAULT;
2331 else if (s->blockState == TBLOCK_PREPARE)
2333 Assert(s->parent == NULL);
2334 PrepareTransaction();
2335 s->blockState = TBLOCK_DEFAULT;
2339 Assert(s->blockState == TBLOCK_INPROGRESS ||
2340 s->blockState == TBLOCK_SUBINPROGRESS);
2345 * The current already-failed subtransaction is ending due to a
2346 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2347 * examine the parent (which could be in any of several states).
2349 case TBLOCK_SUBABORT_END:
2350 CleanupSubTransaction();
2351 CommitTransactionCommand();
2355 * As above, but it's not dead yet, so abort first.
2357 case TBLOCK_SUBABORT_PENDING:
2358 AbortSubTransaction();
2359 CleanupSubTransaction();
2360 CommitTransactionCommand();
2364 * The current subtransaction is the target of a ROLLBACK TO
2365 * command. Abort and pop it, then start a new subtransaction
2366 * with the same name.
2368 case TBLOCK_SUBRESTART:
2373 /* save name and keep Cleanup from freeing it */
2376 savepointLevel = s->savepointLevel;
2378 AbortSubTransaction();
2379 CleanupSubTransaction();
2381 DefineSavepoint(NULL);
2382 s = CurrentTransactionState; /* changed by push */
2384 s->savepointLevel = savepointLevel;
2386 /* This is the same as TBLOCK_SUBBEGIN case */
2387 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2388 StartSubTransaction();
2389 s->blockState = TBLOCK_SUBINPROGRESS;
2394 * Same as above, but the subtransaction had already failed, so we
2395 * don't need AbortSubTransaction.
2397 case TBLOCK_SUBABORT_RESTART:
2402 /* save name and keep Cleanup from freeing it */
2405 savepointLevel = s->savepointLevel;
2407 CleanupSubTransaction();
2409 DefineSavepoint(NULL);
2410 s = CurrentTransactionState; /* changed by push */
2412 s->savepointLevel = savepointLevel;
2414 /* This is the same as TBLOCK_SUBBEGIN case */
2415 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2416 StartSubTransaction();
2417 s->blockState = TBLOCK_SUBINPROGRESS;
2424 * AbortCurrentTransaction
2427 AbortCurrentTransaction(void)
2429 TransactionState s = CurrentTransactionState;
2431 switch (s->blockState)
2433 case TBLOCK_DEFAULT:
2434 if (s->state == TRANS_DEFAULT)
2436 /* we are idle, so nothing to do */
2441 * We can get here after an error during transaction start
2442 * (state will be TRANS_START). Need to clean up the
2443 * incompletely started transaction. First, adjust the
2444 * low-level state to suppress warning message from
2447 if (s->state == TRANS_START)
2448 s->state = TRANS_INPROGRESS;
2450 CleanupTransaction();
2455 * if we aren't in a transaction block, we just do the basic abort
2456 * & cleanup transaction.
2458 case TBLOCK_STARTED:
2460 CleanupTransaction();
2461 s->blockState = TBLOCK_DEFAULT;
2465 * If we are in TBLOCK_BEGIN it means something screwed up right
2466 * after reading "BEGIN TRANSACTION". We assume that the user
2467 * will interpret the error as meaning the BEGIN failed to get him
2468 * into a transaction block, so we should abort and return to idle
2473 CleanupTransaction();
2474 s->blockState = TBLOCK_DEFAULT;
2478 * We are somewhere in a transaction block and we've gotten a
2479 * failure, so we abort the transaction and set up the persistent
2480 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2482 case TBLOCK_INPROGRESS:
2484 s->blockState = TBLOCK_ABORT;
2485 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2489 * Here, we failed while trying to COMMIT. Clean up the
2490 * transaction and return to idle state (we do not want to stay in
2495 CleanupTransaction();
2496 s->blockState = TBLOCK_DEFAULT;
2500 * Here, we are already in an aborted transaction state and are
2501 * waiting for a ROLLBACK, but for some reason we failed again! So
2502 * we just remain in the abort state.
2505 case TBLOCK_SUBABORT:
2509 * We are in a failed transaction and we got the ROLLBACK command.
2510 * We have already aborted, we just need to cleanup and go to idle
2513 case TBLOCK_ABORT_END:
2514 CleanupTransaction();
2515 s->blockState = TBLOCK_DEFAULT;
2519 * We are in a live transaction and we got a ROLLBACK command.
2520 * Abort, cleanup, go to idle state.
2522 case TBLOCK_ABORT_PENDING:
2524 CleanupTransaction();
2525 s->blockState = TBLOCK_DEFAULT;
2529 * Here, we failed while trying to PREPARE. Clean up the
2530 * transaction and return to idle state (we do not want to stay in
2533 case TBLOCK_PREPARE:
2535 CleanupTransaction();
2536 s->blockState = TBLOCK_DEFAULT;
2540 * We got an error inside a subtransaction. Abort just the
2541 * subtransaction, and go to the persistent SUBABORT state until
2544 case TBLOCK_SUBINPROGRESS:
2545 AbortSubTransaction();
2546 s->blockState = TBLOCK_SUBABORT;
2550 * If we failed while trying to create a subtransaction, clean up
2551 * the broken subtransaction and abort the parent. The same
2552 * applies if we get a failure while ending a subtransaction.
2554 case TBLOCK_SUBBEGIN:
2556 case TBLOCK_SUBABORT_PENDING:
2557 case TBLOCK_SUBRESTART:
2558 AbortSubTransaction();
2559 CleanupSubTransaction();
2560 AbortCurrentTransaction();
2564 * Same as above, except the Abort() was already done.
2566 case TBLOCK_SUBABORT_END:
2567 case TBLOCK_SUBABORT_RESTART:
2568 CleanupSubTransaction();
2569 AbortCurrentTransaction();
2575 * PreventTransactionChain
2577 * This routine is to be called by statements that must not run inside
2578 * a transaction block, typically because they have non-rollback-able
2579 * side effects or do internal commits.
2581 * If we have already started a transaction block, issue an error; also issue
2582 * an error if we appear to be running inside a user-defined function (which
2583 * could issue more commands and possibly cause a failure after the statement
2584 * completes). Subtransactions are verboten too.
2586 * isTopLevel: passed down from ProcessUtility to determine whether we are
2587 * inside a function or multi-query querystring. (We will always fail if
2588 * this is false, but it's convenient to centralize the check here instead of
2589 * making callers do it.)
2590 * stmtType: statement type name, for error messages.
2593 PreventTransactionChain(bool isTopLevel, const char *stmtType)
2596 * xact block already started?
2598 if (IsTransactionBlock())
2600 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2601 /* translator: %s represents an SQL statement name */
2602 errmsg("%s cannot run inside a transaction block",
2608 if (IsSubTransaction())
2610 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2611 /* translator: %s represents an SQL statement name */
2612 errmsg("%s cannot run inside a subtransaction",
2616 * inside a function call?
2620 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2621 /* translator: %s represents an SQL statement name */
2622 errmsg("%s cannot be executed from a function or multi-command string",
2625 /* If we got past IsTransactionBlock test, should be in default state */
2626 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2627 CurrentTransactionState->blockState != TBLOCK_STARTED)
2628 elog(FATAL, "cannot prevent transaction chain");
2633 * RequireTransactionChain
2635 * This routine is to be called by statements that must run inside
2636 * a transaction block, because they have no effects that persist past
2637 * transaction end (and so calling them outside a transaction block
2638 * is presumably an error). DECLARE CURSOR is an example.
2640 * If we appear to be running inside a user-defined function, we do not
2641 * issue an error, since the function could issue more commands that make
2642 * use of the current statement's results. Likewise subtransactions.
2643 * Thus this is an inverse for PreventTransactionChain.
2645 * isTopLevel: passed down from ProcessUtility to determine whether we are
2646 * inside a function.
2647 * stmtType: statement type name, for error messages.
2650 RequireTransactionChain(bool isTopLevel, const char *stmtType)
2653 * xact block already started?
2655 if (IsTransactionBlock())
2661 if (IsSubTransaction())
2665 * inside a function call?
2671 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2672 /* translator: %s represents an SQL statement name */
2673 errmsg("%s can only be used in transaction blocks",
2678 * IsInTransactionChain
2680 * This routine is for statements that need to behave differently inside
2681 * a transaction block than when running as single commands. ANALYZE is
2682 * currently the only example.
2684 * isTopLevel: passed down from ProcessUtility to determine whether we are
2685 * inside a function.
2688 IsInTransactionChain(bool isTopLevel)
2691 * Return true on same conditions that would make PreventTransactionChain
2694 if (IsTransactionBlock())
2697 if (IsSubTransaction())
2703 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2704 CurrentTransactionState->blockState != TBLOCK_STARTED)
2712 * Register or deregister callback functions for start- and end-of-xact
2715 * These functions are intended for use by dynamically loaded modules.
2716 * For built-in modules we generally just hardwire the appropriate calls
2717 * (mainly because it's easier to control the order that way, where needed).
2719 * At transaction end, the callback occurs post-commit or post-abort, so the
2720 * callback functions can only do noncritical cleanup.
2723 RegisterXactCallback(XactCallback callback, void *arg)
2725 XactCallbackItem *item;
2727 item = (XactCallbackItem *)
2728 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2729 item->callback = callback;
2731 item->next = Xact_callbacks;
2732 Xact_callbacks = item;
2736 UnregisterXactCallback(XactCallback callback, void *arg)
2738 XactCallbackItem *item;
2739 XactCallbackItem *prev;
2742 for (item = Xact_callbacks; item; prev = item, item = item->next)
2744 if (item->callback == callback && item->arg == arg)
2747 prev->next = item->next;
2749 Xact_callbacks = item->next;
2757 CallXactCallbacks(XactEvent event)
2759 XactCallbackItem *item;
2761 for (item = Xact_callbacks; item; item = item->next)
2762 (*item->callback) (event, item->arg);
2767 * Register or deregister callback functions for start- and end-of-subxact
2770 * Pretty much same as above, but for subtransaction events.
2772 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2773 * so the callback functions can only do noncritical cleanup. At
2774 * subtransaction start, the callback is called when the subtransaction has
2775 * finished initializing.
2778 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2780 SubXactCallbackItem *item;
2782 item = (SubXactCallbackItem *)
2783 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2784 item->callback = callback;
2786 item->next = SubXact_callbacks;
2787 SubXact_callbacks = item;
2791 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2793 SubXactCallbackItem *item;
2794 SubXactCallbackItem *prev;
2797 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2799 if (item->callback == callback && item->arg == arg)
2802 prev->next = item->next;
2804 SubXact_callbacks = item->next;
2812 CallSubXactCallbacks(SubXactEvent event,
2813 SubTransactionId mySubid,
2814 SubTransactionId parentSubid)
2816 SubXactCallbackItem *item;
2818 for (item = SubXact_callbacks; item; item = item->next)
2819 (*item->callback) (event, mySubid, parentSubid, item->arg);
2823 /* ----------------------------------------------------------------
2824 * transaction block support
2825 * ----------------------------------------------------------------
2829 * BeginTransactionBlock
2830 * This executes a BEGIN command.
2833 BeginTransactionBlock(void)
2835 TransactionState s = CurrentTransactionState;
2837 switch (s->blockState)
2840 * We are not inside a transaction block, so allow one to begin.
2842 case TBLOCK_STARTED:
2843 s->blockState = TBLOCK_BEGIN;
2847 * Already a transaction block in progress.
2849 case TBLOCK_INPROGRESS:
2850 case TBLOCK_SUBINPROGRESS:
2852 case TBLOCK_SUBABORT:
2854 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2855 errmsg("there is already a transaction in progress")));
2858 /* These cases are invalid. */
2859 case TBLOCK_DEFAULT:
2861 case TBLOCK_SUBBEGIN:
2864 case TBLOCK_ABORT_END:
2865 case TBLOCK_SUBABORT_END:
2866 case TBLOCK_ABORT_PENDING:
2867 case TBLOCK_SUBABORT_PENDING:
2868 case TBLOCK_SUBRESTART:
2869 case TBLOCK_SUBABORT_RESTART:
2870 case TBLOCK_PREPARE:
2871 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2872 BlockStateAsString(s->blockState));
2878 * PrepareTransactionBlock
2879 * This executes a PREPARE command.
2881 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2882 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2884 * Note that we don't actually do anything here except change blockState.
2885 * The real work will be done in the upcoming PrepareTransaction().
2886 * We do it this way because it's not convenient to change memory context,
2887 * resource owner, etc while executing inside a Portal.
2890 PrepareTransactionBlock(char *gid)
2895 /* Set up to commit the current transaction */
2896 result = EndTransactionBlock();
2898 /* If successful, change outer tblock state to PREPARE */
2901 s = CurrentTransactionState;
2903 while (s->parent != NULL)
2906 if (s->blockState == TBLOCK_END)
2908 /* Save GID where PrepareTransaction can find it again */
2909 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2911 s->blockState = TBLOCK_PREPARE;
2916 * ignore case where we are not in a transaction;
2917 * EndTransactionBlock already issued a warning.
2919 Assert(s->blockState == TBLOCK_STARTED);
2920 /* Don't send back a PREPARE result tag... */
2929 * EndTransactionBlock
2930 * This executes a COMMIT command.
2932 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2933 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2935 * Note that we don't actually do anything here except change blockState.
2936 * The real work will be done in the upcoming CommitTransactionCommand().
2937 * We do it this way because it's not convenient to change memory context,
2938 * resource owner, etc while executing inside a Portal.
2941 EndTransactionBlock(void)
2943 TransactionState s = CurrentTransactionState;
2944 bool result = false;
2946 switch (s->blockState)
2949 * We are in a transaction block, so tell CommitTransactionCommand
2952 case TBLOCK_INPROGRESS:
2953 s->blockState = TBLOCK_END;
2958 * We are in a failed transaction block. Tell
2959 * CommitTransactionCommand it's time to exit the block.
2962 s->blockState = TBLOCK_ABORT_END;
2966 * We are in a live subtransaction block. Set up to subcommit all
2967 * open subtransactions and then commit the main transaction.
2969 case TBLOCK_SUBINPROGRESS:
2970 while (s->parent != NULL)
2972 if (s->blockState == TBLOCK_SUBINPROGRESS)
2973 s->blockState = TBLOCK_SUBEND;
2975 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2976 BlockStateAsString(s->blockState));
2979 if (s->blockState == TBLOCK_INPROGRESS)
2980 s->blockState = TBLOCK_END;
2982 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2983 BlockStateAsString(s->blockState));
2988 * Here we are inside an aborted subtransaction. Treat the COMMIT
2989 * as ROLLBACK: set up to abort everything and exit the main
2992 case TBLOCK_SUBABORT:
2993 while (s->parent != NULL)
2995 if (s->blockState == TBLOCK_SUBINPROGRESS)
2996 s->blockState = TBLOCK_SUBABORT_PENDING;
2997 else if (s->blockState == TBLOCK_SUBABORT)
2998 s->blockState = TBLOCK_SUBABORT_END;
3000 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3001 BlockStateAsString(s->blockState));
3004 if (s->blockState == TBLOCK_INPROGRESS)
3005 s->blockState = TBLOCK_ABORT_PENDING;
3006 else if (s->blockState == TBLOCK_ABORT)
3007 s->blockState = TBLOCK_ABORT_END;
3009 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3010 BlockStateAsString(s->blockState));
3014 * The user issued COMMIT when not inside a transaction. Issue a
3015 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
3016 * CommitTransactionCommand() will then close the transaction and
3017 * put us back into the default state.
3019 case TBLOCK_STARTED:
3021 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3022 errmsg("there is no transaction in progress")));
3026 /* These cases are invalid. */
3027 case TBLOCK_DEFAULT:
3029 case TBLOCK_SUBBEGIN:
3032 case TBLOCK_ABORT_END:
3033 case TBLOCK_SUBABORT_END:
3034 case TBLOCK_ABORT_PENDING:
3035 case TBLOCK_SUBABORT_PENDING:
3036 case TBLOCK_SUBRESTART:
3037 case TBLOCK_SUBABORT_RESTART:
3038 case TBLOCK_PREPARE:
3039 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3040 BlockStateAsString(s->blockState));
3048 * UserAbortTransactionBlock
3049 * This executes a ROLLBACK command.
3051 * As above, we don't actually do anything here except change blockState.
3054 UserAbortTransactionBlock(void)
3056 TransactionState s = CurrentTransactionState;
3058 switch (s->blockState)
3061 * We are inside a transaction block and we got a ROLLBACK command
3062 * from the user, so tell CommitTransactionCommand to abort and
3063 * exit the transaction block.
3065 case TBLOCK_INPROGRESS:
3066 s->blockState = TBLOCK_ABORT_PENDING;
3070 * We are inside a failed transaction block and we got a ROLLBACK
3071 * command from the user. Abort processing is already done, so
3072 * CommitTransactionCommand just has to cleanup and go back to
3076 s->blockState = TBLOCK_ABORT_END;
3080 * We are inside a subtransaction. Mark everything up to top
3081 * level as exitable.
3083 case TBLOCK_SUBINPROGRESS:
3084 case TBLOCK_SUBABORT:
3085 while (s->parent != NULL)
3087 if (s->blockState == TBLOCK_SUBINPROGRESS)
3088 s->blockState = TBLOCK_SUBABORT_PENDING;
3089 else if (s->blockState == TBLOCK_SUBABORT)
3090 s->blockState = TBLOCK_SUBABORT_END;
3092 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3093 BlockStateAsString(s->blockState));
3096 if (s->blockState == TBLOCK_INPROGRESS)
3097 s->blockState = TBLOCK_ABORT_PENDING;
3098 else if (s->blockState == TBLOCK_ABORT)
3099 s->blockState = TBLOCK_ABORT_END;
3101 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3102 BlockStateAsString(s->blockState));
3106 * The user issued ABORT when not inside a transaction. Issue a
3107 * WARNING and go to abort state. The upcoming call to
3108 * CommitTransactionCommand() will then put us back into the
3111 case TBLOCK_STARTED:
3113 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3114 errmsg("there is no transaction in progress")));
3115 s->blockState = TBLOCK_ABORT_PENDING;
3118 /* These cases are invalid. */
3119 case TBLOCK_DEFAULT:
3121 case TBLOCK_SUBBEGIN:
3124 case TBLOCK_ABORT_END:
3125 case TBLOCK_SUBABORT_END:
3126 case TBLOCK_ABORT_PENDING:
3127 case TBLOCK_SUBABORT_PENDING:
3128 case TBLOCK_SUBRESTART:
3129 case TBLOCK_SUBABORT_RESTART:
3130 case TBLOCK_PREPARE:
3131 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3132 BlockStateAsString(s->blockState));
3139 * This executes a SAVEPOINT command.
3142 DefineSavepoint(char *name)
3144 TransactionState s = CurrentTransactionState;
3146 switch (s->blockState)
3148 case TBLOCK_INPROGRESS:
3149 case TBLOCK_SUBINPROGRESS:
3150 /* Normal subtransaction start */
3152 s = CurrentTransactionState; /* changed by push */
3155 * Savepoint names, like the TransactionState block itself, live
3156 * in TopTransactionContext.
3159 s->name = MemoryContextStrdup(TopTransactionContext, name);
3162 /* These cases are invalid. */
3163 case TBLOCK_DEFAULT:
3164 case TBLOCK_STARTED:
3166 case TBLOCK_SUBBEGIN:
3170 case TBLOCK_SUBABORT:
3171 case TBLOCK_ABORT_END:
3172 case TBLOCK_SUBABORT_END:
3173 case TBLOCK_ABORT_PENDING:
3174 case TBLOCK_SUBABORT_PENDING:
3175 case TBLOCK_SUBRESTART:
3176 case TBLOCK_SUBABORT_RESTART:
3177 case TBLOCK_PREPARE:
3178 elog(FATAL, "DefineSavepoint: unexpected state %s",
3179 BlockStateAsString(s->blockState));
3186 * This executes a RELEASE command.
3188 * As above, we don't actually do anything here except change blockState.
3191 ReleaseSavepoint(List *options)
3193 TransactionState s = CurrentTransactionState;
3194 TransactionState target,
3199 switch (s->blockState)
3202 * We can't rollback to a savepoint if there is no savepoint
3205 case TBLOCK_INPROGRESS:
3207 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3208 errmsg("no such savepoint")));
3212 * We are in a non-aborted subtransaction. This is the only valid
3215 case TBLOCK_SUBINPROGRESS:
3218 /* These cases are invalid. */
3219 case TBLOCK_DEFAULT:
3220 case TBLOCK_STARTED:
3222 case TBLOCK_SUBBEGIN:
3226 case TBLOCK_SUBABORT:
3227 case TBLOCK_ABORT_END:
3228 case TBLOCK_SUBABORT_END:
3229 case TBLOCK_ABORT_PENDING:
3230 case TBLOCK_SUBABORT_PENDING:
3231 case TBLOCK_SUBRESTART:
3232 case TBLOCK_SUBABORT_RESTART:
3233 case TBLOCK_PREPARE:
3234 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3235 BlockStateAsString(s->blockState));
3239 foreach(cell, options)
3241 DefElem *elem = lfirst(cell);
3243 if (strcmp(elem->defname, "savepoint_name") == 0)
3244 name = strVal(elem->arg);
3247 Assert(PointerIsValid(name));
3249 for (target = s; PointerIsValid(target); target = target->parent)
3251 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3255 if (!PointerIsValid(target))
3257 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3258 errmsg("no such savepoint")));
3260 /* disallow crossing savepoint level boundaries */
3261 if (target->savepointLevel != s->savepointLevel)
3263 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3264 errmsg("no such savepoint")));
3267 * Mark "commit pending" all subtransactions up to the target
3268 * subtransaction. The actual commits will happen when control gets to
3269 * CommitTransactionCommand.
3271 xact = CurrentTransactionState;
3274 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3275 xact->blockState = TBLOCK_SUBEND;
3278 xact = xact->parent;
3279 Assert(PointerIsValid(xact));
3284 * RollbackToSavepoint
3285 * This executes a ROLLBACK TO <savepoint> command.
3287 * As above, we don't actually do anything here except change blockState.
3290 RollbackToSavepoint(List *options)
3292 TransactionState s = CurrentTransactionState;
3293 TransactionState target,
3298 switch (s->blockState)
3301 * We can't rollback to a savepoint if there is no savepoint
3304 case TBLOCK_INPROGRESS:
3307 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3308 errmsg("no such savepoint")));
3312 * There is at least one savepoint, so proceed.
3314 case TBLOCK_SUBINPROGRESS:
3315 case TBLOCK_SUBABORT:
3318 /* These cases are invalid. */
3319 case TBLOCK_DEFAULT:
3320 case TBLOCK_STARTED:
3322 case TBLOCK_SUBBEGIN:
3325 case TBLOCK_ABORT_END:
3326 case TBLOCK_SUBABORT_END:
3327 case TBLOCK_ABORT_PENDING:
3328 case TBLOCK_SUBABORT_PENDING:
3329 case TBLOCK_SUBRESTART:
3330 case TBLOCK_SUBABORT_RESTART:
3331 case TBLOCK_PREPARE:
3332 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3333 BlockStateAsString(s->blockState));
3337 foreach(cell, options)
3339 DefElem *elem = lfirst(cell);
3341 if (strcmp(elem->defname, "savepoint_name") == 0)
3342 name = strVal(elem->arg);
3345 Assert(PointerIsValid(name));
3347 for (target = s; PointerIsValid(target); target = target->parent)
3349 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3353 if (!PointerIsValid(target))
3355 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3356 errmsg("no such savepoint")));
3358 /* disallow crossing savepoint level boundaries */
3359 if (target->savepointLevel != s->savepointLevel)
3361 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3362 errmsg("no such savepoint")));
3365 * Mark "abort pending" all subtransactions up to the target
3366 * subtransaction. The actual aborts will happen when control gets to
3367 * CommitTransactionCommand.
3369 xact = CurrentTransactionState;
3374 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3375 xact->blockState = TBLOCK_SUBABORT_PENDING;
3376 else if (xact->blockState == TBLOCK_SUBABORT)
3377 xact->blockState = TBLOCK_SUBABORT_END;
3379 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3380 BlockStateAsString(xact->blockState));
3381 xact = xact->parent;
3382 Assert(PointerIsValid(xact));
3385 /* And mark the target as "restart pending" */
3386 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3387 xact->blockState = TBLOCK_SUBRESTART;
3388 else if (xact->blockState == TBLOCK_SUBABORT)
3389 xact->blockState = TBLOCK_SUBABORT_RESTART;
3391 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3392 BlockStateAsString(xact->blockState));
3396 * BeginInternalSubTransaction
3397 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3398 * TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3399 * used in functions that might be called when not inside a BEGIN block
3400 * or when running deferred triggers at COMMIT/PREPARE time. Also, it
3401 * automatically does CommitTransactionCommand/StartTransactionCommand
3402 * instead of expecting the caller to do it.
3405 BeginInternalSubTransaction(char *name)
3407 TransactionState s = CurrentTransactionState;
3409 switch (s->blockState)
3411 case TBLOCK_STARTED:
3412 case TBLOCK_INPROGRESS:
3414 case TBLOCK_PREPARE:
3415 case TBLOCK_SUBINPROGRESS:
3416 /* Normal subtransaction start */
3418 s = CurrentTransactionState; /* changed by push */
3421 * Savepoint names, like the TransactionState block itself, live
3422 * in TopTransactionContext.
3425 s->name = MemoryContextStrdup(TopTransactionContext, name);
3428 /* These cases are invalid. */
3429 case TBLOCK_DEFAULT:
3431 case TBLOCK_SUBBEGIN:
3434 case TBLOCK_SUBABORT:
3435 case TBLOCK_ABORT_END:
3436 case TBLOCK_SUBABORT_END:
3437 case TBLOCK_ABORT_PENDING:
3438 case TBLOCK_SUBABORT_PENDING:
3439 case TBLOCK_SUBRESTART:
3440 case TBLOCK_SUBABORT_RESTART:
3441 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3442 BlockStateAsString(s->blockState));
3446 CommitTransactionCommand();
3447 StartTransactionCommand();
3451 * ReleaseCurrentSubTransaction
3453 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3454 * savepoint name (if any).
3455 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3458 ReleaseCurrentSubTransaction(void)
3460 TransactionState s = CurrentTransactionState;
3462 if (s->blockState != TBLOCK_SUBINPROGRESS)
3463 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3464 BlockStateAsString(s->blockState));
3465 Assert(s->state == TRANS_INPROGRESS);
3466 MemoryContextSwitchTo(CurTransactionContext);
3467 CommitSubTransaction();
3468 s = CurrentTransactionState; /* changed by pop */
3469 Assert(s->state == TRANS_INPROGRESS);
3473 * RollbackAndReleaseCurrentSubTransaction
3475 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3476 * of its savepoint name (if any).
3477 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3480 RollbackAndReleaseCurrentSubTransaction(void)
3482 TransactionState s = CurrentTransactionState;
3484 switch (s->blockState)
3486 /* Must be in a subtransaction */
3487 case TBLOCK_SUBINPROGRESS:
3488 case TBLOCK_SUBABORT:
3491 /* These cases are invalid. */
3492 case TBLOCK_DEFAULT:
3493 case TBLOCK_STARTED:
3495 case TBLOCK_SUBBEGIN:
3496 case TBLOCK_INPROGRESS:
3500 case TBLOCK_ABORT_END:
3501 case TBLOCK_SUBABORT_END:
3502 case TBLOCK_ABORT_PENDING:
3503 case TBLOCK_SUBABORT_PENDING:
3504 case TBLOCK_SUBRESTART:
3505 case TBLOCK_SUBABORT_RESTART:
3506 case TBLOCK_PREPARE:
3507 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3508 BlockStateAsString(s->blockState));
3513 * Abort the current subtransaction, if needed.
3515 if (s->blockState == TBLOCK_SUBINPROGRESS)
3516 AbortSubTransaction();
3518 /* And clean it up, too */
3519 CleanupSubTransaction();
3521 s = CurrentTransactionState; /* changed by pop */
3522 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3523 s->blockState == TBLOCK_INPROGRESS ||
3524 s->blockState == TBLOCK_STARTED);
3528 * AbortOutOfAnyTransaction
3530 * This routine is provided for error recovery purposes. It aborts any
3531 * active transaction or transaction block, leaving the system in a known
3535 AbortOutOfAnyTransaction(void)
3537 TransactionState s = CurrentTransactionState;
3540 * Get out of any transaction or nested transaction
3544 switch (s->blockState)
3546 case TBLOCK_DEFAULT:
3547 /* Not in a transaction, do nothing */
3549 case TBLOCK_STARTED:
3551 case TBLOCK_INPROGRESS:
3553 case TBLOCK_ABORT_PENDING:
3554 case TBLOCK_PREPARE:
3555 /* In a transaction, so clean up */
3557 CleanupTransaction();
3558 s->blockState = TBLOCK_DEFAULT;
3561 case TBLOCK_ABORT_END:
3562 /* AbortTransaction already done, still need Cleanup */
3563 CleanupTransaction();
3564 s->blockState = TBLOCK_DEFAULT;
3568 * In a subtransaction, so clean it up and abort parent too
3570 case TBLOCK_SUBBEGIN:
3571 case TBLOCK_SUBINPROGRESS:
3573 case TBLOCK_SUBABORT_PENDING:
3574 case TBLOCK_SUBRESTART:
3575 AbortSubTransaction();
3576 CleanupSubTransaction();
3577 s = CurrentTransactionState; /* changed by pop */
3580 case TBLOCK_SUBABORT:
3581 case TBLOCK_SUBABORT_END:
3582 case TBLOCK_SUBABORT_RESTART:
3583 /* As above, but AbortSubTransaction already done */
3584 CleanupSubTransaction();
3585 s = CurrentTransactionState; /* changed by pop */
3588 } while (s->blockState != TBLOCK_DEFAULT);
3590 /* Should be out of all subxacts now */
3591 Assert(s->parent == NULL);
3595 * IsTransactionBlock --- are we within a transaction block?
3598 IsTransactionBlock(void)
3600 TransactionState s = CurrentTransactionState;
3602 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3609 * IsTransactionOrTransactionBlock --- are we within either a transaction
3610 * or a transaction block? (The backend is only really "idle" when this
3613 * This should match up with IsTransactionBlock and IsTransactionState.
3616 IsTransactionOrTransactionBlock(void)
3618 TransactionState s = CurrentTransactionState;
3620 if (s->blockState == TBLOCK_DEFAULT)
3627 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3630 TransactionBlockStatusCode(void)
3632 TransactionState s = CurrentTransactionState;
3634 switch (s->blockState)
3636 case TBLOCK_DEFAULT:
3637 case TBLOCK_STARTED:
3638 return 'I'; /* idle --- not in transaction */
3640 case TBLOCK_SUBBEGIN:
3641 case TBLOCK_INPROGRESS:
3642 case TBLOCK_SUBINPROGRESS:
3645 case TBLOCK_PREPARE:
3646 return 'T'; /* in transaction */
3648 case TBLOCK_SUBABORT:
3649 case TBLOCK_ABORT_END:
3650 case TBLOCK_SUBABORT_END:
3651 case TBLOCK_ABORT_PENDING:
3652 case TBLOCK_SUBABORT_PENDING:
3653 case TBLOCK_SUBRESTART:
3654 case TBLOCK_SUBABORT_RESTART:
3655 return 'E'; /* in failed transaction */
3658 /* should never get here */
3659 elog(FATAL, "invalid transaction block state: %s",
3660 BlockStateAsString(s->blockState));
3661 return 0; /* keep compiler quiet */
3668 IsSubTransaction(void)
3670 TransactionState s = CurrentTransactionState;
3672 if (s->nestingLevel >= 2)
3679 * StartSubTransaction
3681 * If you're wondering why this is separate from PushTransaction: it's because
3682 * we can't conveniently do this stuff right inside DefineSavepoint. The
3683 * SAVEPOINT utility command will be executed inside a Portal, and if we
3684 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3685 * the Portal will undo those settings. So we make DefineSavepoint just
3686 * push a dummy transaction block, and when control returns to the main
3687 * idle loop, CommitTransactionCommand will be called, and we'll come here
3688 * to finish starting the subtransaction.
3691 StartSubTransaction(void)
3693 TransactionState s = CurrentTransactionState;
3695 if (s->state != TRANS_DEFAULT)
3696 elog(WARNING, "StartSubTransaction while in %s state",
3697 TransStateAsString(s->state));
3699 s->state = TRANS_START;
3702 * Initialize subsystems for new subtransaction
3704 * must initialize resource-management stuff first
3706 AtSubStart_Memory();
3707 AtSubStart_ResourceOwner();
3709 AtSubStart_Notify();
3710 AfterTriggerBeginSubXact();
3712 s->state = TRANS_INPROGRESS;
3715 * Call start-of-subxact callbacks
3717 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3718 s->parent->subTransactionId);
3720 ShowTransactionState("StartSubTransaction");
3724 * CommitSubTransaction
3726 * The caller has to make sure to always reassign CurrentTransactionState
3727 * if it has a local pointer to it after calling this function.
3730 CommitSubTransaction(void)
3732 TransactionState s = CurrentTransactionState;
3734 ShowTransactionState("CommitSubTransaction");
3736 if (s->state != TRANS_INPROGRESS)
3737 elog(WARNING, "CommitSubTransaction while in %s state",
3738 TransStateAsString(s->state));
3740 /* Pre-commit processing goes here -- nothing to do at the moment */
3742 s->state = TRANS_COMMIT;
3744 /* Must CCI to ensure commands of subtransaction are seen as done */
3745 CommandCounterIncrement();
3747 /* Mark subtransaction as subcommitted */
3748 if (TransactionIdIsValid(s->transactionId))
3750 RecordSubTransactionCommit();
3751 AtSubCommit_childXids();
3754 /* Post-commit cleanup */
3755 AfterTriggerEndSubXact(true);
3756 AtSubCommit_Portals(s->subTransactionId,
3757 s->parent->subTransactionId,
3758 s->parent->curTransactionOwner);
3759 AtEOSubXact_LargeObject(true, s->subTransactionId,
3760 s->parent->subTransactionId);
3761 AtSubCommit_Notify();
3762 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3763 s->parent->subTransactionId);
3765 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3766 s->parent->subTransactionId);
3768 ResourceOwnerRelease(s->curTransactionOwner,
3769 RESOURCE_RELEASE_BEFORE_LOCKS,
3771 AtEOSubXact_RelationCache(true, s->subTransactionId,
3772 s->parent->subTransactionId);
3773 AtEOSubXact_Inval(true);
3777 * The only lock we actually release here is the subtransaction XID lock.
3778 * The rest just get transferred to the parent resource owner.
3780 CurrentResourceOwner = s->curTransactionOwner;
3781 if (TransactionIdIsValid(s->transactionId))
3782 XactLockTableDelete(s->transactionId);
3784 ResourceOwnerRelease(s->curTransactionOwner,
3785 RESOURCE_RELEASE_LOCKS,
3787 ResourceOwnerRelease(s->curTransactionOwner,
3788 RESOURCE_RELEASE_AFTER_LOCKS,
3791 AtEOXact_GUC(true, true);
3792 AtEOSubXact_SPI(true, s->subTransactionId);
3793 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3794 s->parent->subTransactionId);
3795 AtEOSubXact_Namespace(true, s->subTransactionId,
3796 s->parent->subTransactionId);
3797 AtEOSubXact_Files(true, s->subTransactionId,
3798 s->parent->subTransactionId);
3799 AtEOSubXact_HashTables(true, s->nestingLevel);
3800 AtEOSubXact_PgStat(true, s->nestingLevel);
3803 * We need to restore the upper transaction's read-only state, in case the
3804 * upper is read-write while the child is read-only; GUC will incorrectly
3805 * think it should leave the child state in place.
3807 XactReadOnly = s->prevXactReadOnly;
3809 CurrentResourceOwner = s->parent->curTransactionOwner;
3810 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3811 ResourceOwnerDelete(s->curTransactionOwner);
3812 s->curTransactionOwner = NULL;
3814 AtSubCommit_Memory();
3816 s->state = TRANS_DEFAULT;
3822 * AbortSubTransaction
3825 AbortSubTransaction(void)
3827 TransactionState s = CurrentTransactionState;
3829 /* Prevent cancel/die interrupt while cleaning up */
3832 /* Make sure we have a valid memory context and resource owner */
3833 AtSubAbort_Memory();
3834 AtSubAbort_ResourceOwner();
3837 * Release any LW locks we might be holding as quickly as possible.
3838 * (Regular locks, however, must be held till we finish aborting.)
3839 * Releasing LW locks is critical since we might try to grab them again
3840 * while cleaning up!
3842 * FIXME This may be incorrect --- Are there some locks we should keep?
3843 * Buffer locks, for example? I don't think so but I'm not sure.
3853 * check the current transaction state
3855 ShowTransactionState("AbortSubTransaction");
3857 if (s->state != TRANS_INPROGRESS)
3858 elog(WARNING, "AbortSubTransaction while in %s state",
3859 TransStateAsString(s->state));
3861 s->state = TRANS_ABORT;
3864 * We can skip all this stuff if the subxact failed before creating a
3867 if (s->curTransactionOwner)
3869 AfterTriggerEndSubXact(false);
3870 AtSubAbort_Portals(s->subTransactionId,
3871 s->parent->subTransactionId,
3872 s->parent->curTransactionOwner);
3873 AtEOSubXact_LargeObject(false, s->subTransactionId,
3874 s->parent->subTransactionId);
3875 AtSubAbort_Notify();
3876 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3877 s->parent->subTransactionId);
3879 /* Advertise the fact that we aborted in pg_clog. */
3880 if (TransactionIdIsValid(s->transactionId))
3882 RecordSubTransactionAbort();
3883 AtSubAbort_childXids();
3886 /* Post-abort cleanup */
3887 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3888 s->parent->subTransactionId);
3890 ResourceOwnerRelease(s->curTransactionOwner,
3891 RESOURCE_RELEASE_BEFORE_LOCKS,
3893 AtEOSubXact_RelationCache(false, s->subTransactionId,
3894 s->parent->subTransactionId);
3895 AtEOSubXact_Inval(false);
3897 ResourceOwnerRelease(s->curTransactionOwner,
3898 RESOURCE_RELEASE_LOCKS,
3900 ResourceOwnerRelease(s->curTransactionOwner,
3901 RESOURCE_RELEASE_AFTER_LOCKS,
3904 AtEOXact_GUC(false, true);
3905 AtEOSubXact_SPI(false, s->subTransactionId);
3906 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3907 s->parent->subTransactionId);
3908 AtEOSubXact_Namespace(false, s->subTransactionId,
3909 s->parent->subTransactionId);
3910 AtEOSubXact_Files(false, s->subTransactionId,
3911 s->parent->subTransactionId);
3912 AtEOSubXact_HashTables(false, s->nestingLevel);
3913 AtEOSubXact_PgStat(false, s->nestingLevel);
3917 * Reset user id which might have been changed transiently. Here we want
3918 * to restore to the userid that was current at subxact entry. (As in
3919 * AbortTransaction, we need not worry about the session userid.)
3921 * Must do this after AtEOXact_GUC to handle the case where we entered the
3922 * subxact inside a SECURITY DEFINER function (hence current and session
3923 * userids were different) and then session auth was changed inside the
3924 * subxact. GUC will reset both current and session userids to the
3925 * entry-time session userid. This is right in every other scenario so it
3926 * seems simplest to let GUC do that and fix it here.
3928 SetUserId(s->currentUser);
3931 * Restore the upper transaction's read-only state, too. This should be
3932 * redundant with GUC's cleanup but we may as well do it for consistency
3933 * with the commit case.
3935 XactReadOnly = s->prevXactReadOnly;
3937 RESUME_INTERRUPTS();
3941 * CleanupSubTransaction
3943 * The caller has to make sure to always reassign CurrentTransactionState
3944 * if it has a local pointer to it after calling this function.
3947 CleanupSubTransaction(void)
3949 TransactionState s = CurrentTransactionState;
3951 ShowTransactionState("CleanupSubTransaction");
3953 if (s->state != TRANS_ABORT)
3954 elog(WARNING, "CleanupSubTransaction while in %s state",
3955 TransStateAsString(s->state));
3957 AtSubCleanup_Portals(s->subTransactionId);
3959 CurrentResourceOwner = s->parent->curTransactionOwner;
3960 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3961 if (s->curTransactionOwner)
3962 ResourceOwnerDelete(s->curTransactionOwner);
3963 s->curTransactionOwner = NULL;
3965 AtSubCleanup_Memory();
3967 s->state = TRANS_DEFAULT;
3974 * Create transaction state stack entry for a subtransaction
3976 * The caller has to make sure to always reassign CurrentTransactionState
3977 * if it has a local pointer to it after calling this function.
3980 PushTransaction(void)
3982 TransactionState p = CurrentTransactionState;
3987 * At present, GetUserId cannot fail, but let's not assume that. Get the
3988 * ID before entering the critical code sequence.
3990 currentUser = GetUserId();
3993 * We keep subtransaction state nodes in TopTransactionContext.
3995 s = (TransactionState)
3996 MemoryContextAllocZero(TopTransactionContext,
3997 sizeof(TransactionStateData));
4000 * Assign a subtransaction ID, watching out for counter wraparound.
4002 currentSubTransactionId += 1;
4003 if (currentSubTransactionId == InvalidSubTransactionId)
4005 currentSubTransactionId -= 1;
4008 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4009 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
4013 * We can now stack a minimally valid subtransaction without fear of
4016 s->transactionId = InvalidTransactionId; /* until assigned */
4017 s->subTransactionId = currentSubTransactionId;
4019 s->nestingLevel = p->nestingLevel + 1;
4020 s->savepointLevel = p->savepointLevel;
4021 s->state = TRANS_DEFAULT;
4022 s->blockState = TBLOCK_SUBBEGIN;
4023 s->currentUser = currentUser;
4024 s->prevXactReadOnly = XactReadOnly;
4026 CurrentTransactionState = s;
4029 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
4030 * with the subtransaction from here on out; in particular they should not
4031 * assume that it necessarily has a transaction context, resource owner,
4038 * Pop back to parent transaction state
4040 * The caller has to make sure to always reassign CurrentTransactionState
4041 * if it has a local pointer to it after calling this function.
4044 PopTransaction(void)
4046 TransactionState s = CurrentTransactionState;
4048 if (s->state != TRANS_DEFAULT)
4049 elog(WARNING, "PopTransaction while in %s state",
4050 TransStateAsString(s->state));
4052 if (s->parent == NULL)
4053 elog(FATAL, "PopTransaction with no parent");
4055 CurrentTransactionState = s->parent;
4057 /* Let's just make sure CurTransactionContext is good */
4058 CurTransactionContext = s->parent->curTransactionContext;
4059 MemoryContextSwitchTo(CurTransactionContext);
4061 /* Ditto for ResourceOwner links */
4062 CurTransactionResourceOwner = s->parent->curTransactionOwner;
4063 CurrentResourceOwner = s->parent->curTransactionOwner;
4065 /* Free the old child structure */
4072 * ShowTransactionState
4076 ShowTransactionState(const char *str)
4078 /* skip work if message will definitely not be printed */
4079 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
4081 elog(DEBUG3, "%s", str);
4082 ShowTransactionStateRec(CurrentTransactionState);
4087 * ShowTransactionStateRec
4088 * Recursive subroutine for ShowTransactionState
4091 ShowTransactionStateRec(TransactionState s)
4094 ShowTransactionStateRec(s->parent);
4096 /* use ereport to suppress computation if msg will not be printed */
4098 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
4099 PointerIsValid(s->name) ? s->name : "unnamed",
4100 BlockStateAsString(s->blockState),
4101 TransStateAsString(s->state),
4102 (unsigned int) s->transactionId,
4103 (unsigned int) s->subTransactionId,
4104 (unsigned int) currentCommandId,
4106 nodeToString(s->childXids))));
4110 * BlockStateAsString
4114 BlockStateAsString(TBlockState blockState)
4118 case TBLOCK_DEFAULT:
4120 case TBLOCK_STARTED:
4124 case TBLOCK_INPROGRESS:
4125 return "INPROGRESS";
4130 case TBLOCK_ABORT_END:
4132 case TBLOCK_ABORT_PENDING:
4133 return "ABORT PEND";
4134 case TBLOCK_PREPARE:
4136 case TBLOCK_SUBBEGIN:
4138 case TBLOCK_SUBINPROGRESS:
4139 return "SUB INPROGRS";
4142 case TBLOCK_SUBABORT:
4144 case TBLOCK_SUBABORT_END:
4145 return "SUB ABORT END";
4146 case TBLOCK_SUBABORT_PENDING:
4147 return "SUB ABRT PEND";
4148 case TBLOCK_SUBRESTART:
4149 return "SUB RESTART";
4150 case TBLOCK_SUBABORT_RESTART:
4151 return "SUB AB RESTRT";
4153 return "UNRECOGNIZED";
4157 * TransStateAsString
4161 TransStateAsString(TransState state)
4169 case TRANS_INPROGRESS:
4178 return "UNRECOGNIZED";
4182 * xactGetCommittedChildren
4184 * Gets the list of committed children of the current transaction. The return
4185 * value is the number of child transactions. *children is set to point to a
4186 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4190 xactGetCommittedChildren(TransactionId **ptr)
4192 TransactionState s = CurrentTransactionState;
4194 TransactionId *children;
4197 nchildren = list_length(s->childXids);
4204 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4207 foreach(p, s->childXids)
4209 TransactionId child = lfirst_xid(p);
4211 *children++ = child;
4218 * XLOG support routines
4222 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4224 TransactionId *sub_xids;
4225 TransactionId max_xid;
4228 TransactionIdCommit(xid);
4230 /* Mark committed subtransactions as committed */
4231 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4232 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4234 /* Make sure nextXid is beyond any XID mentioned in the record */
4236 for (i = 0; i < xlrec->nsubxacts; i++)
4238 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4239 max_xid = sub_xids[i];
4241 if (TransactionIdFollowsOrEquals(max_xid,
4242 ShmemVariableCache->nextXid))
4244 ShmemVariableCache->nextXid = max_xid;
4245 TransactionIdAdvance(ShmemVariableCache->nextXid);
4248 /* Make sure files supposed to be dropped are dropped */
4249 for (i = 0; i < xlrec->nrels; i++)
4251 XLogDropRelation(xlrec->xnodes[i]);
4252 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4257 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4259 TransactionId *sub_xids;
4260 TransactionId max_xid;
4263 TransactionIdAbort(xid);
4265 /* Mark subtransactions as aborted */
4266 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4267 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4269 /* Make sure nextXid is beyond any XID mentioned in the record */
4271 for (i = 0; i < xlrec->nsubxacts; i++)
4273 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4274 max_xid = sub_xids[i];
4276 if (TransactionIdFollowsOrEquals(max_xid,
4277 ShmemVariableCache->nextXid))
4279 ShmemVariableCache->nextXid = max_xid;
4280 TransactionIdAdvance(ShmemVariableCache->nextXid);
4283 /* Make sure files supposed to be dropped are dropped */
4284 for (i = 0; i < xlrec->nrels; i++)
4286 XLogDropRelation(xlrec->xnodes[i]);
4287 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4292 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4294 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4296 if (info == XLOG_XACT_COMMIT)
4298 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4300 xact_redo_commit(xlrec, record->xl_xid);
4302 else if (info == XLOG_XACT_ABORT)
4304 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4306 xact_redo_abort(xlrec, record->xl_xid);
4308 else if (info == XLOG_XACT_PREPARE)
4310 /* the record contents are exactly the 2PC file */
4311 RecreateTwoPhaseFile(record->xl_xid,
4312 XLogRecGetData(record), record->xl_len);
4314 else if (info == XLOG_XACT_COMMIT_PREPARED)
4316 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4318 xact_redo_commit(&xlrec->crec, xlrec->xid);
4319 RemoveTwoPhaseFile(xlrec->xid, false);
4321 else if (info == XLOG_XACT_ABORT_PREPARED)
4323 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4325 xact_redo_abort(&xlrec->arec, xlrec->xid);
4326 RemoveTwoPhaseFile(xlrec->xid, false);
4329 elog(PANIC, "xact_redo: unknown op code %u", info);
4333 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4337 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4338 if (xlrec->nrels > 0)
4340 appendStringInfo(buf, "; rels:");
4341 for (i = 0; i < xlrec->nrels; i++)
4343 RelFileNode rnode = xlrec->xnodes[i];
4345 appendStringInfo(buf, " %u/%u/%u",
4346 rnode.spcNode, rnode.dbNode, rnode.relNode);
4349 if (xlrec->nsubxacts > 0)
4351 TransactionId *xacts = (TransactionId *)
4352 &xlrec->xnodes[xlrec->nrels];
4354 appendStringInfo(buf, "; subxacts:");
4355 for (i = 0; i < xlrec->nsubxacts; i++)
4356 appendStringInfo(buf, " %u", xacts[i]);
4361 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4365 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4366 if (xlrec->nrels > 0)
4368 appendStringInfo(buf, "; rels:");
4369 for (i = 0; i < xlrec->nrels; i++)
4371 RelFileNode rnode = xlrec->xnodes[i];
4373 appendStringInfo(buf, " %u/%u/%u",
4374 rnode.spcNode, rnode.dbNode, rnode.relNode);
4377 if (xlrec->nsubxacts > 0)
4379 TransactionId *xacts = (TransactionId *)
4380 &xlrec->xnodes[xlrec->nrels];
4382 appendStringInfo(buf, "; subxacts:");
4383 for (i = 0; i < xlrec->nsubxacts; i++)
4384 appendStringInfo(buf, " %u", xacts[i]);
4389 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4391 uint8 info = xl_info & ~XLR_INFO_MASK;
4393 if (info == XLOG_XACT_COMMIT)
4395 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4397 appendStringInfo(buf, "commit: ");
4398 xact_desc_commit(buf, xlrec);
4400 else if (info == XLOG_XACT_ABORT)
4402 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4404 appendStringInfo(buf, "abort: ");
4405 xact_desc_abort(buf, xlrec);
4407 else if (info == XLOG_XACT_PREPARE)
4409 appendStringInfo(buf, "prepare");
4411 else if (info == XLOG_XACT_COMMIT_PREPARED)
4413 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4415 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4416 xact_desc_commit(buf, &xlrec->crec);
4418 else if (info == XLOG_XACT_ABORT_PREPARED)
4420 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4422 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4423 xact_desc_abort(buf, &xlrec->arec);
4426 appendStringInfo(buf, "UNKNOWN");