1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.220 2006/04/25 00:25:17 momjian Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/twophase.h"
26 #include "access/xact.h"
27 #include "catalog/heap.h"
28 #include "catalog/index.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
36 #include "storage/fd.h"
37 #include "storage/proc.h"
38 #include "storage/procarray.h"
39 #include "storage/smgr.h"
40 #include "utils/flatfiles.h"
41 #include "utils/guc.h"
42 #include "utils/inval.h"
43 #include "utils/memutils.h"
44 #include "utils/portal.h"
45 #include "utils/relcache.h"
46 #include "utils/resowner.h"
51 * User-tweakable parameters
53 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
56 bool DefaultXactReadOnly = false;
59 int CommitDelay = 0; /* precommit delay in microseconds */
60 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
64 * transaction states - transaction state from server perspective
66 typedef enum TransState
77 * transaction block states - transaction state of client queries
79 * Note: the subtransaction states are used only for non-topmost
80 * transactions; the others appear only in the topmost transaction.
82 typedef enum TBlockState
84 /* not-in-transaction-block states */
85 TBLOCK_DEFAULT, /* idle */
86 TBLOCK_STARTED, /* running single-query transaction */
88 /* transaction block states */
89 TBLOCK_BEGIN, /* starting transaction block */
90 TBLOCK_INPROGRESS, /* live transaction */
91 TBLOCK_END, /* COMMIT received */
92 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
93 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
94 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
95 TBLOCK_PREPARE, /* live xact, PREPARE received */
97 /* subtransaction states */
98 TBLOCK_SUBBEGIN, /* starting a subtransaction */
99 TBLOCK_SUBINPROGRESS, /* live subtransaction */
100 TBLOCK_SUBEND, /* RELEASE received */
101 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
102 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
103 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
104 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
105 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
109 * transaction state structure
111 typedef struct TransactionStateData
113 TransactionId transactionId; /* my XID, or Invalid if none */
114 SubTransactionId subTransactionId; /* my subxact ID */
115 char *name; /* savepoint name, if any */
116 int savepointLevel; /* savepoint level */
117 TransState state; /* low-level state */
118 TBlockState blockState; /* high-level state */
119 int nestingLevel; /* nest depth */
120 MemoryContext curTransactionContext; /* my xact-lifetime context */
121 ResourceOwner curTransactionOwner; /* my query resources */
122 List *childXids; /* subcommitted child XIDs */
123 Oid currentUser; /* subxact start current_user */
124 bool prevXactReadOnly; /* entry-time xact r/o state */
125 struct TransactionStateData *parent; /* back link to parent */
126 } TransactionStateData;
128 typedef TransactionStateData *TransactionState;
131 * childXids is currently implemented as an Oid List, relying on the
132 * assumption that TransactionIds are no wider than Oid. We use these
133 * macros to provide some isolation in case that changes in the future.
135 #define lfirst_xid(lc) ((TransactionId) lfirst_oid(lc))
136 #define lappend_xid(list, datum) lappend_oid(list, (Oid) (datum))
139 * CurrentTransactionState always points to the current transaction state
140 * block. It will point to TopTransactionStateData when not in a
141 * transaction at all, or when in a top-level transaction.
143 static TransactionStateData TopTransactionStateData = {
144 0, /* transaction id */
145 0, /* subtransaction id */
146 NULL, /* savepoint name */
147 0, /* savepoint level */
148 TRANS_DEFAULT, /* transaction state */
149 TBLOCK_DEFAULT, /* transaction block state from the client
151 0, /* nesting level */
152 NULL, /* cur transaction context */
153 NULL, /* cur transaction resource owner */
154 NIL, /* subcommitted child Xids */
155 0, /* entry-time current userid */
156 false, /* entry-time xact r/o state */
157 NULL /* link to parent state block */
160 static TransactionState CurrentTransactionState = &TopTransactionStateData;
163 * The subtransaction ID and command ID assignment counters are global
164 * to a whole transaction, so we do not keep them in the state stack.
166 static SubTransactionId currentSubTransactionId;
167 static CommandId currentCommandId;
170 * This is the value of now(), ie, the transaction start time.
171 * This does not change as we enter and exit subtransactions, so we don't
172 * keep it inside the TransactionState stack.
174 static TimestampTz xactStartTimestamp;
175 static TimestampTz stmtStartTimestamp;
178 * GID to be used for preparing the current transaction. This is also
179 * global to a whole transaction, so we don't keep it in the state stack.
181 static char *prepareGID;
185 * List of add-on start- and end-of-xact callbacks
187 typedef struct XactCallbackItem
189 struct XactCallbackItem *next;
190 XactCallback callback;
194 static XactCallbackItem *Xact_callbacks = NULL;
197 * List of add-on start- and end-of-subxact callbacks
199 typedef struct SubXactCallbackItem
201 struct SubXactCallbackItem *next;
202 SubXactCallback callback;
204 } SubXactCallbackItem;
206 static SubXactCallbackItem *SubXact_callbacks = NULL;
209 /* local function prototypes */
210 static void AssignSubTransactionId(TransactionState s);
211 static void AbortTransaction(void);
212 static void AtAbort_Memory(void);
213 static void AtCleanup_Memory(void);
214 static void AtAbort_ResourceOwner(void);
215 static void AtCommit_LocalCache(void);
216 static void AtCommit_Memory(void);
217 static void AtStart_Cache(void);
218 static void AtStart_Memory(void);
219 static void AtStart_ResourceOwner(void);
220 static void CallXactCallbacks(XactEvent event);
221 static void CallSubXactCallbacks(SubXactEvent event,
222 SubTransactionId mySubid,
223 SubTransactionId parentSubid);
224 static void CleanupTransaction(void);
225 static void CommitTransaction(void);
226 static void RecordTransactionAbort(void);
227 static void StartTransaction(void);
229 static void RecordSubTransactionCommit(void);
230 static void StartSubTransaction(void);
231 static void CommitSubTransaction(void);
232 static void AbortSubTransaction(void);
233 static void CleanupSubTransaction(void);
234 static void PushTransaction(void);
235 static void PopTransaction(void);
237 static void AtSubAbort_Memory(void);
238 static void AtSubCleanup_Memory(void);
239 static void AtSubAbort_ResourceOwner(void);
240 static void AtSubCommit_Memory(void);
241 static void AtSubStart_Memory(void);
242 static void AtSubStart_ResourceOwner(void);
244 static void ShowTransactionState(const char *str);
245 static void ShowTransactionStateRec(TransactionState state);
246 static const char *BlockStateAsString(TBlockState blockState);
247 static const char *TransStateAsString(TransState state);
250 /* ----------------------------------------------------------------
251 * transaction state accessors
252 * ----------------------------------------------------------------
258 * This returns true if we are currently running a query
259 * within an executing transaction.
262 IsTransactionState(void)
264 TransactionState s = CurrentTransactionState;
272 case TRANS_INPROGRESS:
283 * Shouldn't get here, but lint is not happy without this...
289 * IsAbortedTransactionBlockState
291 * This returns true if we are currently running a query
292 * within an aborted transaction block.
295 IsAbortedTransactionBlockState(void)
297 TransactionState s = CurrentTransactionState;
299 if (s->blockState == TBLOCK_ABORT ||
300 s->blockState == TBLOCK_SUBABORT)
308 * GetTopTransactionId
310 * Get the ID of the main transaction, even if we are currently inside
314 GetTopTransactionId(void)
316 return TopTransactionStateData.transactionId;
321 * GetCurrentTransactionId
323 * We do not assign XIDs to subtransactions until/unless this is called.
324 * When we do assign an XID to a subtransaction, recursively make sure
325 * its parent has one as well (this maintains the invariant that a child
326 * transaction has an XID following its parent's).
329 GetCurrentTransactionId(void)
331 TransactionState s = CurrentTransactionState;
333 if (!TransactionIdIsValid(s->transactionId))
334 AssignSubTransactionId(s);
336 return s->transactionId;
340 AssignSubTransactionId(TransactionState s)
342 ResourceOwner currentOwner;
344 Assert(s->parent != NULL);
345 Assert(s->state == TRANS_INPROGRESS);
346 if (!TransactionIdIsValid(s->parent->transactionId))
347 AssignSubTransactionId(s->parent);
350 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
352 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
353 * shared storage other than PG_PROC; because if there's no room for it in
354 * PG_PROC, the subtrans entry is needed to ensure that other backends see
355 * the Xid as "running". See GetNewTransactionId.
357 s->transactionId = GetNewTransactionId(true);
359 SubTransSetParent(s->transactionId, s->parent->transactionId);
362 * Acquire lock on the transaction XID. (We assume this cannot block.) We
363 * have to be sure that the lock is assigned to the transaction's
366 currentOwner = CurrentResourceOwner;
369 CurrentResourceOwner = s->curTransactionOwner;
371 XactLockTableInsert(s->transactionId);
375 /* Ensure CurrentResourceOwner is restored on error */
376 CurrentResourceOwner = currentOwner;
380 CurrentResourceOwner = currentOwner;
385 * GetCurrentTransactionIdIfAny
387 * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
388 * if we are currently not in a transaction, or in a transaction or
389 * subtransaction that has not yet assigned itself an XID.
392 GetCurrentTransactionIdIfAny(void)
394 TransactionState s = CurrentTransactionState;
396 return s->transactionId;
401 * GetCurrentSubTransactionId
404 GetCurrentSubTransactionId(void)
406 TransactionState s = CurrentTransactionState;
408 return s->subTransactionId;
413 * GetCurrentCommandId
416 GetCurrentCommandId(void)
418 /* this is global to a transaction, not subtransaction-local */
419 return currentCommandId;
423 * GetCurrentTransactionStartTimestamp
426 GetCurrentTransactionStartTimestamp(void)
428 return xactStartTimestamp;
432 * GetCurrentStatementStartTimestamp
435 GetCurrentStatementStartTimestamp(void)
437 return stmtStartTimestamp;
441 * SetCurrentStatementStartTimestamp
444 SetCurrentStatementStartTimestamp(void)
446 stmtStartTimestamp = GetCurrentTimestamp();
450 * GetCurrentTransactionNestLevel
452 * Note: this will return zero when not inside any transaction, one when
453 * inside a top-level transaction, etc.
456 GetCurrentTransactionNestLevel(void)
458 TransactionState s = CurrentTransactionState;
460 return s->nestingLevel;
465 * TransactionIdIsCurrentTransactionId
468 TransactionIdIsCurrentTransactionId(TransactionId xid)
473 * We always say that BootstrapTransactionId is "not my transaction ID"
474 * even when it is (ie, during bootstrap). Along with the fact that
475 * transam.c always treats BootstrapTransactionId as already committed,
476 * this causes the tqual.c routines to see all tuples as committed, which
477 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
478 * it never updates or deletes them, so all tuples can be presumed good
481 if (xid == BootstrapTransactionId)
485 * We will return true for the Xid of the current subtransaction, any of
486 * its subcommitted children, any of its parents, or any of their
487 * previously subcommitted children. However, a transaction being aborted
488 * is no longer "current", even though it may still have an entry on the
491 for (s = CurrentTransactionState; s != NULL; s = s->parent)
495 if (s->state == TRANS_ABORT)
497 if (!TransactionIdIsValid(s->transactionId))
498 continue; /* it can't have any child XIDs either */
499 if (TransactionIdEquals(xid, s->transactionId))
501 foreach(cell, s->childXids)
503 if (TransactionIdEquals(xid, lfirst_xid(cell)))
513 * CommandCounterIncrement
516 CommandCounterIncrement(void)
518 currentCommandId += 1;
519 if (currentCommandId == FirstCommandId) /* check for overflow */
521 currentCommandId -= 1;
523 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
524 errmsg("cannot have more than 2^32-1 commands in a transaction")));
527 /* Propagate new command ID into static snapshots, if set */
528 if (SerializableSnapshot)
529 SerializableSnapshot->curcid = currentCommandId;
531 LatestSnapshot->curcid = currentCommandId;
534 * make cache changes visible to me.
536 AtCommit_LocalCache();
541 /* ----------------------------------------------------------------
542 * StartTransaction stuff
543 * ----------------------------------------------------------------
552 AcceptInvalidationMessages();
561 TransactionState s = CurrentTransactionState;
564 * We shouldn't have a transaction context already.
566 Assert(TopTransactionContext == NULL);
569 * Create a toplevel context for the transaction.
571 TopTransactionContext =
572 AllocSetContextCreate(TopMemoryContext,
573 "TopTransactionContext",
574 ALLOCSET_DEFAULT_MINSIZE,
575 ALLOCSET_DEFAULT_INITSIZE,
576 ALLOCSET_DEFAULT_MAXSIZE);
579 * In a top-level transaction, CurTransactionContext is the same as
580 * TopTransactionContext.
582 CurTransactionContext = TopTransactionContext;
583 s->curTransactionContext = CurTransactionContext;
585 /* Make the CurTransactionContext active. */
586 MemoryContextSwitchTo(CurTransactionContext);
590 * AtStart_ResourceOwner
593 AtStart_ResourceOwner(void)
595 TransactionState s = CurrentTransactionState;
598 * We shouldn't have a transaction resource owner already.
600 Assert(TopTransactionResourceOwner == NULL);
603 * Create a toplevel resource owner for the transaction.
605 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
607 TopTransactionResourceOwner = s->curTransactionOwner;
608 CurTransactionResourceOwner = s->curTransactionOwner;
609 CurrentResourceOwner = s->curTransactionOwner;
612 /* ----------------------------------------------------------------
613 * StartSubTransaction stuff
614 * ----------------------------------------------------------------
621 AtSubStart_Memory(void)
623 TransactionState s = CurrentTransactionState;
625 Assert(CurTransactionContext != NULL);
628 * Create a CurTransactionContext, which will be used to hold data that
629 * survives subtransaction commit but disappears on subtransaction abort.
630 * We make it a child of the immediate parent's CurTransactionContext.
632 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
633 "CurTransactionContext",
634 ALLOCSET_DEFAULT_MINSIZE,
635 ALLOCSET_DEFAULT_INITSIZE,
636 ALLOCSET_DEFAULT_MAXSIZE);
637 s->curTransactionContext = CurTransactionContext;
639 /* Make the CurTransactionContext active. */
640 MemoryContextSwitchTo(CurTransactionContext);
644 * AtSubStart_ResourceOwner
647 AtSubStart_ResourceOwner(void)
649 TransactionState s = CurrentTransactionState;
651 Assert(s->parent != NULL);
654 * Create a resource owner for the subtransaction. We make it a child of
655 * the immediate parent's resource owner.
657 s->curTransactionOwner =
658 ResourceOwnerCreate(s->parent->curTransactionOwner,
661 CurTransactionResourceOwner = s->curTransactionOwner;
662 CurrentResourceOwner = s->curTransactionOwner;
665 /* ----------------------------------------------------------------
666 * CommitTransaction stuff
667 * ----------------------------------------------------------------
671 * RecordTransactionCommit
674 RecordTransactionCommit(void)
679 TransactionId *children;
681 /* Get data needed for commit record */
682 nrels = smgrGetPendingDeletes(true, &rels);
683 nchildren = xactGetCommittedChildren(&children);
686 * If we made neither any XLOG entries nor any temp-rel updates, and have
687 * no files to be deleted, we can omit recording the transaction commit at
688 * all. (This test includes the effects of subtransactions, so the
689 * presence of committed subxacts need not alone force a write.)
691 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
693 TransactionId xid = GetCurrentTransactionId();
697 /* Tell bufmgr and smgr to prepare for commit */
700 START_CRIT_SECTION();
703 * If our transaction made any transaction-controlled XLOG entries, we
704 * need to lock out checkpoint start between writing our XLOG record
705 * and updating pg_clog. Otherwise it is possible for the checkpoint
706 * to set REDO after the XLOG record but fail to flush the pg_clog
707 * update to disk, leading to loss of the transaction commit if we
708 * crash a little later. Slightly klugy fix for problem discovered
711 * (If it made no transaction-controlled XLOG entries, its XID appears
712 * nowhere in permanent storage, so no one else will ever care if it
713 * committed; so it doesn't matter if we lose the commit flag.)
715 * Note we only need a shared lock.
717 madeTCentries = (MyLastRecPtr.xrecoff != 0);
719 LWLockAcquire(CheckpointStartLock, LW_SHARED);
722 * We only need to log the commit in XLOG if the transaction made any
723 * transaction-controlled XLOG entries or will delete files.
725 if (madeTCentries || nrels > 0)
727 XLogRecData rdata[3];
729 xl_xact_commit xlrec;
731 xlrec.xtime = time(NULL);
733 xlrec.nsubxacts = nchildren;
734 rdata[0].data = (char *) (&xlrec);
735 rdata[0].len = MinSizeOfXactCommit;
736 rdata[0].buffer = InvalidBuffer;
737 /* dump rels to delete */
740 rdata[0].next = &(rdata[1]);
741 rdata[1].data = (char *) rels;
742 rdata[1].len = nrels * sizeof(RelFileNode);
743 rdata[1].buffer = InvalidBuffer;
746 /* dump committed child Xids */
749 rdata[lastrdata].next = &(rdata[2]);
750 rdata[2].data = (char *) children;
751 rdata[2].len = nchildren * sizeof(TransactionId);
752 rdata[2].buffer = InvalidBuffer;
755 rdata[lastrdata].next = NULL;
757 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
761 /* Just flush through last record written by me */
762 recptr = ProcLastRecEnd;
766 * We must flush our XLOG entries to disk if we made any XLOG entries,
767 * whether in or out of transaction control. For example, if we
768 * reported a nextval() result to the client, this ensures that any
769 * XLOG record generated by nextval will hit the disk before we report
770 * the transaction committed.
772 * Note: if we generated a commit record above, MyXactMadeXLogEntry
773 * will certainly be set now.
775 if (MyXactMadeXLogEntry)
778 * Sleep before flush! So we can flush more than one commit
779 * records per single fsync. (The idea is some other backend may
780 * do the XLogFlush while we're sleeping. This needs work still,
781 * because on most Unixen, the minimum select() delay is 10msec or
782 * more, which is way too long.)
784 * We do not sleep if enableFsync is not turned on, nor if there
785 * are fewer than CommitSiblings other backends with active
788 if (CommitDelay > 0 && enableFsync &&
789 CountActiveBackends() >= CommitSiblings)
790 pg_usleep(CommitDelay);
796 * We must mark the transaction committed in clog if its XID appears
797 * either in permanent rels or in local temporary rels. We test this
798 * by seeing if we made transaction-controlled entries *OR* local-rel
799 * tuple updates. Note that if we made only the latter, we have not
800 * emitted an XLOG record for our commit, and so in the event of a
801 * crash the clog update might be lost. This is okay because no one
802 * else will ever care whether we committed.
804 if (madeTCentries || MyXactMadeTempRelUpdate)
806 TransactionIdCommit(xid);
807 /* to avoid race conditions, the parent must commit first */
808 TransactionIdCommitTree(nchildren, children);
811 /* Unlock checkpoint lock if we acquired it */
813 LWLockRelease(CheckpointStartLock);
818 /* Break the chain of back-links in the XLOG records I output */
819 MyLastRecPtr.xrecoff = 0;
820 MyXactMadeXLogEntry = false;
821 MyXactMadeTempRelUpdate = false;
823 /* And clean up local data */
832 * AtCommit_LocalCache
835 AtCommit_LocalCache(void)
838 * Make catalog changes visible to me for the next command.
840 CommandEndInvalidationMessages();
847 AtCommit_Memory(void)
850 * Now that we're "out" of a transaction, have the system allocate things
851 * in the top memory context instead of per-transaction contexts.
853 MemoryContextSwitchTo(TopMemoryContext);
856 * Release all transaction-local memory.
858 Assert(TopTransactionContext != NULL);
859 MemoryContextDelete(TopTransactionContext);
860 TopTransactionContext = NULL;
861 CurTransactionContext = NULL;
862 CurrentTransactionState->curTransactionContext = NULL;
865 /* ----------------------------------------------------------------
866 * CommitSubTransaction stuff
867 * ----------------------------------------------------------------
874 AtSubCommit_Memory(void)
876 TransactionState s = CurrentTransactionState;
878 Assert(s->parent != NULL);
880 /* Return to parent transaction level's memory context. */
881 CurTransactionContext = s->parent->curTransactionContext;
882 MemoryContextSwitchTo(CurTransactionContext);
885 * Ordinarily we cannot throw away the child's CurTransactionContext,
886 * since the data it contains will be needed at upper commit. However, if
887 * there isn't actually anything in it, we can throw it away. This avoids
888 * a small memory leak in the common case of "trivial" subxacts.
890 if (MemoryContextIsEmpty(s->curTransactionContext))
892 MemoryContextDelete(s->curTransactionContext);
893 s->curTransactionContext = NULL;
898 * AtSubCommit_childXids
900 * Pass my own XID and my child XIDs up to my parent as committed children.
903 AtSubCommit_childXids(void)
905 TransactionState s = CurrentTransactionState;
906 MemoryContext old_cxt;
908 Assert(s->parent != NULL);
911 * We keep the child-XID lists in TopTransactionContext; this avoids
912 * setting up child-transaction contexts for what might be just a few
913 * bytes of grandchild XIDs.
915 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
917 s->parent->childXids = lappend_xid(s->parent->childXids,
920 if (s->childXids != NIL)
922 s->parent->childXids = list_concat(s->parent->childXids,
926 * list_concat doesn't free the list header for the second list; do so
927 * here to avoid memory leakage (kluge)
933 MemoryContextSwitchTo(old_cxt);
937 * RecordSubTransactionCommit
940 RecordSubTransactionCommit(void)
943 * We do not log the subcommit in XLOG; it doesn't matter until the
944 * top-level transaction commits.
946 * We must mark the subtransaction subcommitted in clog if its XID appears
947 * either in permanent rels or in local temporary rels. We test this by
948 * seeing if we made transaction-controlled entries *OR* local-rel tuple
949 * updates. (The test here actually covers the entire transaction tree so
950 * far, so it may mark subtransactions that don't really need it, but it's
951 * probably not worth being tenser. Note that if a prior subtransaction
952 * dirtied these variables, then RecordTransactionCommit will have to do
953 * the full pushup anyway...)
955 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
957 TransactionId xid = GetCurrentTransactionId();
959 /* XXX does this really need to be a critical section? */
960 START_CRIT_SECTION();
962 /* Record subtransaction subcommit */
963 TransactionIdSubCommit(xid);
969 /* ----------------------------------------------------------------
970 * AbortTransaction stuff
971 * ----------------------------------------------------------------
975 * RecordTransactionAbort
978 RecordTransactionAbort(void)
983 TransactionId *children;
985 /* Get data needed for abort record */
986 nrels = smgrGetPendingDeletes(false, &rels);
987 nchildren = xactGetCommittedChildren(&children);
990 * If we made neither any transaction-controlled XLOG entries nor any
991 * temp-rel updates, and are not going to delete any files, we can omit
992 * recording the transaction abort at all. No one will ever care that it
993 * aborted. (These tests cover our whole transaction tree.)
995 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
997 TransactionId xid = GetCurrentTransactionId();
1000 * Catch the scenario where we aborted partway through
1001 * RecordTransactionCommit ...
1003 if (TransactionIdDidCommit(xid))
1004 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
1006 START_CRIT_SECTION();
1009 * We only need to log the abort in XLOG if the transaction made any
1010 * transaction-controlled XLOG entries or will delete files. (If it
1011 * made no transaction-controlled XLOG entries, its XID appears
1012 * nowhere in permanent storage, so no one else will ever care if it
1015 * We do not flush XLOG to disk unless deleting files, since the
1016 * default assumption after a crash would be that we aborted, anyway.
1017 * For the same reason, we don't need to worry about interlocking
1018 * against checkpoint start.
1020 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1022 XLogRecData rdata[3];
1024 xl_xact_abort xlrec;
1027 xlrec.xtime = time(NULL);
1028 xlrec.nrels = nrels;
1029 xlrec.nsubxacts = nchildren;
1030 rdata[0].data = (char *) (&xlrec);
1031 rdata[0].len = MinSizeOfXactAbort;
1032 rdata[0].buffer = InvalidBuffer;
1033 /* dump rels to delete */
1036 rdata[0].next = &(rdata[1]);
1037 rdata[1].data = (char *) rels;
1038 rdata[1].len = nrels * sizeof(RelFileNode);
1039 rdata[1].buffer = InvalidBuffer;
1042 /* dump committed child Xids */
1045 rdata[lastrdata].next = &(rdata[2]);
1046 rdata[2].data = (char *) children;
1047 rdata[2].len = nchildren * sizeof(TransactionId);
1048 rdata[2].buffer = InvalidBuffer;
1051 rdata[lastrdata].next = NULL;
1053 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1055 /* Must flush if we are deleting files... */
1061 * Mark the transaction aborted in clog. This is not absolutely
1062 * necessary but we may as well do it while we are here.
1064 * The ordering here isn't critical but it seems best to mark the
1065 * parent first. This assures an atomic transition of all the
1066 * subtransactions to aborted state from the point of view of
1067 * concurrent TransactionIdDidAbort calls.
1069 TransactionIdAbort(xid);
1070 TransactionIdAbortTree(nchildren, children);
1075 /* Break the chain of back-links in the XLOG records I output */
1076 MyLastRecPtr.xrecoff = 0;
1077 MyXactMadeXLogEntry = false;
1078 MyXactMadeTempRelUpdate = false;
1080 /* And clean up local data */
1091 AtAbort_Memory(void)
1094 * Make sure we are in a valid context (not a child of
1095 * TopTransactionContext...). Note that it is possible for this code to
1096 * be called when we aren't in a transaction at all; go directly to
1097 * TopMemoryContext in that case.
1099 if (TopTransactionContext != NULL)
1101 MemoryContextSwitchTo(TopTransactionContext);
1104 * We do not want to destroy the transaction's global state yet, so we
1105 * can't free any memory here.
1109 MemoryContextSwitchTo(TopMemoryContext);
1116 AtSubAbort_Memory(void)
1118 Assert(TopTransactionContext != NULL);
1120 MemoryContextSwitchTo(TopTransactionContext);
1125 * AtAbort_ResourceOwner
1128 AtAbort_ResourceOwner(void)
1131 * Make sure we have a valid ResourceOwner, if possible (else it will be
1132 * NULL, which is OK)
1134 CurrentResourceOwner = TopTransactionResourceOwner;
1138 * AtSubAbort_ResourceOwner
1141 AtSubAbort_ResourceOwner(void)
1143 TransactionState s = CurrentTransactionState;
1145 /* Make sure we have a valid ResourceOwner */
1146 CurrentResourceOwner = s->curTransactionOwner;
1151 * AtSubAbort_childXids
1154 AtSubAbort_childXids(void)
1156 TransactionState s = CurrentTransactionState;
1159 * We keep the child-XID lists in TopTransactionContext (see
1160 * AtSubCommit_childXids). This means we'd better free the list
1161 * explicitly at abort to avoid leakage.
1163 list_free(s->childXids);
1168 * RecordSubTransactionAbort
1171 RecordSubTransactionAbort(void)
1175 TransactionId xid = GetCurrentTransactionId();
1177 TransactionId *children;
1179 /* Get data needed for abort record */
1180 nrels = smgrGetPendingDeletes(false, &rels);
1181 nchildren = xactGetCommittedChildren(&children);
1184 * If we made neither any transaction-controlled XLOG entries nor any
1185 * temp-rel updates, and are not going to delete any files, we can omit
1186 * recording the transaction abort at all. No one will ever care that it
1187 * aborted. (These tests cover our whole transaction tree, and therefore
1188 * may mark subxacts that don't really need it, but it's probably not
1189 * worth being tenser.)
1191 * In this case we needn't worry about marking subcommitted children as
1192 * aborted, because they didn't mark themselves as subcommitted in the
1193 * first place; see the optimization in RecordSubTransactionCommit.
1195 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1197 START_CRIT_SECTION();
1200 * We only need to log the abort in XLOG if the transaction made any
1201 * transaction-controlled XLOG entries or will delete files.
1203 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1205 XLogRecData rdata[3];
1207 xl_xact_abort xlrec;
1210 xlrec.xtime = time(NULL);
1211 xlrec.nrels = nrels;
1212 xlrec.nsubxacts = nchildren;
1213 rdata[0].data = (char *) (&xlrec);
1214 rdata[0].len = MinSizeOfXactAbort;
1215 rdata[0].buffer = InvalidBuffer;
1216 /* dump rels to delete */
1219 rdata[0].next = &(rdata[1]);
1220 rdata[1].data = (char *) rels;
1221 rdata[1].len = nrels * sizeof(RelFileNode);
1222 rdata[1].buffer = InvalidBuffer;
1225 /* dump committed child Xids */
1228 rdata[lastrdata].next = &(rdata[2]);
1229 rdata[2].data = (char *) children;
1230 rdata[2].len = nchildren * sizeof(TransactionId);
1231 rdata[2].buffer = InvalidBuffer;
1234 rdata[lastrdata].next = NULL;
1236 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1238 /* Must flush if we are deleting files... */
1244 * Mark the transaction aborted in clog. This is not absolutely
1245 * necessary but XactLockTableWait makes use of it to avoid waiting
1246 * for already-aborted subtransactions.
1248 TransactionIdAbort(xid);
1249 TransactionIdAbortTree(nchildren, children);
1255 * We can immediately remove failed XIDs from PGPROC's cache of running
1256 * child XIDs. It's easiest to do it here while we have the child XID
1257 * array at hand, even though in the main-transaction case the equivalent
1258 * work happens just after return from RecordTransactionAbort.
1260 XidCacheRemoveRunningXids(xid, nchildren, children);
1262 /* And clean up local data */
1269 /* ----------------------------------------------------------------
1270 * CleanupTransaction stuff
1271 * ----------------------------------------------------------------
1278 AtCleanup_Memory(void)
1281 * Now that we're "out" of a transaction, have the system allocate things
1282 * in the top memory context instead of per-transaction contexts.
1284 MemoryContextSwitchTo(TopMemoryContext);
1286 Assert(CurrentTransactionState->parent == NULL);
1289 * Release all transaction-local memory.
1291 if (TopTransactionContext != NULL)
1292 MemoryContextDelete(TopTransactionContext);
1293 TopTransactionContext = NULL;
1294 CurTransactionContext = NULL;
1295 CurrentTransactionState->curTransactionContext = NULL;
1299 /* ----------------------------------------------------------------
1300 * CleanupSubTransaction stuff
1301 * ----------------------------------------------------------------
1305 * AtSubCleanup_Memory
1308 AtSubCleanup_Memory(void)
1310 TransactionState s = CurrentTransactionState;
1312 Assert(s->parent != NULL);
1314 /* Make sure we're not in an about-to-be-deleted context */
1315 MemoryContextSwitchTo(s->parent->curTransactionContext);
1316 CurTransactionContext = s->parent->curTransactionContext;
1319 * Delete the subxact local memory contexts. Its CurTransactionContext can
1320 * go too (note this also kills CurTransactionContexts from any children
1323 if (s->curTransactionContext)
1324 MemoryContextDelete(s->curTransactionContext);
1325 s->curTransactionContext = NULL;
1328 /* ----------------------------------------------------------------
1329 * interface routines
1330 * ----------------------------------------------------------------
1337 StartTransaction(void)
1342 * Let's just make sure the state stack is empty
1344 s = &TopTransactionStateData;
1345 CurrentTransactionState = s;
1348 * check the current transaction state
1350 if (s->state != TRANS_DEFAULT)
1351 elog(WARNING, "StartTransaction while in %s state",
1352 TransStateAsString(s->state));
1355 * set the current transaction state information appropriately during
1358 s->state = TRANS_START;
1359 s->transactionId = InvalidTransactionId; /* until assigned */
1362 * Make sure we've freed any old snapshot, and reset xact state variables
1365 XactIsoLevel = DefaultXactIsoLevel;
1366 XactReadOnly = DefaultXactReadOnly;
1369 * reinitialize within-transaction counters
1371 s->subTransactionId = TopSubTransactionId;
1372 currentSubTransactionId = TopSubTransactionId;
1373 currentCommandId = FirstCommandId;
1376 * must initialize resource-management stuff first
1379 AtStart_ResourceOwner();
1382 * generate a new transaction id
1384 s->transactionId = GetNewTransactionId(false);
1386 XactLockTableInsert(s->transactionId);
1389 * now() and statement_timestamp() should be the same time
1391 xactStartTimestamp = stmtStartTimestamp;
1394 * initialize current transaction state fields
1396 s->nestingLevel = 1;
1400 * You might expect to see "s->currentUser = GetUserId();" here, but you
1401 * won't because it doesn't work during startup; the userid isn't set yet
1402 * during a backend's first transaction start. We only use the
1403 * currentUser field in sub-transaction state structs.
1405 * prevXactReadOnly is also valid only in sub-transactions.
1409 * initialize other subsystems for new transaction
1413 AfterTriggerBeginXact();
1416 * done with start processing, set current transaction state to "in
1419 s->state = TRANS_INPROGRESS;
1421 ShowTransactionState("StartTransaction");
1428 * NB: if you change this routine, better look at PrepareTransaction too!
1431 CommitTransaction(void)
1433 TransactionState s = CurrentTransactionState;
1435 ShowTransactionState("CommitTransaction");
1438 * check the current transaction state
1440 if (s->state != TRANS_INPROGRESS)
1441 elog(WARNING, "CommitTransaction while in %s state",
1442 TransStateAsString(s->state));
1443 Assert(s->parent == NULL);
1446 * Do pre-commit processing (most of this stuff requires database access,
1447 * and in fact could still cause an error...)
1449 * It is possible for CommitHoldablePortals to invoke functions that queue
1450 * deferred triggers, and it's also possible that triggers create holdable
1451 * cursors. So we have to loop until there's nothing left to do.
1456 * Fire all currently pending deferred triggers.
1458 AfterTriggerFireDeferred();
1461 * Convert any open holdable cursors into static portals. If there
1462 * weren't any, we are done ... otherwise loop back to check if they
1463 * queued deferred triggers. Lather, rinse, repeat.
1465 if (!CommitHoldablePortals())
1469 /* Now we can shut down the deferred-trigger manager */
1470 AfterTriggerEndXact(true);
1472 /* Close any open regular cursors */
1476 * Let ON COMMIT management do its thing (must happen after closing
1477 * cursors, to avoid dangling-reference problems)
1479 PreCommit_on_commit_actions();
1481 /* close large objects before lower-level cleanup */
1482 AtEOXact_LargeObject(true);
1484 /* NOTIFY commit must come before lower-level cleanup */
1488 * Update flat files if we changed pg_database, pg_authid or
1489 * pg_auth_members. This should be the last step before commit.
1491 AtEOXact_UpdateFlatFiles(true);
1493 /* Prevent cancel/die interrupt while cleaning up */
1497 * set the current transaction state information appropriately during
1500 s->state = TRANS_COMMIT;
1503 * Here is where we really truly commit.
1505 RecordTransactionCommit();
1508 * Let others know about no transaction in progress by me. Note that
1509 * this must be done _before_ releasing locks we hold and _after_
1510 * RecordTransactionCommit.
1512 * LWLockAcquire(ProcArrayLock) is required; consider this example:
1513 * UPDATE with xid 0 is blocked by xid 1's UPDATE.
1514 * xid 1 is doing commit while xid 2 gets snapshot.
1515 * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1516 * xid 0 as running as well, or it will be able to see two tuple versions
1517 * - one deleted by xid 1 and one inserted by xid 0. See notes in
1520 * Note: MyProc may be null during bootstrap.
1525 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1526 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1527 MyProc->xid = InvalidTransactionId;
1528 MyProc->xmin = InvalidTransactionId;
1530 /* Clear the subtransaction-XID cache too while holding the lock */
1531 MyProc->subxids.nxids = 0;
1532 MyProc->subxids.overflowed = false;
1534 LWLockRelease(ProcArrayLock);
1538 * This is all post-commit cleanup. Note that if an error is raised here,
1539 * it's too late to abort the transaction. This should be just
1540 * noncritical resource releasing.
1542 * The ordering of operations is not entirely random. The idea is:
1543 * release resources visible to other backends (eg, files, buffer pins);
1544 * then release locks; then release backend-local resources. We want to
1545 * release locks at the point where any backend waiting for us will see
1546 * our transaction as being fully cleaned up.
1548 * Resources that can be associated with individual queries are handled by
1549 * the ResourceOwner mechanism. The other calls here are for backend-wide
1553 CallXactCallbacks(XACT_EVENT_COMMIT);
1555 ResourceOwnerRelease(TopTransactionResourceOwner,
1556 RESOURCE_RELEASE_BEFORE_LOCKS,
1559 /* Check we've released all buffer pins */
1560 AtEOXact_Buffers(true);
1562 /* Clean up the relation cache */
1563 AtEOXact_RelationCache(true);
1566 * Make catalog changes visible to all backends. This has to happen after
1567 * relcache references are dropped (see comments for
1568 * AtEOXact_RelationCache), but before locks are released (if anyone is
1569 * waiting for lock on a relation we've modified, we want them to know
1570 * about the catalog change before they start using the relation).
1572 AtEOXact_Inval(true);
1575 * Likewise, dropping of files deleted during the transaction is best done
1576 * after releasing relcache and buffer pins. (This is not strictly
1577 * necessary during commit, since such pins should have been released
1578 * already, but this ordering is definitely critical during abort.)
1580 smgrDoPendingDeletes(true);
1582 AtEOXact_MultiXact();
1584 ResourceOwnerRelease(TopTransactionResourceOwner,
1585 RESOURCE_RELEASE_LOCKS,
1587 ResourceOwnerRelease(TopTransactionResourceOwner,
1588 RESOURCE_RELEASE_AFTER_LOCKS,
1591 /* Check we've released all catcache entries */
1592 AtEOXact_CatCache(true);
1594 AtEOXact_GUC(true, false);
1596 AtEOXact_on_commit_actions(true);
1597 AtEOXact_Namespace(true);
1598 /* smgrcommit already done */
1600 pgstat_count_xact_commit();
1602 CurrentResourceOwner = NULL;
1603 ResourceOwnerDelete(TopTransactionResourceOwner);
1604 s->curTransactionOwner = NULL;
1605 CurTransactionResourceOwner = NULL;
1606 TopTransactionResourceOwner = NULL;
1610 s->transactionId = InvalidTransactionId;
1611 s->subTransactionId = InvalidSubTransactionId;
1612 s->nestingLevel = 0;
1616 * done with commit processing, set current transaction state back to
1619 s->state = TRANS_DEFAULT;
1621 RESUME_INTERRUPTS();
1626 * PrepareTransaction
1628 * NB: if you change this routine, better look at CommitTransaction too!
1631 PrepareTransaction(void)
1633 TransactionState s = CurrentTransactionState;
1634 TransactionId xid = GetCurrentTransactionId();
1635 GlobalTransaction gxact;
1636 TimestampTz prepared_at;
1638 ShowTransactionState("PrepareTransaction");
1641 * check the current transaction state
1643 if (s->state != TRANS_INPROGRESS)
1644 elog(WARNING, "PrepareTransaction while in %s state",
1645 TransStateAsString(s->state));
1646 Assert(s->parent == NULL);
1649 * Do pre-commit processing (most of this stuff requires database access,
1650 * and in fact could still cause an error...)
1652 * It is possible for PrepareHoldablePortals to invoke functions that
1653 * queue deferred triggers, and it's also possible that triggers create
1654 * holdable cursors. So we have to loop until there's nothing left to do.
1659 * Fire all currently pending deferred triggers.
1661 AfterTriggerFireDeferred();
1664 * Convert any open holdable cursors into static portals. If there
1665 * weren't any, we are done ... otherwise loop back to check if they
1666 * queued deferred triggers. Lather, rinse, repeat.
1668 if (!PrepareHoldablePortals())
1672 /* Now we can shut down the deferred-trigger manager */
1673 AfterTriggerEndXact(true);
1675 /* Close any open regular cursors */
1679 * Let ON COMMIT management do its thing (must happen after closing
1680 * cursors, to avoid dangling-reference problems)
1682 PreCommit_on_commit_actions();
1684 /* close large objects before lower-level cleanup */
1685 AtEOXact_LargeObject(true);
1687 /* NOTIFY and flatfiles will be handled below */
1689 /* Prevent cancel/die interrupt while cleaning up */
1693 * set the current transaction state information appropriately during
1694 * prepare processing
1696 s->state = TRANS_PREPARE;
1698 prepared_at = GetCurrentTimestamp();
1700 /* Tell bufmgr and smgr to prepare for commit */
1704 * Reserve the GID for this transaction. This could fail if the requested
1705 * GID is invalid or already in use.
1707 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1708 GetUserId(), MyDatabaseId);
1712 * Collect data for the 2PC state file. Note that in general, no actual
1713 * state change should happen in the called modules during this step,
1714 * since it's still possible to fail before commit, and in that case we
1715 * want transaction abort to be able to clean up. (In particular, the
1716 * AtPrepare routines may error out if they find cases they cannot
1717 * handle.) State cleanup should happen in the PostPrepare routines
1718 * below. However, some modules can go ahead and clear state here because
1719 * they wouldn't do anything with it during abort anyway.
1721 * Note: because the 2PC state file records will be replayed in the same
1722 * order they are made, the order of these calls has to match the order in
1723 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1724 * PREPARED; in particular, pay attention to whether things should happen
1725 * before or after releasing the transaction's locks.
1727 StartPrepare(gxact);
1730 AtPrepare_UpdateFlatFiles();
1735 * Here is where we really truly prepare.
1737 * We have to record transaction prepares even if we didn't make any
1738 * updates, because the transaction manager might get confused if we lose
1739 * a global transaction.
1744 * Now we clean up backend-internal state and release internal resources.
1747 /* Break the chain of back-links in the XLOG records I output */
1748 MyLastRecPtr.xrecoff = 0;
1749 MyXactMadeXLogEntry = false;
1750 MyXactMadeTempRelUpdate = false;
1753 * Let others know about no transaction in progress by me. This has to be
1754 * done *after* the prepared transaction has been marked valid, else
1755 * someone may think it is unlocked and recyclable.
1758 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1759 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1760 MyProc->xid = InvalidTransactionId;
1761 MyProc->xmin = InvalidTransactionId;
1763 /* Clear the subtransaction-XID cache too while holding the lock */
1764 MyProc->subxids.nxids = 0;
1765 MyProc->subxids.overflowed = false;
1767 LWLockRelease(ProcArrayLock);
1770 * This is all post-transaction cleanup. Note that if an error is raised
1771 * here, it's too late to abort the transaction. This should be just
1772 * noncritical resource releasing. See notes in CommitTransaction.
1775 CallXactCallbacks(XACT_EVENT_PREPARE);
1777 ResourceOwnerRelease(TopTransactionResourceOwner,
1778 RESOURCE_RELEASE_BEFORE_LOCKS,
1781 /* Check we've released all buffer pins */
1782 AtEOXact_Buffers(true);
1784 /* Clean up the relation cache */
1785 AtEOXact_RelationCache(true);
1787 /* notify and flatfiles don't need a postprepare call */
1789 PostPrepare_Inval();
1793 AtEOXact_MultiXact();
1795 PostPrepare_Locks(xid);
1797 ResourceOwnerRelease(TopTransactionResourceOwner,
1798 RESOURCE_RELEASE_LOCKS,
1800 ResourceOwnerRelease(TopTransactionResourceOwner,
1801 RESOURCE_RELEASE_AFTER_LOCKS,
1804 /* Check we've released all catcache entries */
1805 AtEOXact_CatCache(true);
1807 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1808 AtEOXact_GUC(true, false);
1810 AtEOXact_on_commit_actions(true);
1811 AtEOXact_Namespace(true);
1812 /* smgrcommit already done */
1815 CurrentResourceOwner = NULL;
1816 ResourceOwnerDelete(TopTransactionResourceOwner);
1817 s->curTransactionOwner = NULL;
1818 CurTransactionResourceOwner = NULL;
1819 TopTransactionResourceOwner = NULL;
1823 s->transactionId = InvalidTransactionId;
1824 s->subTransactionId = InvalidSubTransactionId;
1825 s->nestingLevel = 0;
1829 * done with 1st phase commit processing, set current transaction state
1832 s->state = TRANS_DEFAULT;
1834 RESUME_INTERRUPTS();
1842 AbortTransaction(void)
1844 TransactionState s = CurrentTransactionState;
1846 /* Prevent cancel/die interrupt while cleaning up */
1850 * Release any LW locks we might be holding as quickly as possible.
1851 * (Regular locks, however, must be held till we finish aborting.)
1852 * Releasing LW locks is critical since we might try to grab them again
1853 * while cleaning up!
1857 /* Clean up buffer I/O and buffer context locks, too */
1862 * Also clean up any open wait for lock, since the lock manager will choke
1863 * if we try to wait for another lock before doing this.
1868 * check the current transaction state
1870 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1871 elog(WARNING, "AbortTransaction while in %s state",
1872 TransStateAsString(s->state));
1873 Assert(s->parent == NULL);
1876 * set the current transaction state information appropriately during the
1879 s->state = TRANS_ABORT;
1881 /* Make sure we have a valid memory context and resource owner */
1883 AtAbort_ResourceOwner();
1886 * Reset user id which might have been changed transiently. We cannot use
1887 * s->currentUser, since it may not be set yet; instead rely on internal
1888 * state of miscinit.c.
1890 * (Note: it is not necessary to restore session authorization here
1891 * because that can only be changed via GUC, and GUC will take care of
1892 * rolling it back if need be. However, an error within a SECURITY
1893 * DEFINER function could send control here with the wrong current
1899 * do abort processing
1901 AfterTriggerEndXact(false);
1903 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1905 AtEOXact_UpdateFlatFiles(false);
1908 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1909 * far as assigning an XID to advertise).
1911 if (TransactionIdIsValid(s->transactionId))
1912 RecordTransactionAbort();
1915 * Let others know about no transaction in progress by me. Note that this
1916 * must be done _before_ releasing locks we hold and _after_
1917 * RecordTransactionAbort.
1921 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1922 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1923 MyProc->xid = InvalidTransactionId;
1924 MyProc->xmin = InvalidTransactionId;
1926 /* Clear the subtransaction-XID cache too while holding the lock */
1927 MyProc->subxids.nxids = 0;
1928 MyProc->subxids.overflowed = false;
1930 LWLockRelease(ProcArrayLock);
1934 * Post-abort cleanup. See notes in CommitTransaction() concerning
1938 CallXactCallbacks(XACT_EVENT_ABORT);
1940 ResourceOwnerRelease(TopTransactionResourceOwner,
1941 RESOURCE_RELEASE_BEFORE_LOCKS,
1943 AtEOXact_Buffers(false);
1944 AtEOXact_RelationCache(false);
1945 AtEOXact_Inval(false);
1946 smgrDoPendingDeletes(false);
1947 AtEOXact_MultiXact();
1948 ResourceOwnerRelease(TopTransactionResourceOwner,
1949 RESOURCE_RELEASE_LOCKS,
1951 ResourceOwnerRelease(TopTransactionResourceOwner,
1952 RESOURCE_RELEASE_AFTER_LOCKS,
1954 AtEOXact_CatCache(false);
1956 AtEOXact_GUC(false, false);
1957 AtEOXact_SPI(false);
1958 AtEOXact_on_commit_actions(false);
1959 AtEOXact_Namespace(false);
1962 pgstat_count_xact_rollback();
1965 * State remains TRANS_ABORT until CleanupTransaction().
1967 RESUME_INTERRUPTS();
1971 * CleanupTransaction
1974 CleanupTransaction(void)
1976 TransactionState s = CurrentTransactionState;
1979 * State should still be TRANS_ABORT from AbortTransaction().
1981 if (s->state != TRANS_ABORT)
1982 elog(FATAL, "CleanupTransaction: unexpected state %s",
1983 TransStateAsString(s->state));
1986 * do abort cleanup processing
1988 AtCleanup_Portals(); /* now safe to release portal memory */
1990 CurrentResourceOwner = NULL; /* and resource owner */
1991 if (TopTransactionResourceOwner)
1992 ResourceOwnerDelete(TopTransactionResourceOwner);
1993 s->curTransactionOwner = NULL;
1994 CurTransactionResourceOwner = NULL;
1995 TopTransactionResourceOwner = NULL;
1997 AtCleanup_Memory(); /* and transaction memory */
1999 s->transactionId = InvalidTransactionId;
2000 s->subTransactionId = InvalidSubTransactionId;
2001 s->nestingLevel = 0;
2005 * done with abort processing, set current transaction state back to
2008 s->state = TRANS_DEFAULT;
2012 * StartTransactionCommand
2015 StartTransactionCommand(void)
2017 TransactionState s = CurrentTransactionState;
2019 switch (s->blockState)
2022 * if we aren't in a transaction block, we just do our usual start
2025 case TBLOCK_DEFAULT:
2027 s->blockState = TBLOCK_STARTED;
2031 * We are somewhere in a transaction block or subtransaction and
2032 * about to start a new command. For now we do nothing, but
2033 * someday we may do command-local resource initialization. (Note
2034 * that any needed CommandCounterIncrement was done by the
2035 * previous CommitTransactionCommand.)
2037 case TBLOCK_INPROGRESS:
2038 case TBLOCK_SUBINPROGRESS:
2042 * Here we are in a failed transaction block (one of the commands
2043 * caused an abort) so we do nothing but remain in the abort
2044 * state. Eventually we will get a ROLLBACK command which will
2045 * get us out of this state. (It is up to other code to ensure
2046 * that no commands other than ROLLBACK will be processed in these
2050 case TBLOCK_SUBABORT:
2053 /* These cases are invalid. */
2054 case TBLOCK_STARTED:
2056 case TBLOCK_SUBBEGIN:
2059 case TBLOCK_ABORT_END:
2060 case TBLOCK_SUBABORT_END:
2061 case TBLOCK_ABORT_PENDING:
2062 case TBLOCK_SUBABORT_PENDING:
2063 case TBLOCK_SUBRESTART:
2064 case TBLOCK_SUBABORT_RESTART:
2065 case TBLOCK_PREPARE:
2066 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2067 BlockStateAsString(s->blockState));
2072 * We must switch to CurTransactionContext before returning. This is
2073 * already done if we called StartTransaction, otherwise not.
2075 Assert(CurTransactionContext != NULL);
2076 MemoryContextSwitchTo(CurTransactionContext);
2080 * CommitTransactionCommand
2083 CommitTransactionCommand(void)
2085 TransactionState s = CurrentTransactionState;
2087 switch (s->blockState)
2090 * This shouldn't happen, because it means the previous
2091 * StartTransactionCommand didn't set the STARTED state
2094 case TBLOCK_DEFAULT:
2095 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2096 BlockStateAsString(s->blockState));
2100 * If we aren't in a transaction block, just do our usual
2101 * transaction commit, and return to the idle state.
2103 case TBLOCK_STARTED:
2104 CommitTransaction();
2105 s->blockState = TBLOCK_DEFAULT;
2109 * We are completing a "BEGIN TRANSACTION" command, so we change
2110 * to the "transaction block in progress" state and return. (We
2111 * assume the BEGIN did nothing to the database, so we need no
2112 * CommandCounterIncrement.)
2115 s->blockState = TBLOCK_INPROGRESS;
2119 * This is the case when we have finished executing a command
2120 * someplace within a transaction block. We increment the command
2121 * counter and return.
2123 case TBLOCK_INPROGRESS:
2124 case TBLOCK_SUBINPROGRESS:
2125 CommandCounterIncrement();
2129 * We are completing a "COMMIT" command. Do it and return to the
2133 CommitTransaction();
2134 s->blockState = TBLOCK_DEFAULT;
2138 * Here we are in the middle of a transaction block but one of the
2139 * commands caused an abort so we do nothing but remain in the
2140 * abort state. Eventually we will get a ROLLBACK comand.
2143 case TBLOCK_SUBABORT:
2147 * Here we were in an aborted transaction block and we just got
2148 * the ROLLBACK command from the user, so clean up the
2149 * already-aborted transaction and return to the idle state.
2151 case TBLOCK_ABORT_END:
2152 CleanupTransaction();
2153 s->blockState = TBLOCK_DEFAULT;
2157 * Here we were in a perfectly good transaction block but the user
2158 * told us to ROLLBACK anyway. We have to abort the transaction
2159 * and then clean up.
2161 case TBLOCK_ABORT_PENDING:
2163 CleanupTransaction();
2164 s->blockState = TBLOCK_DEFAULT;
2168 * We are completing a "PREPARE TRANSACTION" command. Do it and
2169 * return to the idle state.
2171 case TBLOCK_PREPARE:
2172 PrepareTransaction();
2173 s->blockState = TBLOCK_DEFAULT;
2177 * We were just issued a SAVEPOINT inside a transaction block.
2178 * Start a subtransaction. (DefineSavepoint already did
2179 * PushTransaction, so as to have someplace to put the SUBBEGIN
2182 case TBLOCK_SUBBEGIN:
2183 StartSubTransaction();
2184 s->blockState = TBLOCK_SUBINPROGRESS;
2188 * We were issued a COMMIT or RELEASE command, so we end the
2189 * current subtransaction and return to the parent transaction.
2190 * The parent might be ended too, so repeat till we are all the
2191 * way out or find an INPROGRESS transaction.
2196 CommitSubTransaction();
2197 s = CurrentTransactionState; /* changed by pop */
2198 } while (s->blockState == TBLOCK_SUBEND);
2199 /* If we had a COMMIT command, finish off the main xact too */
2200 if (s->blockState == TBLOCK_END)
2202 Assert(s->parent == NULL);
2203 CommitTransaction();
2204 s->blockState = TBLOCK_DEFAULT;
2206 else if (s->blockState == TBLOCK_PREPARE)
2208 Assert(s->parent == NULL);
2209 PrepareTransaction();
2210 s->blockState = TBLOCK_DEFAULT;
2214 Assert(s->blockState == TBLOCK_INPROGRESS ||
2215 s->blockState == TBLOCK_SUBINPROGRESS);
2220 * The current already-failed subtransaction is ending due to a
2221 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2222 * examine the parent (which could be in any of several states).
2224 case TBLOCK_SUBABORT_END:
2225 CleanupSubTransaction();
2226 CommitTransactionCommand();
2230 * As above, but it's not dead yet, so abort first.
2232 case TBLOCK_SUBABORT_PENDING:
2233 AbortSubTransaction();
2234 CleanupSubTransaction();
2235 CommitTransactionCommand();
2239 * The current subtransaction is the target of a ROLLBACK TO
2240 * command. Abort and pop it, then start a new subtransaction
2241 * with the same name.
2243 case TBLOCK_SUBRESTART:
2248 /* save name and keep Cleanup from freeing it */
2251 savepointLevel = s->savepointLevel;
2253 AbortSubTransaction();
2254 CleanupSubTransaction();
2256 DefineSavepoint(NULL);
2257 s = CurrentTransactionState; /* changed by push */
2259 s->savepointLevel = savepointLevel;
2261 /* This is the same as TBLOCK_SUBBEGIN case */
2262 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2263 StartSubTransaction();
2264 s->blockState = TBLOCK_SUBINPROGRESS;
2269 * Same as above, but the subtransaction had already failed, so we
2270 * don't need AbortSubTransaction.
2272 case TBLOCK_SUBABORT_RESTART:
2277 /* save name and keep Cleanup from freeing it */
2280 savepointLevel = s->savepointLevel;
2282 CleanupSubTransaction();
2284 DefineSavepoint(NULL);
2285 s = CurrentTransactionState; /* changed by push */
2287 s->savepointLevel = savepointLevel;
2289 /* This is the same as TBLOCK_SUBBEGIN case */
2290 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2291 StartSubTransaction();
2292 s->blockState = TBLOCK_SUBINPROGRESS;
2299 * AbortCurrentTransaction
2302 AbortCurrentTransaction(void)
2304 TransactionState s = CurrentTransactionState;
2306 switch (s->blockState)
2308 case TBLOCK_DEFAULT:
2309 if (s->state == TRANS_DEFAULT)
2311 /* we are idle, so nothing to do */
2316 * We can get here after an error during transaction start
2317 * (state will be TRANS_START). Need to clean up the
2318 * incompletely started transaction. First, adjust the
2319 * low-level state to suppress warning message from
2322 if (s->state == TRANS_START)
2323 s->state = TRANS_INPROGRESS;
2325 CleanupTransaction();
2330 * if we aren't in a transaction block, we just do the basic abort
2331 * & cleanup transaction.
2333 case TBLOCK_STARTED:
2335 CleanupTransaction();
2336 s->blockState = TBLOCK_DEFAULT;
2340 * If we are in TBLOCK_BEGIN it means something screwed up right
2341 * after reading "BEGIN TRANSACTION". We assume that the user
2342 * will interpret the error as meaning the BEGIN failed to get him
2343 * into a transaction block, so we should abort and return to idle
2348 CleanupTransaction();
2349 s->blockState = TBLOCK_DEFAULT;
2353 * We are somewhere in a transaction block and we've gotten a
2354 * failure, so we abort the transaction and set up the persistent
2355 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2357 case TBLOCK_INPROGRESS:
2359 s->blockState = TBLOCK_ABORT;
2360 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2364 * Here, we failed while trying to COMMIT. Clean up the
2365 * transaction and return to idle state (we do not want to stay in
2370 CleanupTransaction();
2371 s->blockState = TBLOCK_DEFAULT;
2375 * Here, we are already in an aborted transaction state and are
2376 * waiting for a ROLLBACK, but for some reason we failed again! So
2377 * we just remain in the abort state.
2380 case TBLOCK_SUBABORT:
2384 * We are in a failed transaction and we got the ROLLBACK command.
2385 * We have already aborted, we just need to cleanup and go to idle
2388 case TBLOCK_ABORT_END:
2389 CleanupTransaction();
2390 s->blockState = TBLOCK_DEFAULT;
2394 * We are in a live transaction and we got a ROLLBACK command.
2395 * Abort, cleanup, go to idle state.
2397 case TBLOCK_ABORT_PENDING:
2399 CleanupTransaction();
2400 s->blockState = TBLOCK_DEFAULT;
2404 * Here, we failed while trying to PREPARE. Clean up the
2405 * transaction and return to idle state (we do not want to stay in
2408 case TBLOCK_PREPARE:
2410 CleanupTransaction();
2411 s->blockState = TBLOCK_DEFAULT;
2415 * We got an error inside a subtransaction. Abort just the
2416 * subtransaction, and go to the persistent SUBABORT state until
2419 case TBLOCK_SUBINPROGRESS:
2420 AbortSubTransaction();
2421 s->blockState = TBLOCK_SUBABORT;
2425 * If we failed while trying to create a subtransaction, clean up
2426 * the broken subtransaction and abort the parent. The same
2427 * applies if we get a failure while ending a subtransaction.
2429 case TBLOCK_SUBBEGIN:
2431 case TBLOCK_SUBABORT_PENDING:
2432 case TBLOCK_SUBRESTART:
2433 AbortSubTransaction();
2434 CleanupSubTransaction();
2435 AbortCurrentTransaction();
2439 * Same as above, except the Abort() was already done.
2441 case TBLOCK_SUBABORT_END:
2442 case TBLOCK_SUBABORT_RESTART:
2443 CleanupSubTransaction();
2444 AbortCurrentTransaction();
2450 * PreventTransactionChain
2452 * This routine is to be called by statements that must not run inside
2453 * a transaction block, typically because they have non-rollback-able
2454 * side effects or do internal commits.
2456 * If we have already started a transaction block, issue an error; also issue
2457 * an error if we appear to be running inside a user-defined function (which
2458 * could issue more commands and possibly cause a failure after the statement
2459 * completes). Subtransactions are verboten too.
2461 * stmtNode: pointer to parameter block for statement; this is used in
2462 * a very klugy way to determine whether we are inside a function.
2463 * stmtType: statement type name for error messages.
2466 PreventTransactionChain(void *stmtNode, const char *stmtType)
2469 * xact block already started?
2471 if (IsTransactionBlock())
2473 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2474 /* translator: %s represents an SQL statement name */
2475 errmsg("%s cannot run inside a transaction block",
2481 if (IsSubTransaction())
2483 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2484 /* translator: %s represents an SQL statement name */
2485 errmsg("%s cannot run inside a subtransaction",
2489 * Are we inside a function call? If the statement's parameter block was
2490 * allocated in QueryContext, assume it is an interactive command.
2491 * Otherwise assume it is coming from a function.
2493 if (!MemoryContextContains(QueryContext, stmtNode))
2495 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2496 /* translator: %s represents an SQL statement name */
2497 errmsg("%s cannot be executed from a function", stmtType)));
2499 /* If we got past IsTransactionBlock test, should be in default state */
2500 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2501 CurrentTransactionState->blockState != TBLOCK_STARTED)
2502 elog(FATAL, "cannot prevent transaction chain");
2507 * RequireTransactionChain
2509 * This routine is to be called by statements that must run inside
2510 * a transaction block, because they have no effects that persist past
2511 * transaction end (and so calling them outside a transaction block
2512 * is presumably an error). DECLARE CURSOR is an example.
2514 * If we appear to be running inside a user-defined function, we do not
2515 * issue an error, since the function could issue more commands that make
2516 * use of the current statement's results. Likewise subtransactions.
2517 * Thus this is an inverse for PreventTransactionChain.
2519 * stmtNode: pointer to parameter block for statement; this is used in
2520 * a very klugy way to determine whether we are inside a function.
2521 * stmtType: statement type name for error messages.
2524 RequireTransactionChain(void *stmtNode, const char *stmtType)
2527 * xact block already started?
2529 if (IsTransactionBlock())
2535 if (IsSubTransaction())
2539 * Are we inside a function call? If the statement's parameter block was
2540 * allocated in QueryContext, assume it is an interactive command.
2541 * Otherwise assume it is coming from a function.
2543 if (!MemoryContextContains(QueryContext, stmtNode))
2546 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2547 /* translator: %s represents an SQL statement name */
2548 errmsg("%s may only be used in transaction blocks",
2553 * IsInTransactionChain
2555 * This routine is for statements that need to behave differently inside
2556 * a transaction block than when running as single commands. ANALYZE is
2557 * currently the only example.
2559 * stmtNode: pointer to parameter block for statement; this is used in
2560 * a very klugy way to determine whether we are inside a function.
2563 IsInTransactionChain(void *stmtNode)
2566 * Return true on same conditions that would make PreventTransactionChain
2569 if (IsTransactionBlock())
2572 if (IsSubTransaction())
2575 if (!MemoryContextContains(QueryContext, stmtNode))
2578 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2579 CurrentTransactionState->blockState != TBLOCK_STARTED)
2587 * Register or deregister callback functions for start- and end-of-xact
2590 * These functions are intended for use by dynamically loaded modules.
2591 * For built-in modules we generally just hardwire the appropriate calls
2592 * (mainly because it's easier to control the order that way, where needed).
2594 * At transaction end, the callback occurs post-commit or post-abort, so the
2595 * callback functions can only do noncritical cleanup.
2598 RegisterXactCallback(XactCallback callback, void *arg)
2600 XactCallbackItem *item;
2602 item = (XactCallbackItem *)
2603 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2604 item->callback = callback;
2606 item->next = Xact_callbacks;
2607 Xact_callbacks = item;
2611 UnregisterXactCallback(XactCallback callback, void *arg)
2613 XactCallbackItem *item;
2614 XactCallbackItem *prev;
2617 for (item = Xact_callbacks; item; prev = item, item = item->next)
2619 if (item->callback == callback && item->arg == arg)
2622 prev->next = item->next;
2624 Xact_callbacks = item->next;
2632 CallXactCallbacks(XactEvent event)
2634 XactCallbackItem *item;
2636 for (item = Xact_callbacks; item; item = item->next)
2637 (*item->callback) (event, item->arg);
2642 * Register or deregister callback functions for start- and end-of-subxact
2645 * Pretty much same as above, but for subtransaction events.
2647 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2648 * so the callback functions can only do noncritical cleanup. At
2649 * subtransaction start, the callback is called when the subtransaction has
2650 * finished initializing.
2653 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2655 SubXactCallbackItem *item;
2657 item = (SubXactCallbackItem *)
2658 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2659 item->callback = callback;
2661 item->next = SubXact_callbacks;
2662 SubXact_callbacks = item;
2666 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2668 SubXactCallbackItem *item;
2669 SubXactCallbackItem *prev;
2672 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2674 if (item->callback == callback && item->arg == arg)
2677 prev->next = item->next;
2679 SubXact_callbacks = item->next;
2687 CallSubXactCallbacks(SubXactEvent event,
2688 SubTransactionId mySubid,
2689 SubTransactionId parentSubid)
2691 SubXactCallbackItem *item;
2693 for (item = SubXact_callbacks; item; item = item->next)
2694 (*item->callback) (event, mySubid, parentSubid, item->arg);
2698 /* ----------------------------------------------------------------
2699 * transaction block support
2700 * ----------------------------------------------------------------
2704 * BeginTransactionBlock
2705 * This executes a BEGIN command.
2708 BeginTransactionBlock(void)
2710 TransactionState s = CurrentTransactionState;
2712 switch (s->blockState)
2715 * We are not inside a transaction block, so allow one to begin.
2717 case TBLOCK_STARTED:
2718 s->blockState = TBLOCK_BEGIN;
2722 * Already a transaction block in progress.
2724 case TBLOCK_INPROGRESS:
2725 case TBLOCK_SUBINPROGRESS:
2727 case TBLOCK_SUBABORT:
2729 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2730 errmsg("there is already a transaction in progress")));
2733 /* These cases are invalid. */
2734 case TBLOCK_DEFAULT:
2736 case TBLOCK_SUBBEGIN:
2739 case TBLOCK_ABORT_END:
2740 case TBLOCK_SUBABORT_END:
2741 case TBLOCK_ABORT_PENDING:
2742 case TBLOCK_SUBABORT_PENDING:
2743 case TBLOCK_SUBRESTART:
2744 case TBLOCK_SUBABORT_RESTART:
2745 case TBLOCK_PREPARE:
2746 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2747 BlockStateAsString(s->blockState));
2753 * PrepareTransactionBlock
2754 * This executes a PREPARE command.
2756 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2757 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2759 * Note that we don't actually do anything here except change blockState.
2760 * The real work will be done in the upcoming PrepareTransaction().
2761 * We do it this way because it's not convenient to change memory context,
2762 * resource owner, etc while executing inside a Portal.
2765 PrepareTransactionBlock(char *gid)
2770 /* Set up to commit the current transaction */
2771 result = EndTransactionBlock();
2773 /* If successful, change outer tblock state to PREPARE */
2776 s = CurrentTransactionState;
2778 while (s->parent != NULL)
2781 if (s->blockState == TBLOCK_END)
2783 /* Save GID where PrepareTransaction can find it again */
2784 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2786 s->blockState = TBLOCK_PREPARE;
2791 * ignore case where we are not in a transaction;
2792 * EndTransactionBlock already issued a warning.
2794 Assert(s->blockState == TBLOCK_STARTED);
2795 /* Don't send back a PREPARE result tag... */
2804 * EndTransactionBlock
2805 * This executes a COMMIT command.
2807 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2808 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2810 * Note that we don't actually do anything here except change blockState.
2811 * The real work will be done in the upcoming CommitTransactionCommand().
2812 * We do it this way because it's not convenient to change memory context,
2813 * resource owner, etc while executing inside a Portal.
2816 EndTransactionBlock(void)
2818 TransactionState s = CurrentTransactionState;
2819 bool result = false;
2821 switch (s->blockState)
2824 * We are in a transaction block, so tell CommitTransactionCommand
2827 case TBLOCK_INPROGRESS:
2828 s->blockState = TBLOCK_END;
2833 * We are in a failed transaction block. Tell
2834 * CommitTransactionCommand it's time to exit the block.
2837 s->blockState = TBLOCK_ABORT_END;
2841 * We are in a live subtransaction block. Set up to subcommit all
2842 * open subtransactions and then commit the main transaction.
2844 case TBLOCK_SUBINPROGRESS:
2845 while (s->parent != NULL)
2847 if (s->blockState == TBLOCK_SUBINPROGRESS)
2848 s->blockState = TBLOCK_SUBEND;
2850 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2851 BlockStateAsString(s->blockState));
2854 if (s->blockState == TBLOCK_INPROGRESS)
2855 s->blockState = TBLOCK_END;
2857 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2858 BlockStateAsString(s->blockState));
2863 * Here we are inside an aborted subtransaction. Treat the COMMIT
2864 * as ROLLBACK: set up to abort everything and exit the main
2867 case TBLOCK_SUBABORT:
2868 while (s->parent != NULL)
2870 if (s->blockState == TBLOCK_SUBINPROGRESS)
2871 s->blockState = TBLOCK_SUBABORT_PENDING;
2872 else if (s->blockState == TBLOCK_SUBABORT)
2873 s->blockState = TBLOCK_SUBABORT_END;
2875 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2876 BlockStateAsString(s->blockState));
2879 if (s->blockState == TBLOCK_INPROGRESS)
2880 s->blockState = TBLOCK_ABORT_PENDING;
2881 else if (s->blockState == TBLOCK_ABORT)
2882 s->blockState = TBLOCK_ABORT_END;
2884 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2885 BlockStateAsString(s->blockState));
2889 * The user issued COMMIT when not inside a transaction. Issue a
2890 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2891 * CommitTransactionCommand() will then close the transaction and
2892 * put us back into the default state.
2894 case TBLOCK_STARTED:
2896 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2897 errmsg("there is no transaction in progress")));
2901 /* These cases are invalid. */
2902 case TBLOCK_DEFAULT:
2904 case TBLOCK_SUBBEGIN:
2907 case TBLOCK_ABORT_END:
2908 case TBLOCK_SUBABORT_END:
2909 case TBLOCK_ABORT_PENDING:
2910 case TBLOCK_SUBABORT_PENDING:
2911 case TBLOCK_SUBRESTART:
2912 case TBLOCK_SUBABORT_RESTART:
2913 case TBLOCK_PREPARE:
2914 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2915 BlockStateAsString(s->blockState));
2923 * UserAbortTransactionBlock
2924 * This executes a ROLLBACK command.
2926 * As above, we don't actually do anything here except change blockState.
2929 UserAbortTransactionBlock(void)
2931 TransactionState s = CurrentTransactionState;
2933 switch (s->blockState)
2936 * We are inside a transaction block and we got a ROLLBACK command
2937 * from the user, so tell CommitTransactionCommand to abort and
2938 * exit the transaction block.
2940 case TBLOCK_INPROGRESS:
2941 s->blockState = TBLOCK_ABORT_PENDING;
2945 * We are inside a failed transaction block and we got a ROLLBACK
2946 * command from the user. Abort processing is already done, so
2947 * CommitTransactionCommand just has to cleanup and go back to
2951 s->blockState = TBLOCK_ABORT_END;
2955 * We are inside a subtransaction. Mark everything up to top
2956 * level as exitable.
2958 case TBLOCK_SUBINPROGRESS:
2959 case TBLOCK_SUBABORT:
2960 while (s->parent != NULL)
2962 if (s->blockState == TBLOCK_SUBINPROGRESS)
2963 s->blockState = TBLOCK_SUBABORT_PENDING;
2964 else if (s->blockState == TBLOCK_SUBABORT)
2965 s->blockState = TBLOCK_SUBABORT_END;
2967 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2968 BlockStateAsString(s->blockState));
2971 if (s->blockState == TBLOCK_INPROGRESS)
2972 s->blockState = TBLOCK_ABORT_PENDING;
2973 else if (s->blockState == TBLOCK_ABORT)
2974 s->blockState = TBLOCK_ABORT_END;
2976 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2977 BlockStateAsString(s->blockState));
2981 * The user issued ABORT when not inside a transaction. Issue a
2982 * WARNING and go to abort state. The upcoming call to
2983 * CommitTransactionCommand() will then put us back into the
2986 case TBLOCK_STARTED:
2988 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2989 errmsg("there is no transaction in progress")));
2990 s->blockState = TBLOCK_ABORT_PENDING;
2993 /* These cases are invalid. */
2994 case TBLOCK_DEFAULT:
2996 case TBLOCK_SUBBEGIN:
2999 case TBLOCK_ABORT_END:
3000 case TBLOCK_SUBABORT_END:
3001 case TBLOCK_ABORT_PENDING:
3002 case TBLOCK_SUBABORT_PENDING:
3003 case TBLOCK_SUBRESTART:
3004 case TBLOCK_SUBABORT_RESTART:
3005 case TBLOCK_PREPARE:
3006 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3007 BlockStateAsString(s->blockState));
3014 * This executes a SAVEPOINT command.
3017 DefineSavepoint(char *name)
3019 TransactionState s = CurrentTransactionState;
3021 switch (s->blockState)
3023 case TBLOCK_INPROGRESS:
3024 case TBLOCK_SUBINPROGRESS:
3025 /* Normal subtransaction start */
3027 s = CurrentTransactionState; /* changed by push */
3030 * Savepoint names, like the TransactionState block itself, live
3031 * in TopTransactionContext.
3034 s->name = MemoryContextStrdup(TopTransactionContext, name);
3037 /* These cases are invalid. */
3038 case TBLOCK_DEFAULT:
3039 case TBLOCK_STARTED:
3041 case TBLOCK_SUBBEGIN:
3045 case TBLOCK_SUBABORT:
3046 case TBLOCK_ABORT_END:
3047 case TBLOCK_SUBABORT_END:
3048 case TBLOCK_ABORT_PENDING:
3049 case TBLOCK_SUBABORT_PENDING:
3050 case TBLOCK_SUBRESTART:
3051 case TBLOCK_SUBABORT_RESTART:
3052 case TBLOCK_PREPARE:
3053 elog(FATAL, "DefineSavepoint: unexpected state %s",
3054 BlockStateAsString(s->blockState));
3061 * This executes a RELEASE command.
3063 * As above, we don't actually do anything here except change blockState.
3066 ReleaseSavepoint(List *options)
3068 TransactionState s = CurrentTransactionState;
3069 TransactionState target,
3074 switch (s->blockState)
3077 * We can't rollback to a savepoint if there is no savepoint
3080 case TBLOCK_INPROGRESS:
3082 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3083 errmsg("no such savepoint")));
3087 * We are in a non-aborted subtransaction. This is the only valid
3090 case TBLOCK_SUBINPROGRESS:
3093 /* These cases are invalid. */
3094 case TBLOCK_DEFAULT:
3095 case TBLOCK_STARTED:
3097 case TBLOCK_SUBBEGIN:
3101 case TBLOCK_SUBABORT:
3102 case TBLOCK_ABORT_END:
3103 case TBLOCK_SUBABORT_END:
3104 case TBLOCK_ABORT_PENDING:
3105 case TBLOCK_SUBABORT_PENDING:
3106 case TBLOCK_SUBRESTART:
3107 case TBLOCK_SUBABORT_RESTART:
3108 case TBLOCK_PREPARE:
3109 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3110 BlockStateAsString(s->blockState));
3114 foreach(cell, options)
3116 DefElem *elem = lfirst(cell);
3118 if (strcmp(elem->defname, "savepoint_name") == 0)
3119 name = strVal(elem->arg);
3122 Assert(PointerIsValid(name));
3124 for (target = s; PointerIsValid(target); target = target->parent)
3126 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3130 if (!PointerIsValid(target))
3132 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3133 errmsg("no such savepoint")));
3135 /* disallow crossing savepoint level boundaries */
3136 if (target->savepointLevel != s->savepointLevel)
3138 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3139 errmsg("no such savepoint")));
3142 * Mark "commit pending" all subtransactions up to the target
3143 * subtransaction. The actual commits will happen when control gets to
3144 * CommitTransactionCommand.
3146 xact = CurrentTransactionState;
3149 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3150 xact->blockState = TBLOCK_SUBEND;
3153 xact = xact->parent;
3154 Assert(PointerIsValid(xact));
3159 * RollbackToSavepoint
3160 * This executes a ROLLBACK TO <savepoint> command.
3162 * As above, we don't actually do anything here except change blockState.
3165 RollbackToSavepoint(List *options)
3167 TransactionState s = CurrentTransactionState;
3168 TransactionState target,
3173 switch (s->blockState)
3176 * We can't rollback to a savepoint if there is no savepoint
3179 case TBLOCK_INPROGRESS:
3182 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3183 errmsg("no such savepoint")));
3187 * There is at least one savepoint, so proceed.
3189 case TBLOCK_SUBINPROGRESS:
3190 case TBLOCK_SUBABORT:
3193 /* These cases are invalid. */
3194 case TBLOCK_DEFAULT:
3195 case TBLOCK_STARTED:
3197 case TBLOCK_SUBBEGIN:
3200 case TBLOCK_ABORT_END:
3201 case TBLOCK_SUBABORT_END:
3202 case TBLOCK_ABORT_PENDING:
3203 case TBLOCK_SUBABORT_PENDING:
3204 case TBLOCK_SUBRESTART:
3205 case TBLOCK_SUBABORT_RESTART:
3206 case TBLOCK_PREPARE:
3207 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3208 BlockStateAsString(s->blockState));
3212 foreach(cell, options)
3214 DefElem *elem = lfirst(cell);
3216 if (strcmp(elem->defname, "savepoint_name") == 0)
3217 name = strVal(elem->arg);
3220 Assert(PointerIsValid(name));
3222 for (target = s; PointerIsValid(target); target = target->parent)
3224 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3228 if (!PointerIsValid(target))
3230 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3231 errmsg("no such savepoint")));
3233 /* disallow crossing savepoint level boundaries */
3234 if (target->savepointLevel != s->savepointLevel)
3236 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3237 errmsg("no such savepoint")));
3240 * Mark "abort pending" all subtransactions up to the target
3241 * subtransaction. The actual aborts will happen when control gets to
3242 * CommitTransactionCommand.
3244 xact = CurrentTransactionState;
3249 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3250 xact->blockState = TBLOCK_SUBABORT_PENDING;
3251 else if (xact->blockState == TBLOCK_SUBABORT)
3252 xact->blockState = TBLOCK_SUBABORT_END;
3254 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3255 BlockStateAsString(xact->blockState));
3256 xact = xact->parent;
3257 Assert(PointerIsValid(xact));
3260 /* And mark the target as "restart pending" */
3261 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3262 xact->blockState = TBLOCK_SUBRESTART;
3263 else if (xact->blockState == TBLOCK_SUBABORT)
3264 xact->blockState = TBLOCK_SUBABORT_RESTART;
3266 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3267 BlockStateAsString(xact->blockState));
3271 * BeginInternalSubTransaction
3272 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3273 * state, and therefore it can safely be used in a function that might
3274 * be called when not inside a BEGIN block. Also, we automatically
3275 * cycle through CommitTransactionCommand/StartTransactionCommand
3276 * instead of expecting the caller to do it.
3279 BeginInternalSubTransaction(char *name)
3281 TransactionState s = CurrentTransactionState;
3283 switch (s->blockState)
3285 case TBLOCK_STARTED:
3286 case TBLOCK_INPROGRESS:
3287 case TBLOCK_SUBINPROGRESS:
3288 /* Normal subtransaction start */
3290 s = CurrentTransactionState; /* changed by push */
3293 * Savepoint names, like the TransactionState block itself, live
3294 * in TopTransactionContext.
3297 s->name = MemoryContextStrdup(TopTransactionContext, name);
3300 /* These cases are invalid. */
3301 case TBLOCK_DEFAULT:
3303 case TBLOCK_SUBBEGIN:
3307 case TBLOCK_SUBABORT:
3308 case TBLOCK_ABORT_END:
3309 case TBLOCK_SUBABORT_END:
3310 case TBLOCK_ABORT_PENDING:
3311 case TBLOCK_SUBABORT_PENDING:
3312 case TBLOCK_SUBRESTART:
3313 case TBLOCK_SUBABORT_RESTART:
3314 case TBLOCK_PREPARE:
3315 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3316 BlockStateAsString(s->blockState));
3320 CommitTransactionCommand();
3321 StartTransactionCommand();
3325 * ReleaseCurrentSubTransaction
3327 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3328 * savepoint name (if any).
3329 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3332 ReleaseCurrentSubTransaction(void)
3334 TransactionState s = CurrentTransactionState;
3336 if (s->blockState != TBLOCK_SUBINPROGRESS)
3337 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3338 BlockStateAsString(s->blockState));
3339 Assert(s->state == TRANS_INPROGRESS);
3340 MemoryContextSwitchTo(CurTransactionContext);
3341 CommitSubTransaction();
3342 s = CurrentTransactionState; /* changed by pop */
3343 Assert(s->state == TRANS_INPROGRESS);
3347 * RollbackAndReleaseCurrentSubTransaction
3349 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3350 * of its savepoint name (if any).
3351 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3354 RollbackAndReleaseCurrentSubTransaction(void)
3356 TransactionState s = CurrentTransactionState;
3358 switch (s->blockState)
3360 /* Must be in a subtransaction */
3361 case TBLOCK_SUBINPROGRESS:
3362 case TBLOCK_SUBABORT:
3365 /* These cases are invalid. */
3366 case TBLOCK_DEFAULT:
3367 case TBLOCK_STARTED:
3369 case TBLOCK_SUBBEGIN:
3370 case TBLOCK_INPROGRESS:
3374 case TBLOCK_ABORT_END:
3375 case TBLOCK_SUBABORT_END:
3376 case TBLOCK_ABORT_PENDING:
3377 case TBLOCK_SUBABORT_PENDING:
3378 case TBLOCK_SUBRESTART:
3379 case TBLOCK_SUBABORT_RESTART:
3380 case TBLOCK_PREPARE:
3381 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3382 BlockStateAsString(s->blockState));
3387 * Abort the current subtransaction, if needed.
3389 if (s->blockState == TBLOCK_SUBINPROGRESS)
3390 AbortSubTransaction();
3392 /* And clean it up, too */
3393 CleanupSubTransaction();
3395 s = CurrentTransactionState; /* changed by pop */
3396 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3397 s->blockState == TBLOCK_INPROGRESS ||
3398 s->blockState == TBLOCK_STARTED);
3402 * AbortOutOfAnyTransaction
3404 * This routine is provided for error recovery purposes. It aborts any
3405 * active transaction or transaction block, leaving the system in a known
3409 AbortOutOfAnyTransaction(void)
3411 TransactionState s = CurrentTransactionState;
3414 * Get out of any transaction or nested transaction
3418 switch (s->blockState)
3420 case TBLOCK_DEFAULT:
3421 /* Not in a transaction, do nothing */
3423 case TBLOCK_STARTED:
3425 case TBLOCK_INPROGRESS:
3427 case TBLOCK_ABORT_PENDING:
3428 case TBLOCK_PREPARE:
3429 /* In a transaction, so clean up */
3431 CleanupTransaction();
3432 s->blockState = TBLOCK_DEFAULT;
3435 case TBLOCK_ABORT_END:
3436 /* AbortTransaction already done, still need Cleanup */
3437 CleanupTransaction();
3438 s->blockState = TBLOCK_DEFAULT;
3442 * In a subtransaction, so clean it up and abort parent too
3444 case TBLOCK_SUBBEGIN:
3445 case TBLOCK_SUBINPROGRESS:
3447 case TBLOCK_SUBABORT_PENDING:
3448 case TBLOCK_SUBRESTART:
3449 AbortSubTransaction();
3450 CleanupSubTransaction();
3451 s = CurrentTransactionState; /* changed by pop */
3454 case TBLOCK_SUBABORT:
3455 case TBLOCK_SUBABORT_END:
3456 case TBLOCK_SUBABORT_RESTART:
3457 /* As above, but AbortSubTransaction already done */
3458 CleanupSubTransaction();
3459 s = CurrentTransactionState; /* changed by pop */
3462 } while (s->blockState != TBLOCK_DEFAULT);
3464 /* Should be out of all subxacts now */
3465 Assert(s->parent == NULL);
3469 * IsTransactionBlock --- are we within a transaction block?
3472 IsTransactionBlock(void)
3474 TransactionState s = CurrentTransactionState;
3476 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3483 * IsTransactionOrTransactionBlock --- are we within either a transaction
3484 * or a transaction block? (The backend is only really "idle" when this
3487 * This should match up with IsTransactionBlock and IsTransactionState.
3490 IsTransactionOrTransactionBlock(void)
3492 TransactionState s = CurrentTransactionState;
3494 if (s->blockState == TBLOCK_DEFAULT)
3501 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3504 TransactionBlockStatusCode(void)
3506 TransactionState s = CurrentTransactionState;
3508 switch (s->blockState)
3510 case TBLOCK_DEFAULT:
3511 case TBLOCK_STARTED:
3512 return 'I'; /* idle --- not in transaction */
3514 case TBLOCK_SUBBEGIN:
3515 case TBLOCK_INPROGRESS:
3516 case TBLOCK_SUBINPROGRESS:
3519 case TBLOCK_PREPARE:
3520 return 'T'; /* in transaction */
3522 case TBLOCK_SUBABORT:
3523 case TBLOCK_ABORT_END:
3524 case TBLOCK_SUBABORT_END:
3525 case TBLOCK_ABORT_PENDING:
3526 case TBLOCK_SUBABORT_PENDING:
3527 case TBLOCK_SUBRESTART:
3528 case TBLOCK_SUBABORT_RESTART:
3529 return 'E'; /* in failed transaction */
3532 /* should never get here */
3533 elog(FATAL, "invalid transaction block state: %s",
3534 BlockStateAsString(s->blockState));
3535 return 0; /* keep compiler quiet */
3542 IsSubTransaction(void)
3544 TransactionState s = CurrentTransactionState;
3546 if (s->nestingLevel >= 2)
3553 * StartSubTransaction
3555 * If you're wondering why this is separate from PushTransaction: it's because
3556 * we can't conveniently do this stuff right inside DefineSavepoint. The
3557 * SAVEPOINT utility command will be executed inside a Portal, and if we
3558 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3559 * the Portal will undo those settings. So we make DefineSavepoint just
3560 * push a dummy transaction block, and when control returns to the main
3561 * idle loop, CommitTransactionCommand will be called, and we'll come here
3562 * to finish starting the subtransaction.
3565 StartSubTransaction(void)
3567 TransactionState s = CurrentTransactionState;
3569 if (s->state != TRANS_DEFAULT)
3570 elog(WARNING, "StartSubTransaction while in %s state",
3571 TransStateAsString(s->state));
3573 s->state = TRANS_START;
3576 * Initialize subsystems for new subtransaction
3578 * must initialize resource-management stuff first
3580 AtSubStart_Memory();
3581 AtSubStart_ResourceOwner();
3583 AtSubStart_Notify();
3584 AfterTriggerBeginSubXact();
3586 s->state = TRANS_INPROGRESS;
3589 * Call start-of-subxact callbacks
3591 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3592 s->parent->subTransactionId);
3594 ShowTransactionState("StartSubTransaction");
3598 * CommitSubTransaction
3600 * The caller has to make sure to always reassign CurrentTransactionState
3601 * if it has a local pointer to it after calling this function.
3604 CommitSubTransaction(void)
3606 TransactionState s = CurrentTransactionState;
3608 ShowTransactionState("CommitSubTransaction");
3610 if (s->state != TRANS_INPROGRESS)
3611 elog(WARNING, "CommitSubTransaction while in %s state",
3612 TransStateAsString(s->state));
3614 /* Pre-commit processing goes here -- nothing to do at the moment */
3616 s->state = TRANS_COMMIT;
3618 /* Must CCI to ensure commands of subtransaction are seen as done */
3619 CommandCounterIncrement();
3621 /* Mark subtransaction as subcommitted */
3622 if (TransactionIdIsValid(s->transactionId))
3624 RecordSubTransactionCommit();
3625 AtSubCommit_childXids();
3628 /* Post-commit cleanup */
3629 AfterTriggerEndSubXact(true);
3630 AtSubCommit_Portals(s->subTransactionId,
3631 s->parent->subTransactionId,
3632 s->parent->curTransactionOwner);
3633 AtEOSubXact_LargeObject(true, s->subTransactionId,
3634 s->parent->subTransactionId);
3635 AtSubCommit_Notify();
3636 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3637 s->parent->subTransactionId);
3639 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3640 s->parent->subTransactionId);
3642 ResourceOwnerRelease(s->curTransactionOwner,
3643 RESOURCE_RELEASE_BEFORE_LOCKS,
3645 AtEOSubXact_RelationCache(true, s->subTransactionId,
3646 s->parent->subTransactionId);
3647 AtEOSubXact_Inval(true);
3651 * The only lock we actually release here is the subtransaction XID lock.
3652 * The rest just get transferred to the parent resource owner.
3654 CurrentResourceOwner = s->curTransactionOwner;
3655 if (TransactionIdIsValid(s->transactionId))
3656 XactLockTableDelete(s->transactionId);
3658 ResourceOwnerRelease(s->curTransactionOwner,
3659 RESOURCE_RELEASE_LOCKS,
3661 ResourceOwnerRelease(s->curTransactionOwner,
3662 RESOURCE_RELEASE_AFTER_LOCKS,
3665 AtEOXact_GUC(true, true);
3666 AtEOSubXact_SPI(true, s->subTransactionId);
3667 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3668 s->parent->subTransactionId);
3669 AtEOSubXact_Namespace(true, s->subTransactionId,
3670 s->parent->subTransactionId);
3671 AtEOSubXact_Files(true, s->subTransactionId,
3672 s->parent->subTransactionId);
3675 * We need to restore the upper transaction's read-only state, in case the
3676 * upper is read-write while the child is read-only; GUC will incorrectly
3677 * think it should leave the child state in place.
3679 XactReadOnly = s->prevXactReadOnly;
3681 CurrentResourceOwner = s->parent->curTransactionOwner;
3682 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3683 ResourceOwnerDelete(s->curTransactionOwner);
3684 s->curTransactionOwner = NULL;
3686 AtSubCommit_Memory();
3688 s->state = TRANS_DEFAULT;
3694 * AbortSubTransaction
3697 AbortSubTransaction(void)
3699 TransactionState s = CurrentTransactionState;
3701 ShowTransactionState("AbortSubTransaction");
3703 if (s->state != TRANS_INPROGRESS)
3704 elog(WARNING, "AbortSubTransaction while in %s state",
3705 TransStateAsString(s->state));
3709 s->state = TRANS_ABORT;
3712 * Release any LW locks we might be holding as quickly as possible.
3713 * (Regular locks, however, must be held till we finish aborting.)
3714 * Releasing LW locks is critical since we might try to grab them again
3715 * while cleaning up!
3717 * FIXME This may be incorrect --- Are there some locks we should keep?
3718 * Buffer locks, for example? I don't think so but I'm not sure.
3728 * do abort processing
3730 AtSubAbort_Memory();
3731 AtSubAbort_ResourceOwner();
3734 * We can skip all this stuff if the subxact failed before creating a
3737 if (s->curTransactionOwner)
3739 AfterTriggerEndSubXact(false);
3740 AtSubAbort_Portals(s->subTransactionId,
3741 s->parent->subTransactionId,
3742 s->parent->curTransactionOwner);
3743 AtEOSubXact_LargeObject(false, s->subTransactionId,
3744 s->parent->subTransactionId);
3745 AtSubAbort_Notify();
3746 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3747 s->parent->subTransactionId);
3749 /* Advertise the fact that we aborted in pg_clog. */
3750 if (TransactionIdIsValid(s->transactionId))
3752 RecordSubTransactionAbort();
3753 AtSubAbort_childXids();
3756 /* Post-abort cleanup */
3757 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3758 s->parent->subTransactionId);
3760 ResourceOwnerRelease(s->curTransactionOwner,
3761 RESOURCE_RELEASE_BEFORE_LOCKS,
3763 AtEOSubXact_RelationCache(false, s->subTransactionId,
3764 s->parent->subTransactionId);
3765 AtEOSubXact_Inval(false);
3767 ResourceOwnerRelease(s->curTransactionOwner,
3768 RESOURCE_RELEASE_LOCKS,
3770 ResourceOwnerRelease(s->curTransactionOwner,
3771 RESOURCE_RELEASE_AFTER_LOCKS,
3774 AtEOXact_GUC(false, true);
3775 AtEOSubXact_SPI(false, s->subTransactionId);
3776 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3777 s->parent->subTransactionId);
3778 AtEOSubXact_Namespace(false, s->subTransactionId,
3779 s->parent->subTransactionId);
3780 AtEOSubXact_Files(false, s->subTransactionId,
3781 s->parent->subTransactionId);
3785 * Reset user id which might have been changed transiently. Here we want
3786 * to restore to the userid that was current at subxact entry. (As in
3787 * AbortTransaction, we need not worry about the session userid.)
3789 * Must do this after AtEOXact_GUC to handle the case where we entered the
3790 * subxact inside a SECURITY DEFINER function (hence current and session
3791 * userids were different) and then session auth was changed inside the
3792 * subxact. GUC will reset both current and session userids to the
3793 * entry-time session userid. This is right in every other scenario so it
3794 * seems simplest to let GUC do that and fix it here.
3796 SetUserId(s->currentUser);
3799 * Restore the upper transaction's read-only state, too. This should be
3800 * redundant with GUC's cleanup but we may as well do it for consistency
3801 * with the commit case.
3803 XactReadOnly = s->prevXactReadOnly;
3805 RESUME_INTERRUPTS();
3809 * CleanupSubTransaction
3811 * The caller has to make sure to always reassign CurrentTransactionState
3812 * if it has a local pointer to it after calling this function.
3815 CleanupSubTransaction(void)
3817 TransactionState s = CurrentTransactionState;
3819 ShowTransactionState("CleanupSubTransaction");
3821 if (s->state != TRANS_ABORT)
3822 elog(WARNING, "CleanupSubTransaction while in %s state",
3823 TransStateAsString(s->state));
3825 AtSubCleanup_Portals(s->subTransactionId);
3827 CurrentResourceOwner = s->parent->curTransactionOwner;
3828 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3829 if (s->curTransactionOwner)
3830 ResourceOwnerDelete(s->curTransactionOwner);
3831 s->curTransactionOwner = NULL;
3833 AtSubCleanup_Memory();
3835 s->state = TRANS_DEFAULT;
3842 * Create transaction state stack entry for a subtransaction
3844 * The caller has to make sure to always reassign CurrentTransactionState
3845 * if it has a local pointer to it after calling this function.
3848 PushTransaction(void)
3850 TransactionState p = CurrentTransactionState;
3855 * At present, GetUserId cannot fail, but let's not assume that. Get the
3856 * ID before entering the critical code sequence.
3858 currentUser = GetUserId();
3861 * We keep subtransaction state nodes in TopTransactionContext.
3863 s = (TransactionState)
3864 MemoryContextAllocZero(TopTransactionContext,
3865 sizeof(TransactionStateData));
3868 * Assign a subtransaction ID, watching out for counter wraparound.
3870 currentSubTransactionId += 1;
3871 if (currentSubTransactionId == InvalidSubTransactionId)
3873 currentSubTransactionId -= 1;
3876 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3877 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3881 * We can now stack a minimally valid subtransaction without fear of
3884 s->transactionId = InvalidTransactionId; /* until assigned */
3885 s->subTransactionId = currentSubTransactionId;
3887 s->nestingLevel = p->nestingLevel + 1;
3888 s->savepointLevel = p->savepointLevel;
3889 s->state = TRANS_DEFAULT;
3890 s->blockState = TBLOCK_SUBBEGIN;
3891 s->currentUser = currentUser;
3892 s->prevXactReadOnly = XactReadOnly;
3894 CurrentTransactionState = s;
3897 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3898 * with the subtransaction from here on out; in particular they should not
3899 * assume that it necessarily has a transaction context, resource owner,
3906 * Pop back to parent transaction state
3908 * The caller has to make sure to always reassign CurrentTransactionState
3909 * if it has a local pointer to it after calling this function.
3912 PopTransaction(void)
3914 TransactionState s = CurrentTransactionState;
3916 if (s->state != TRANS_DEFAULT)
3917 elog(WARNING, "PopTransaction while in %s state",
3918 TransStateAsString(s->state));
3920 if (s->parent == NULL)
3921 elog(FATAL, "PopTransaction with no parent");
3923 CurrentTransactionState = s->parent;
3925 /* Let's just make sure CurTransactionContext is good */
3926 CurTransactionContext = s->parent->curTransactionContext;
3927 MemoryContextSwitchTo(CurTransactionContext);
3929 /* Ditto for ResourceOwner links */
3930 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3931 CurrentResourceOwner = s->parent->curTransactionOwner;
3933 /* Free the old child structure */
3940 * ShowTransactionState
3944 ShowTransactionState(const char *str)
3946 /* skip work if message will definitely not be printed */
3947 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3949 elog(DEBUG3, "%s", str);
3950 ShowTransactionStateRec(CurrentTransactionState);
3955 * ShowTransactionStateRec
3956 * Recursive subroutine for ShowTransactionState
3959 ShowTransactionStateRec(TransactionState s)
3962 ShowTransactionStateRec(s->parent);
3964 /* use ereport to suppress computation if msg will not be printed */
3966 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3967 PointerIsValid(s->name) ? s->name : "unnamed",
3968 BlockStateAsString(s->blockState),
3969 TransStateAsString(s->state),
3970 (unsigned int) s->transactionId,
3971 (unsigned int) s->subTransactionId,
3972 (unsigned int) currentCommandId,
3974 nodeToString(s->childXids))));
3978 * BlockStateAsString
3982 BlockStateAsString(TBlockState blockState)
3986 case TBLOCK_DEFAULT:
3988 case TBLOCK_STARTED:
3992 case TBLOCK_INPROGRESS:
3993 return "INPROGRESS";
3998 case TBLOCK_ABORT_END:
4000 case TBLOCK_ABORT_PENDING:
4001 return "ABORT PEND";
4002 case TBLOCK_PREPARE:
4004 case TBLOCK_SUBBEGIN:
4006 case TBLOCK_SUBINPROGRESS:
4007 return "SUB INPROGRS";
4010 case TBLOCK_SUBABORT:
4012 case TBLOCK_SUBABORT_END:
4013 return "SUB ABORT END";
4014 case TBLOCK_SUBABORT_PENDING:
4015 return "SUB ABRT PEND";
4016 case TBLOCK_SUBRESTART:
4017 return "SUB RESTART";
4018 case TBLOCK_SUBABORT_RESTART:
4019 return "SUB AB RESTRT";
4021 return "UNRECOGNIZED";
4025 * TransStateAsString
4029 TransStateAsString(TransState state)
4037 case TRANS_INPROGRESS:
4046 return "UNRECOGNIZED";
4050 * xactGetCommittedChildren
4052 * Gets the list of committed children of the current transaction. The return
4053 * value is the number of child transactions. *children is set to point to a
4054 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4058 xactGetCommittedChildren(TransactionId **ptr)
4060 TransactionState s = CurrentTransactionState;
4062 TransactionId *children;
4065 nchildren = list_length(s->childXids);
4072 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4075 foreach(p, s->childXids)
4077 TransactionId child = lfirst_xid(p);
4079 *children++ = child;
4086 * XLOG support routines
4090 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4092 TransactionId *sub_xids;
4093 TransactionId max_xid;
4096 TransactionIdCommit(xid);
4098 /* Mark committed subtransactions as committed */
4099 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4100 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4102 /* Make sure nextXid is beyond any XID mentioned in the record */
4104 for (i = 0; i < xlrec->nsubxacts; i++)
4106 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4107 max_xid = sub_xids[i];
4109 if (TransactionIdFollowsOrEquals(max_xid,
4110 ShmemVariableCache->nextXid))
4112 ShmemVariableCache->nextXid = max_xid;
4113 TransactionIdAdvance(ShmemVariableCache->nextXid);
4116 /* Make sure files supposed to be dropped are dropped */
4117 for (i = 0; i < xlrec->nrels; i++)
4119 XLogDropRelation(xlrec->xnodes[i]);
4120 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4125 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4127 TransactionId *sub_xids;
4128 TransactionId max_xid;
4131 TransactionIdAbort(xid);
4133 /* Mark subtransactions as aborted */
4134 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4135 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4137 /* Make sure nextXid is beyond any XID mentioned in the record */
4139 for (i = 0; i < xlrec->nsubxacts; i++)
4141 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4142 max_xid = sub_xids[i];
4144 if (TransactionIdFollowsOrEquals(max_xid,
4145 ShmemVariableCache->nextXid))
4147 ShmemVariableCache->nextXid = max_xid;
4148 TransactionIdAdvance(ShmemVariableCache->nextXid);
4151 /* Make sure files supposed to be dropped are dropped */
4152 for (i = 0; i < xlrec->nrels; i++)
4154 XLogDropRelation(xlrec->xnodes[i]);
4155 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4160 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4162 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4164 if (info == XLOG_XACT_COMMIT)
4166 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4168 xact_redo_commit(xlrec, record->xl_xid);
4170 else if (info == XLOG_XACT_ABORT)
4172 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4174 xact_redo_abort(xlrec, record->xl_xid);
4176 else if (info == XLOG_XACT_PREPARE)
4178 /* the record contents are exactly the 2PC file */
4179 RecreateTwoPhaseFile(record->xl_xid,
4180 XLogRecGetData(record), record->xl_len);
4182 else if (info == XLOG_XACT_COMMIT_PREPARED)
4184 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4186 xact_redo_commit(&xlrec->crec, xlrec->xid);
4187 RemoveTwoPhaseFile(xlrec->xid, false);
4189 else if (info == XLOG_XACT_ABORT_PREPARED)
4191 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4193 xact_redo_abort(&xlrec->arec, xlrec->xid);
4194 RemoveTwoPhaseFile(xlrec->xid, false);
4197 elog(PANIC, "xact_redo: unknown op code %u", info);
4201 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4203 struct tm *tm = localtime(&xlrec->xtime);
4206 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4207 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4208 tm->tm_hour, tm->tm_min, tm->tm_sec);
4209 if (xlrec->nrels > 0)
4211 appendStringInfo(buf, "; rels:");
4212 for (i = 0; i < xlrec->nrels; i++)
4214 RelFileNode rnode = xlrec->xnodes[i];
4216 appendStringInfo(buf, " %u/%u/%u",
4217 rnode.spcNode, rnode.dbNode, rnode.relNode);
4220 if (xlrec->nsubxacts > 0)
4222 TransactionId *xacts = (TransactionId *)
4223 &xlrec->xnodes[xlrec->nrels];
4225 appendStringInfo(buf, "; subxacts:");
4226 for (i = 0; i < xlrec->nsubxacts; i++)
4227 appendStringInfo(buf, " %u", xacts[i]);
4232 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4234 struct tm *tm = localtime(&xlrec->xtime);
4237 appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
4238 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4239 tm->tm_hour, tm->tm_min, tm->tm_sec);
4240 if (xlrec->nrels > 0)
4242 appendStringInfo(buf, "; rels:");
4243 for (i = 0; i < xlrec->nrels; i++)
4245 RelFileNode rnode = xlrec->xnodes[i];
4247 appendStringInfo(buf, " %u/%u/%u",
4248 rnode.spcNode, rnode.dbNode, rnode.relNode);
4251 if (xlrec->nsubxacts > 0)
4253 TransactionId *xacts = (TransactionId *)
4254 &xlrec->xnodes[xlrec->nrels];
4256 appendStringInfo(buf, "; subxacts:");
4257 for (i = 0; i < xlrec->nsubxacts; i++)
4258 appendStringInfo(buf, " %u", xacts[i]);
4263 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4265 uint8 info = xl_info & ~XLR_INFO_MASK;
4267 if (info == XLOG_XACT_COMMIT)
4269 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4271 appendStringInfo(buf, "commit: ");
4272 xact_desc_commit(buf, xlrec);
4274 else if (info == XLOG_XACT_ABORT)
4276 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4278 appendStringInfo(buf, "abort: ");
4279 xact_desc_abort(buf, xlrec);
4281 else if (info == XLOG_XACT_PREPARE)
4283 appendStringInfo(buf, "prepare");
4285 else if (info == XLOG_XACT_COMMIT_PREPARED)
4287 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4289 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4290 xact_desc_commit(buf, &xlrec->crec);
4292 else if (info == XLOG_XACT_ABORT_PREPARED)
4294 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4296 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4297 xact_desc_abort(buf, &xlrec->arec);
4300 appendStringInfo(buf, "UNKNOWN");