1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2008, 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.257 2008/01/15 18:56:59 tgl Exp $
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
37 #include "storage/fd.h"
38 #include "storage/lmgr.h"
39 #include "storage/procarray.h"
40 #include "storage/sinvaladt.h"
41 #include "storage/smgr.h"
42 #include "utils/combocid.h"
43 #include "utils/flatfiles.h"
44 #include "utils/guc.h"
45 #include "utils/inval.h"
46 #include "utils/memutils.h"
47 #include "utils/relcache.h"
48 #include "utils/xml.h"
52 * User-tweakable parameters
54 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
57 bool DefaultXactReadOnly = false;
60 bool XactSyncCommit = true;
62 int CommitDelay = 0; /* precommit delay in microseconds */
63 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
67 * transaction states - transaction state from server perspective
69 typedef enum TransState
71 TRANS_DEFAULT, /* idle */
72 TRANS_START, /* transaction starting */
73 TRANS_INPROGRESS, /* inside a valid transaction */
74 TRANS_COMMIT, /* commit in progress */
75 TRANS_ABORT, /* abort in progress */
76 TRANS_PREPARE /* prepare in progress */
80 * transaction block states - transaction state of client queries
82 * Note: the subtransaction states are used only for non-topmost
83 * transactions; the others appear only in the topmost transaction.
85 typedef enum TBlockState
87 /* not-in-transaction-block states */
88 TBLOCK_DEFAULT, /* idle */
89 TBLOCK_STARTED, /* running single-query transaction */
91 /* transaction block states */
92 TBLOCK_BEGIN, /* starting transaction block */
93 TBLOCK_INPROGRESS, /* live transaction */
94 TBLOCK_END, /* COMMIT received */
95 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
96 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
97 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
98 TBLOCK_PREPARE, /* live xact, PREPARE received */
100 /* subtransaction states */
101 TBLOCK_SUBBEGIN, /* starting a subtransaction */
102 TBLOCK_SUBINPROGRESS, /* live subtransaction */
103 TBLOCK_SUBEND, /* RELEASE received */
104 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
105 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
106 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
107 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
108 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
112 * transaction state structure
114 typedef struct TransactionStateData
116 TransactionId transactionId; /* my XID, or Invalid if none */
117 SubTransactionId subTransactionId; /* my subxact ID */
118 char *name; /* savepoint name, if any */
119 int savepointLevel; /* savepoint level */
120 TransState state; /* low-level state */
121 TBlockState blockState; /* high-level state */
122 int nestingLevel; /* transaction nesting depth */
123 int gucNestLevel; /* GUC context nesting depth */
124 MemoryContext curTransactionContext; /* my xact-lifetime context */
125 ResourceOwner curTransactionOwner; /* my query resources */
126 List *childXids; /* subcommitted child XIDs */
127 Oid prevUser; /* previous CurrentUserId setting */
128 bool prevSecDefCxt; /* previous SecurityDefinerContext setting */
129 bool prevXactReadOnly; /* entry-time xact r/o state */
130 struct TransactionStateData *parent; /* back link to parent */
131 } TransactionStateData;
133 typedef TransactionStateData *TransactionState;
136 * CurrentTransactionState always points to the current transaction state
137 * block. It will point to TopTransactionStateData when not in a
138 * transaction at all, or when in a top-level transaction.
140 static TransactionStateData TopTransactionStateData = {
141 0, /* transaction id */
142 0, /* subtransaction id */
143 NULL, /* savepoint name */
144 0, /* savepoint level */
145 TRANS_DEFAULT, /* transaction state */
146 TBLOCK_DEFAULT, /* transaction block state from the client
148 0, /* transaction nesting depth */
149 0, /* GUC context nesting depth */
150 NULL, /* cur transaction context */
151 NULL, /* cur transaction resource owner */
152 NIL, /* subcommitted child Xids */
153 InvalidOid, /* previous CurrentUserId setting */
154 false, /* previous SecurityDefinerContext setting */
155 false, /* entry-time xact r/o state */
156 NULL /* link to parent state block */
159 static TransactionState CurrentTransactionState = &TopTransactionStateData;
162 * The subtransaction ID and command ID assignment counters are global
163 * to a whole transaction, so we do not keep them in the state stack.
165 static SubTransactionId currentSubTransactionId;
166 static CommandId currentCommandId;
167 static bool currentCommandIdUsed;
170 * xactStartTimestamp is the value of transaction_timestamp().
171 * stmtStartTimestamp is the value of statement_timestamp().
172 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
173 * These do not change as we enter and exit subtransactions, so we don't
174 * keep them inside the TransactionState stack.
176 static TimestampTz xactStartTimestamp;
177 static TimestampTz stmtStartTimestamp;
178 static TimestampTz xactStopTimestamp;
181 * GID to be used for preparing the current transaction. This is also
182 * global to a whole transaction, so we don't keep it in the state stack.
184 static char *prepareGID;
187 * Some commands want to force synchronous commit.
189 static bool forceSyncCommit = false;
192 * Private context for transaction-abort work --- we reserve space for this
193 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
194 * when we've run out of memory.
196 static MemoryContext TransactionAbortContext = NULL;
199 * List of add-on start- and end-of-xact callbacks
201 typedef struct XactCallbackItem
203 struct XactCallbackItem *next;
204 XactCallback callback;
208 static XactCallbackItem *Xact_callbacks = NULL;
211 * List of add-on start- and end-of-subxact callbacks
213 typedef struct SubXactCallbackItem
215 struct SubXactCallbackItem *next;
216 SubXactCallback callback;
218 } SubXactCallbackItem;
220 static SubXactCallbackItem *SubXact_callbacks = NULL;
223 /* local function prototypes */
224 static void AssignTransactionId(TransactionState s);
225 static void AbortTransaction(void);
226 static void AtAbort_Memory(void);
227 static void AtCleanup_Memory(void);
228 static void AtAbort_ResourceOwner(void);
229 static void AtCommit_LocalCache(void);
230 static void AtCommit_Memory(void);
231 static void AtStart_Cache(void);
232 static void AtStart_Memory(void);
233 static void AtStart_ResourceOwner(void);
234 static void CallXactCallbacks(XactEvent event);
235 static void CallSubXactCallbacks(SubXactEvent event,
236 SubTransactionId mySubid,
237 SubTransactionId parentSubid);
238 static void CleanupTransaction(void);
239 static void CommitTransaction(void);
240 static TransactionId RecordTransactionAbort(bool isSubXact);
241 static void StartTransaction(void);
243 static void RecordSubTransactionCommit(void);
244 static void StartSubTransaction(void);
245 static void CommitSubTransaction(void);
246 static void AbortSubTransaction(void);
247 static void CleanupSubTransaction(void);
248 static void PushTransaction(void);
249 static void PopTransaction(void);
251 static void AtSubAbort_Memory(void);
252 static void AtSubCleanup_Memory(void);
253 static void AtSubAbort_ResourceOwner(void);
254 static void AtSubCommit_Memory(void);
255 static void AtSubStart_Memory(void);
256 static void AtSubStart_ResourceOwner(void);
258 static void ShowTransactionState(const char *str);
259 static void ShowTransactionStateRec(TransactionState state);
260 static const char *BlockStateAsString(TBlockState blockState);
261 static const char *TransStateAsString(TransState state);
264 /* ----------------------------------------------------------------
265 * transaction state accessors
266 * ----------------------------------------------------------------
272 * This returns true if we are inside a valid transaction; that is,
273 * it is safe to initiate database access, take heavyweight locks, etc.
276 IsTransactionState(void)
278 TransactionState s = CurrentTransactionState;
281 * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we
282 * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
283 * TRANS_PREPARE since it might be too soon or too late within those
284 * transition states to do anything interesting. Hence, the only "valid"
285 * state is TRANS_INPROGRESS.
287 return (s->state == TRANS_INPROGRESS);
291 * IsAbortedTransactionBlockState
293 * This returns true if we are currently running a query
294 * within an aborted transaction block.
297 IsAbortedTransactionBlockState(void)
299 TransactionState s = CurrentTransactionState;
301 if (s->blockState == TBLOCK_ABORT ||
302 s->blockState == TBLOCK_SUBABORT)
310 * GetTopTransactionId
312 * This will return the XID of the main transaction, assigning one if
313 * it's not yet set. Be careful to call this only inside a valid xact.
316 GetTopTransactionId(void)
318 if (!TransactionIdIsValid(TopTransactionStateData.transactionId))
319 AssignTransactionId(&TopTransactionStateData);
320 return TopTransactionStateData.transactionId;
324 * GetTopTransactionIdIfAny
326 * This will return the XID of the main transaction, if one is assigned.
327 * It will return InvalidTransactionId if we are not currently inside a
328 * transaction, or inside a transaction that hasn't yet been assigned an XID.
331 GetTopTransactionIdIfAny(void)
333 return TopTransactionStateData.transactionId;
337 * GetCurrentTransactionId
339 * This will return the XID of the current transaction (main or sub
340 * transaction), assigning one if it's not yet set. Be careful to call this
341 * only inside a valid xact.
344 GetCurrentTransactionId(void)
346 TransactionState s = CurrentTransactionState;
348 if (!TransactionIdIsValid(s->transactionId))
349 AssignTransactionId(s);
350 return s->transactionId;
354 * GetCurrentTransactionIdIfAny
356 * This will return the XID of the current sub xact, if one is assigned.
357 * It will return InvalidTransactionId if we are not currently inside a
358 * transaction, or inside a transaction that hasn't been assigned an XID yet.
361 GetCurrentTransactionIdIfAny(void)
363 return CurrentTransactionState->transactionId;
368 * AssignTransactionId
370 * Assigns a new permanent XID to the given TransactionState.
371 * We do not assign XIDs to transactions until/unless this is called.
372 * Also, any parent TransactionStates that don't yet have XIDs are assigned
373 * one; this maintains the invariant that a child transaction has an XID
374 * following its parent's.
377 AssignTransactionId(TransactionState s)
379 bool isSubXact = (s->parent != NULL);
380 ResourceOwner currentOwner;
382 /* Assert that caller didn't screw up */
383 Assert(!TransactionIdIsValid(s->transactionId));
384 Assert(s->state == TRANS_INPROGRESS);
387 * Ensure parent(s) have XIDs, so that a child always has an XID later
390 if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
391 AssignTransactionId(s->parent);
394 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
396 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
397 * shared storage other than PG_PROC; because if there's no room for it in
398 * PG_PROC, the subtrans entry is needed to ensure that other backends see
399 * the Xid as "running". See GetNewTransactionId.
401 s->transactionId = GetNewTransactionId(isSubXact);
404 SubTransSetParent(s->transactionId, s->parent->transactionId);
407 * Acquire lock on the transaction XID. (We assume this cannot block.) We
408 * have to ensure that the lock is assigned to the transaction's own
411 currentOwner = CurrentResourceOwner;
414 CurrentResourceOwner = s->curTransactionOwner;
415 XactLockTableInsert(s->transactionId);
419 /* Ensure CurrentResourceOwner is restored on error */
420 CurrentResourceOwner = currentOwner;
424 CurrentResourceOwner = currentOwner;
429 * GetCurrentSubTransactionId
432 GetCurrentSubTransactionId(void)
434 TransactionState s = CurrentTransactionState;
436 return s->subTransactionId;
441 * GetCurrentCommandId
443 * "used" must be TRUE if the caller intends to use the command ID to mark
444 * inserted/updated/deleted tuples. FALSE means the ID is being fetched
445 * for read-only purposes (ie, as a snapshot validity cutoff). See
446 * CommandCounterIncrement() for discussion.
449 GetCurrentCommandId(bool used)
451 /* this is global to a transaction, not subtransaction-local */
453 currentCommandIdUsed = true;
454 return currentCommandId;
458 * GetCurrentTransactionStartTimestamp
461 GetCurrentTransactionStartTimestamp(void)
463 return xactStartTimestamp;
467 * GetCurrentStatementStartTimestamp
470 GetCurrentStatementStartTimestamp(void)
472 return stmtStartTimestamp;
476 * GetCurrentTransactionStopTimestamp
478 * We return current time if the transaction stop time hasn't been set
479 * (which can happen if we decide we don't need to log an XLOG record).
482 GetCurrentTransactionStopTimestamp(void)
484 if (xactStopTimestamp != 0)
485 return xactStopTimestamp;
486 return GetCurrentTimestamp();
490 * SetCurrentStatementStartTimestamp
493 SetCurrentStatementStartTimestamp(void)
495 stmtStartTimestamp = GetCurrentTimestamp();
499 * SetCurrentTransactionStopTimestamp
502 SetCurrentTransactionStopTimestamp(void)
504 xactStopTimestamp = GetCurrentTimestamp();
508 * GetCurrentTransactionNestLevel
510 * Note: this will return zero when not inside any transaction, one when
511 * inside a top-level transaction, etc.
514 GetCurrentTransactionNestLevel(void)
516 TransactionState s = CurrentTransactionState;
518 return s->nestingLevel;
523 * TransactionIdIsCurrentTransactionId
526 TransactionIdIsCurrentTransactionId(TransactionId xid)
531 * We always say that BootstrapTransactionId is "not my transaction ID"
532 * even when it is (ie, during bootstrap). Along with the fact that
533 * transam.c always treats BootstrapTransactionId as already committed,
534 * this causes the tqual.c routines to see all tuples as committed, which
535 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
536 * it never updates or deletes them, so all tuples can be presumed good
539 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
540 * not my transaction ID, so we can just return "false" immediately for
541 * any non-normal XID.
543 if (!TransactionIdIsNormal(xid))
547 * We will return true for the Xid of the current subtransaction, any of
548 * its subcommitted children, any of its parents, or any of their
549 * previously subcommitted children. However, a transaction being aborted
550 * is no longer "current", even though it may still have an entry on the
553 for (s = CurrentTransactionState; s != NULL; s = s->parent)
557 if (s->state == TRANS_ABORT)
559 if (!TransactionIdIsValid(s->transactionId))
560 continue; /* it can't have any child XIDs either */
561 if (TransactionIdEquals(xid, s->transactionId))
563 foreach(cell, s->childXids)
565 if (TransactionIdEquals(xid, lfirst_xid(cell)))
575 * CommandCounterIncrement
578 CommandCounterIncrement(void)
581 * If the current value of the command counter hasn't been "used" to
582 * mark tuples, we need not increment it, since there's no need to
583 * distinguish a read-only command from others. This helps postpone
584 * command counter overflow, and keeps no-op CommandCounterIncrement
587 if (currentCommandIdUsed)
589 currentCommandId += 1;
590 if (currentCommandId == FirstCommandId) /* check for overflow */
592 currentCommandId -= 1;
594 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
595 errmsg("cannot have more than 2^32-1 commands in a transaction")));
597 currentCommandIdUsed = false;
599 /* Propagate new command ID into static snapshots, if set */
600 if (SerializableSnapshot)
601 SerializableSnapshot->curcid = currentCommandId;
603 LatestSnapshot->curcid = currentCommandId;
606 * Make any catalog changes done by the just-completed command
607 * visible in the local syscache. We obviously don't need to do
608 * this after a read-only command. (But see hacks in inval.c
609 * to make real sure we don't think a command that queued inval
610 * messages was read-only.)
612 AtCommit_LocalCache();
616 * Make any other backends' catalog changes visible to me.
618 * XXX this is probably in the wrong place: CommandCounterIncrement
619 * should be purely a local operation, most likely. However fooling
620 * with this will affect asynchronous cross-backend interactions,
621 * which doesn't seem like a wise thing to do in late beta, so save
622 * improving this for another day - tgl 2007-11-30
630 * Interface routine to allow commands to force a synchronous commit of the
631 * current top-level transaction
634 ForceSyncCommit(void)
636 forceSyncCommit = true;
640 /* ----------------------------------------------------------------
641 * StartTransaction stuff
642 * ----------------------------------------------------------------
651 AcceptInvalidationMessages();
660 TransactionState s = CurrentTransactionState;
663 * If this is the first time through, create a private context for
664 * AbortTransaction to work in. By reserving some space now, we can
665 * insulate AbortTransaction from out-of-memory scenarios. Like
666 * ErrorContext, we set it up with slow growth rate and a nonzero minimum
667 * size, so that space will be reserved immediately.
669 if (TransactionAbortContext == NULL)
670 TransactionAbortContext =
671 AllocSetContextCreate(TopMemoryContext,
672 "TransactionAbortContext",
678 * We shouldn't have a transaction context already.
680 Assert(TopTransactionContext == NULL);
683 * Create a toplevel context for the transaction.
685 TopTransactionContext =
686 AllocSetContextCreate(TopMemoryContext,
687 "TopTransactionContext",
688 ALLOCSET_DEFAULT_MINSIZE,
689 ALLOCSET_DEFAULT_INITSIZE,
690 ALLOCSET_DEFAULT_MAXSIZE);
693 * In a top-level transaction, CurTransactionContext is the same as
694 * TopTransactionContext.
696 CurTransactionContext = TopTransactionContext;
697 s->curTransactionContext = CurTransactionContext;
699 /* Make the CurTransactionContext active. */
700 MemoryContextSwitchTo(CurTransactionContext);
704 * AtStart_ResourceOwner
707 AtStart_ResourceOwner(void)
709 TransactionState s = CurrentTransactionState;
712 * We shouldn't have a transaction resource owner already.
714 Assert(TopTransactionResourceOwner == NULL);
717 * Create a toplevel resource owner for the transaction.
719 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
721 TopTransactionResourceOwner = s->curTransactionOwner;
722 CurTransactionResourceOwner = s->curTransactionOwner;
723 CurrentResourceOwner = s->curTransactionOwner;
726 /* ----------------------------------------------------------------
727 * StartSubTransaction stuff
728 * ----------------------------------------------------------------
735 AtSubStart_Memory(void)
737 TransactionState s = CurrentTransactionState;
739 Assert(CurTransactionContext != NULL);
742 * Create a CurTransactionContext, which will be used to hold data that
743 * survives subtransaction commit but disappears on subtransaction abort.
744 * We make it a child of the immediate parent's CurTransactionContext.
746 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
747 "CurTransactionContext",
748 ALLOCSET_DEFAULT_MINSIZE,
749 ALLOCSET_DEFAULT_INITSIZE,
750 ALLOCSET_DEFAULT_MAXSIZE);
751 s->curTransactionContext = CurTransactionContext;
753 /* Make the CurTransactionContext active. */
754 MemoryContextSwitchTo(CurTransactionContext);
758 * AtSubStart_ResourceOwner
761 AtSubStart_ResourceOwner(void)
763 TransactionState s = CurrentTransactionState;
765 Assert(s->parent != NULL);
768 * Create a resource owner for the subtransaction. We make it a child of
769 * the immediate parent's resource owner.
771 s->curTransactionOwner =
772 ResourceOwnerCreate(s->parent->curTransactionOwner,
775 CurTransactionResourceOwner = s->curTransactionOwner;
776 CurrentResourceOwner = s->curTransactionOwner;
779 /* ----------------------------------------------------------------
780 * CommitTransaction stuff
781 * ----------------------------------------------------------------
785 * RecordTransactionCommit
787 * Returns latest XID among xact and its children, or InvalidTransactionId
788 * if the xact has no XID. (We compute that here just because it's easier.)
790 * This is exported only to support an ugly hack in VACUUM FULL.
793 RecordTransactionCommit(void)
795 TransactionId xid = GetTopTransactionIdIfAny();
796 bool markXidCommitted = TransactionIdIsValid(xid);
797 TransactionId latestXid = InvalidTransactionId;
802 TransactionId *children;
804 /* Get data needed for commit record */
805 nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
806 nchildren = xactGetCommittedChildren(&children);
809 * If we haven't been assigned an XID yet, we neither can, nor do we want
810 * to write a COMMIT record.
812 if (!markXidCommitted)
815 * We expect that every smgrscheduleunlink is followed by a catalog
816 * update, and hence XID assignment, so we shouldn't get here with any
817 * pending deletes. Use a real test not just an Assert to check this,
818 * since it's a bit fragile.
821 elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
823 /* Can't have child XIDs either; AssignTransactionId enforces this */
824 Assert(nchildren == 0);
827 * If we didn't create XLOG entries, we're done here; otherwise we
828 * should flush those entries the same as a commit record. (An
829 * example of a possible record that wouldn't cause an XID to be
830 * assigned is a sequence advance record due to nextval() --- we want
831 * to flush that to disk before reporting commit.)
833 if (XactLastRecEnd.xrecoff == 0)
839 * Begin commit critical section and insert the commit XLOG record.
841 XLogRecData rdata[3];
843 xl_xact_commit xlrec;
845 /* Tell bufmgr and smgr to prepare for commit */
849 * Mark ourselves as within our "commit critical section". This
850 * forces any concurrent checkpoint to wait until we've updated
851 * pg_clog. Without this, it is possible for the checkpoint to set
852 * REDO after the XLOG record but fail to flush the pg_clog update to
853 * disk, leading to loss of the transaction commit if the system
854 * crashes a little later.
856 * Note: we could, but don't bother to, set this flag in
857 * RecordTransactionAbort. That's because loss of a transaction abort
858 * is noncritical; the presumption would be that it aborted, anyway.
860 * It's safe to change the inCommit flag of our own backend without
861 * holding the ProcArrayLock, since we're the only one modifying it.
862 * This makes checkpoint's determination of which xacts are inCommit a
863 * bit fuzzy, but it doesn't matter.
865 START_CRIT_SECTION();
866 MyProc->inCommit = true;
868 SetCurrentTransactionStopTimestamp();
869 xlrec.xact_time = xactStopTimestamp;
871 xlrec.nsubxacts = nchildren;
872 rdata[0].data = (char *) (&xlrec);
873 rdata[0].len = MinSizeOfXactCommit;
874 rdata[0].buffer = InvalidBuffer;
875 /* dump rels to delete */
878 rdata[0].next = &(rdata[1]);
879 rdata[1].data = (char *) rels;
880 rdata[1].len = nrels * sizeof(RelFileNode);
881 rdata[1].buffer = InvalidBuffer;
884 /* dump committed child Xids */
887 rdata[lastrdata].next = &(rdata[2]);
888 rdata[2].data = (char *) children;
889 rdata[2].len = nchildren * sizeof(TransactionId);
890 rdata[2].buffer = InvalidBuffer;
893 rdata[lastrdata].next = NULL;
895 (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
899 * Check if we want to commit asynchronously. If the user has set
900 * synchronous_commit = off, and we're not doing cleanup of any non-temp
901 * rels nor committing any command that wanted to force sync commit, then
902 * we can defer flushing XLOG. (We must not allow asynchronous commit if
903 * there are any non-temp tables to be deleted, because we might delete
904 * the files before the COMMIT record is flushed to disk. We do allow
905 * asynchronous commit if all to-be-deleted tables are temporary though,
906 * since they are lost anyway if we crash.)
908 if (XactSyncCommit || forceSyncCommit || haveNonTemp)
911 * Synchronous commit case.
913 * Sleep before flush! So we can flush more than one commit records
914 * per single fsync. (The idea is some other backend may do the
915 * XLogFlush while we're sleeping. This needs work still, because on
916 * most Unixen, the minimum select() delay is 10msec or more, which is
919 * We do not sleep if enableFsync is not turned on, nor if there are
920 * fewer than CommitSiblings other backends with active transactions.
922 if (CommitDelay > 0 && enableFsync &&
923 CountActiveBackends() >= CommitSiblings)
924 pg_usleep(CommitDelay);
926 XLogFlush(XactLastRecEnd);
929 * Now we may update the CLOG, if we wrote a COMMIT record above
931 if (markXidCommitted)
933 TransactionIdCommit(xid);
934 /* to avoid race conditions, the parent must commit first */
935 TransactionIdCommitTree(nchildren, children);
941 * Asynchronous commit case.
943 * Report the latest async commit LSN, so that the WAL writer knows to
946 XLogSetAsyncCommitLSN(XactLastRecEnd);
949 * We must not immediately update the CLOG, since we didn't flush the
950 * XLOG. Instead, we store the LSN up to which the XLOG must be
951 * flushed before the CLOG may be updated.
953 if (markXidCommitted)
955 TransactionIdAsyncCommit(xid, XactLastRecEnd);
956 /* to avoid race conditions, the parent must commit first */
957 TransactionIdAsyncCommitTree(nchildren, children, XactLastRecEnd);
962 * If we entered a commit critical section, leave it now, and let
963 * checkpoints proceed.
965 if (markXidCommitted)
967 MyProc->inCommit = false;
971 /* Compute latestXid while we have the child XIDs handy */
972 latestXid = TransactionIdLatest(xid, nchildren, children);
974 /* Reset XactLastRecEnd until the next transaction writes something */
975 XactLastRecEnd.xrecoff = 0;
978 /* Clean up local data */
989 * AtCommit_LocalCache
992 AtCommit_LocalCache(void)
995 * Make catalog changes visible to me for the next command.
997 CommandEndInvalidationMessages();
1004 AtCommit_Memory(void)
1007 * Now that we're "out" of a transaction, have the system allocate things
1008 * in the top memory context instead of per-transaction contexts.
1010 MemoryContextSwitchTo(TopMemoryContext);
1013 * Release all transaction-local memory.
1015 Assert(TopTransactionContext != NULL);
1016 MemoryContextDelete(TopTransactionContext);
1017 TopTransactionContext = NULL;
1018 CurTransactionContext = NULL;
1019 CurrentTransactionState->curTransactionContext = NULL;
1022 /* ----------------------------------------------------------------
1023 * CommitSubTransaction stuff
1024 * ----------------------------------------------------------------
1028 * AtSubCommit_Memory
1031 AtSubCommit_Memory(void)
1033 TransactionState s = CurrentTransactionState;
1035 Assert(s->parent != NULL);
1037 /* Return to parent transaction level's memory context. */
1038 CurTransactionContext = s->parent->curTransactionContext;
1039 MemoryContextSwitchTo(CurTransactionContext);
1042 * Ordinarily we cannot throw away the child's CurTransactionContext,
1043 * since the data it contains will be needed at upper commit. However, if
1044 * there isn't actually anything in it, we can throw it away. This avoids
1045 * a small memory leak in the common case of "trivial" subxacts.
1047 if (MemoryContextIsEmpty(s->curTransactionContext))
1049 MemoryContextDelete(s->curTransactionContext);
1050 s->curTransactionContext = NULL;
1055 * AtSubCommit_childXids
1057 * Pass my own XID and my child XIDs up to my parent as committed children.
1060 AtSubCommit_childXids(void)
1062 TransactionState s = CurrentTransactionState;
1063 MemoryContext old_cxt;
1065 Assert(s->parent != NULL);
1068 * We keep the child-XID lists in TopTransactionContext; this avoids
1069 * setting up child-transaction contexts for what might be just a few
1070 * bytes of grandchild XIDs.
1072 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
1074 s->parent->childXids = lappend_xid(s->parent->childXids,
1077 if (s->childXids != NIL)
1079 s->parent->childXids = list_concat(s->parent->childXids,
1083 * list_concat doesn't free the list header for the second list; do so
1084 * here to avoid memory leakage (kluge)
1086 pfree(s->childXids);
1090 MemoryContextSwitchTo(old_cxt);
1094 * RecordSubTransactionCommit
1097 RecordSubTransactionCommit(void)
1099 TransactionId xid = GetCurrentTransactionIdIfAny();
1102 * We do not log the subcommit in XLOG; it doesn't matter until the
1103 * top-level transaction commits.
1105 * We must mark the subtransaction subcommitted in the CLOG if it had a
1106 * valid XID assigned. If it did not, nobody else will ever know about
1107 * the existence of this subxact. We don't have to deal with deletions
1108 * scheduled for on-commit here, since they'll be reassigned to our parent
1109 * (who might still abort).
1111 if (TransactionIdIsValid(xid))
1113 /* XXX does this really need to be a critical section? */
1114 START_CRIT_SECTION();
1116 /* Record subtransaction subcommit */
1117 TransactionIdSubCommit(xid);
1123 /* ----------------------------------------------------------------
1124 * AbortTransaction stuff
1125 * ----------------------------------------------------------------
1129 * RecordTransactionAbort
1131 * Returns latest XID among xact and its children, or InvalidTransactionId
1132 * if the xact has no XID. (We compute that here just because it's easier.)
1134 static TransactionId
1135 RecordTransactionAbort(bool isSubXact)
1137 TransactionId xid = GetCurrentTransactionIdIfAny();
1138 TransactionId latestXid;
1142 TransactionId *children;
1143 XLogRecData rdata[3];
1145 xl_xact_abort xlrec;
1148 * If we haven't been assigned an XID, nobody will care whether we aborted
1149 * or not. Hence, we're done in that case. It does not matter if we have
1150 * rels to delete (note that this routine is not responsible for actually
1151 * deleting 'em). We cannot have any child XIDs, either.
1153 if (!TransactionIdIsValid(xid))
1155 /* Reset XactLastRecEnd until the next transaction writes something */
1157 XactLastRecEnd.xrecoff = 0;
1158 return InvalidTransactionId;
1162 * We have a valid XID, so we should write an ABORT record for it.
1164 * We do not flush XLOG to disk here, since the default assumption after a
1165 * crash would be that we aborted, anyway. For the same reason, we don't
1166 * need to worry about interlocking against checkpoint start.
1170 * Check that we haven't aborted halfway through RecordTransactionCommit.
1172 if (TransactionIdDidCommit(xid))
1173 elog(PANIC, "cannot abort transaction %u, it was already committed",
1176 /* Fetch the data we need for the abort record */
1177 nrels = smgrGetPendingDeletes(false, &rels, NULL);
1178 nchildren = xactGetCommittedChildren(&children);
1180 /* XXX do we really need a critical section here? */
1181 START_CRIT_SECTION();
1183 /* Write the ABORT record */
1185 xlrec.xact_time = GetCurrentTimestamp();
1188 SetCurrentTransactionStopTimestamp();
1189 xlrec.xact_time = xactStopTimestamp;
1191 xlrec.nrels = nrels;
1192 xlrec.nsubxacts = nchildren;
1193 rdata[0].data = (char *) (&xlrec);
1194 rdata[0].len = MinSizeOfXactAbort;
1195 rdata[0].buffer = InvalidBuffer;
1196 /* dump rels to delete */
1199 rdata[0].next = &(rdata[1]);
1200 rdata[1].data = (char *) rels;
1201 rdata[1].len = nrels * sizeof(RelFileNode);
1202 rdata[1].buffer = InvalidBuffer;
1205 /* dump committed child Xids */
1208 rdata[lastrdata].next = &(rdata[2]);
1209 rdata[2].data = (char *) children;
1210 rdata[2].len = nchildren * sizeof(TransactionId);
1211 rdata[2].buffer = InvalidBuffer;
1214 rdata[lastrdata].next = NULL;
1216 (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1219 * Mark the transaction aborted in clog. This is not absolutely necessary
1220 * but we may as well do it while we are here; also, in the subxact case
1221 * it is helpful because XactLockTableWait makes use of it to avoid
1222 * waiting for already-aborted subtransactions. It is OK to do it without
1223 * having flushed the ABORT record to disk, because in event of a crash
1224 * we'd be assumed to have aborted anyway.
1226 * The ordering here isn't critical but it seems best to mark the parent
1227 * first. This assures an atomic transition of all the subtransactions to
1228 * aborted state from the point of view of concurrent
1229 * TransactionIdDidAbort calls.
1231 TransactionIdAbort(xid);
1232 TransactionIdAbortTree(nchildren, children);
1236 /* Compute latestXid while we have the child XIDs handy */
1237 latestXid = TransactionIdLatest(xid, nchildren, children);
1240 * If we're aborting a subtransaction, we can immediately remove failed
1241 * XIDs from PGPROC's cache of running child XIDs. We do that here for
1242 * subxacts, because we already have the child XID array at hand. For
1243 * main xacts, the equivalent happens just after this function returns.
1246 XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1248 /* Reset XactLastRecEnd until the next transaction writes something */
1250 XactLastRecEnd.xrecoff = 0;
1252 /* And clean up local data */
1265 AtAbort_Memory(void)
1268 * Switch into TransactionAbortContext, which should have some free space
1269 * even if nothing else does. We'll work in this context until we've
1270 * finished cleaning up.
1272 * It is barely possible to get here when we've not been able to create
1273 * TransactionAbortContext yet; if so use TopMemoryContext.
1275 if (TransactionAbortContext != NULL)
1276 MemoryContextSwitchTo(TransactionAbortContext);
1278 MemoryContextSwitchTo(TopMemoryContext);
1285 AtSubAbort_Memory(void)
1287 Assert(TransactionAbortContext != NULL);
1289 MemoryContextSwitchTo(TransactionAbortContext);
1294 * AtAbort_ResourceOwner
1297 AtAbort_ResourceOwner(void)
1300 * Make sure we have a valid ResourceOwner, if possible (else it will be
1301 * NULL, which is OK)
1303 CurrentResourceOwner = TopTransactionResourceOwner;
1307 * AtSubAbort_ResourceOwner
1310 AtSubAbort_ResourceOwner(void)
1312 TransactionState s = CurrentTransactionState;
1314 /* Make sure we have a valid ResourceOwner */
1315 CurrentResourceOwner = s->curTransactionOwner;
1320 * AtSubAbort_childXids
1323 AtSubAbort_childXids(void)
1325 TransactionState s = CurrentTransactionState;
1328 * We keep the child-XID lists in TopTransactionContext (see
1329 * AtSubCommit_childXids). This means we'd better free the list
1330 * explicitly at abort to avoid leakage.
1332 list_free(s->childXids);
1336 /* ----------------------------------------------------------------
1337 * CleanupTransaction stuff
1338 * ----------------------------------------------------------------
1345 AtCleanup_Memory(void)
1347 Assert(CurrentTransactionState->parent == NULL);
1350 * Now that we're "out" of a transaction, have the system allocate things
1351 * in the top memory context instead of per-transaction contexts.
1353 MemoryContextSwitchTo(TopMemoryContext);
1356 * Clear the special abort context for next time.
1358 if (TransactionAbortContext != NULL)
1359 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1362 * Release all transaction-local memory.
1364 if (TopTransactionContext != NULL)
1365 MemoryContextDelete(TopTransactionContext);
1366 TopTransactionContext = NULL;
1367 CurTransactionContext = NULL;
1368 CurrentTransactionState->curTransactionContext = NULL;
1372 /* ----------------------------------------------------------------
1373 * CleanupSubTransaction stuff
1374 * ----------------------------------------------------------------
1378 * AtSubCleanup_Memory
1381 AtSubCleanup_Memory(void)
1383 TransactionState s = CurrentTransactionState;
1385 Assert(s->parent != NULL);
1387 /* Make sure we're not in an about-to-be-deleted context */
1388 MemoryContextSwitchTo(s->parent->curTransactionContext);
1389 CurTransactionContext = s->parent->curTransactionContext;
1392 * Clear the special abort context for next time.
1394 if (TransactionAbortContext != NULL)
1395 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1398 * Delete the subxact local memory contexts. Its CurTransactionContext can
1399 * go too (note this also kills CurTransactionContexts from any children
1402 if (s->curTransactionContext)
1403 MemoryContextDelete(s->curTransactionContext);
1404 s->curTransactionContext = NULL;
1407 /* ----------------------------------------------------------------
1408 * interface routines
1409 * ----------------------------------------------------------------
1416 StartTransaction(void)
1419 VirtualTransactionId vxid;
1422 * Let's just make sure the state stack is empty
1424 s = &TopTransactionStateData;
1425 CurrentTransactionState = s;
1428 * check the current transaction state
1430 if (s->state != TRANS_DEFAULT)
1431 elog(WARNING, "StartTransaction while in %s state",
1432 TransStateAsString(s->state));
1435 * set the current transaction state information appropriately during
1438 s->state = TRANS_START;
1439 s->transactionId = InvalidTransactionId; /* until assigned */
1442 * Make sure we've freed any old snapshot, and reset xact state variables
1445 XactIsoLevel = DefaultXactIsoLevel;
1446 XactReadOnly = DefaultXactReadOnly;
1447 forceSyncCommit = false;
1450 * reinitialize within-transaction counters
1452 s->subTransactionId = TopSubTransactionId;
1453 currentSubTransactionId = TopSubTransactionId;
1454 currentCommandId = FirstCommandId;
1455 currentCommandIdUsed = false;
1458 * must initialize resource-management stuff first
1461 AtStart_ResourceOwner();
1464 * Assign a new LocalTransactionId, and combine it with the backendId to
1465 * form a virtual transaction id.
1467 vxid.backendId = MyBackendId;
1468 vxid.localTransactionId = GetNextLocalTransactionId();
1471 * Lock the virtual transaction id before we announce it in the proc array
1473 VirtualXactLockTableInsert(vxid);
1476 * Advertise it in the proc array. We assume assignment of
1477 * LocalTransactionID is atomic, and the backendId should be set already.
1479 Assert(MyProc->backendId == vxid.backendId);
1480 MyProc->lxid = vxid.localTransactionId;
1482 PG_TRACE1(transaction__start, vxid.localTransactionId);
1485 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1486 * as the first command's statement_timestamp(), so don't do a fresh
1487 * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1488 * xactStopTimestamp as unset.
1490 xactStartTimestamp = stmtStartTimestamp;
1491 xactStopTimestamp = 0;
1492 pgstat_report_xact_timestamp(xactStartTimestamp);
1495 * initialize current transaction state fields
1497 * note: prevXactReadOnly is not used at the outermost level
1499 s->nestingLevel = 1;
1500 s->gucNestLevel = 1;
1502 GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
1503 /* SecurityDefinerContext should never be set outside a transaction */
1504 Assert(!s->prevSecDefCxt);
1507 * initialize other subsystems for new transaction
1512 AfterTriggerBeginXact();
1515 * done with start processing, set current transaction state to "in
1518 s->state = TRANS_INPROGRESS;
1520 ShowTransactionState("StartTransaction");
1527 * NB: if you change this routine, better look at PrepareTransaction too!
1530 CommitTransaction(void)
1532 TransactionState s = CurrentTransactionState;
1533 TransactionId latestXid;
1535 ShowTransactionState("CommitTransaction");
1538 * check the current transaction state
1540 if (s->state != TRANS_INPROGRESS)
1541 elog(WARNING, "CommitTransaction while in %s state",
1542 TransStateAsString(s->state));
1543 Assert(s->parent == NULL);
1546 * Do pre-commit processing (most of this stuff requires database access,
1547 * and in fact could still cause an error...)
1549 * It is possible for CommitHoldablePortals to invoke functions that queue
1550 * deferred triggers, and it's also possible that triggers create holdable
1551 * cursors. So we have to loop until there's nothing left to do.
1556 * Fire all currently pending deferred triggers.
1558 AfterTriggerFireDeferred();
1561 * Convert any open holdable cursors into static portals. If there
1562 * weren't any, we are done ... otherwise loop back to check if they
1563 * queued deferred triggers. Lather, rinse, repeat.
1565 if (!CommitHoldablePortals())
1569 /* Now we can shut down the deferred-trigger manager */
1570 AfterTriggerEndXact(true);
1572 /* Close any open regular cursors */
1576 * Let ON COMMIT management do its thing (must happen after closing
1577 * cursors, to avoid dangling-reference problems)
1579 PreCommit_on_commit_actions();
1581 /* close large objects before lower-level cleanup */
1582 AtEOXact_LargeObject(true);
1584 /* NOTIFY commit must come before lower-level cleanup */
1588 * Update flat files if we changed pg_database, pg_authid or
1589 * pg_auth_members. This should be the last step before commit.
1591 AtEOXact_UpdateFlatFiles(true);
1593 /* Prevent cancel/die interrupt while cleaning up */
1597 * set the current transaction state information appropriately during
1600 s->state = TRANS_COMMIT;
1603 * Here is where we really truly commit.
1605 latestXid = RecordTransactionCommit();
1607 PG_TRACE1(transaction__commit, MyProc->lxid);
1610 * Let others know about no transaction in progress by me. Note that this
1611 * must be done _before_ releasing locks we hold and _after_
1612 * RecordTransactionCommit.
1614 ProcArrayEndTransaction(MyProc, latestXid);
1617 * This is all post-commit cleanup. Note that if an error is raised here,
1618 * it's too late to abort the transaction. This should be just
1619 * noncritical resource releasing.
1621 * The ordering of operations is not entirely random. The idea is:
1622 * release resources visible to other backends (eg, files, buffer pins);
1623 * then release locks; then release backend-local resources. We want to
1624 * release locks at the point where any backend waiting for us will see
1625 * our transaction as being fully cleaned up.
1627 * Resources that can be associated with individual queries are handled by
1628 * the ResourceOwner mechanism. The other calls here are for backend-wide
1632 CallXactCallbacks(XACT_EVENT_COMMIT);
1634 ResourceOwnerRelease(TopTransactionResourceOwner,
1635 RESOURCE_RELEASE_BEFORE_LOCKS,
1638 /* Check we've released all buffer pins */
1639 AtEOXact_Buffers(true);
1641 /* Clean up the relation cache */
1642 AtEOXact_RelationCache(true);
1645 * Make catalog changes visible to all backends. This has to happen after
1646 * relcache references are dropped (see comments for
1647 * AtEOXact_RelationCache), but before locks are released (if anyone is
1648 * waiting for lock on a relation we've modified, we want them to know
1649 * about the catalog change before they start using the relation).
1651 AtEOXact_Inval(true);
1654 * Likewise, dropping of files deleted during the transaction is best done
1655 * after releasing relcache and buffer pins. (This is not strictly
1656 * necessary during commit, since such pins should have been released
1657 * already, but this ordering is definitely critical during abort.)
1659 smgrDoPendingDeletes(true);
1661 AtEOXact_MultiXact();
1663 ResourceOwnerRelease(TopTransactionResourceOwner,
1664 RESOURCE_RELEASE_LOCKS,
1666 ResourceOwnerRelease(TopTransactionResourceOwner,
1667 RESOURCE_RELEASE_AFTER_LOCKS,
1670 /* Check we've released all catcache entries */
1671 AtEOXact_CatCache(true);
1673 AtEOXact_GUC(true, 1);
1676 AtEOXact_on_commit_actions(true);
1677 AtEOXact_Namespace(true);
1678 /* smgrcommit already done */
1680 AtEOXact_ComboCid();
1681 AtEOXact_HashTables(true);
1682 AtEOXact_PgStat(true);
1683 pgstat_report_xact_timestamp(0);
1685 CurrentResourceOwner = NULL;
1686 ResourceOwnerDelete(TopTransactionResourceOwner);
1687 s->curTransactionOwner = NULL;
1688 CurTransactionResourceOwner = NULL;
1689 TopTransactionResourceOwner = NULL;
1693 s->transactionId = InvalidTransactionId;
1694 s->subTransactionId = InvalidSubTransactionId;
1695 s->nestingLevel = 0;
1696 s->gucNestLevel = 0;
1700 * done with commit processing, set current transaction state back to
1703 s->state = TRANS_DEFAULT;
1705 RESUME_INTERRUPTS();
1710 * PrepareTransaction
1712 * NB: if you change this routine, better look at CommitTransaction too!
1715 PrepareTransaction(void)
1717 TransactionState s = CurrentTransactionState;
1718 TransactionId xid = GetCurrentTransactionId();
1719 GlobalTransaction gxact;
1720 TimestampTz prepared_at;
1722 ShowTransactionState("PrepareTransaction");
1725 * check the current transaction state
1727 if (s->state != TRANS_INPROGRESS)
1728 elog(WARNING, "PrepareTransaction while in %s state",
1729 TransStateAsString(s->state));
1730 Assert(s->parent == NULL);
1733 * Do pre-commit processing (most of this stuff requires database access,
1734 * and in fact could still cause an error...)
1736 * It is possible for PrepareHoldablePortals to invoke functions that
1737 * queue deferred triggers, and it's also possible that triggers create
1738 * holdable cursors. So we have to loop until there's nothing left to do.
1743 * Fire all currently pending deferred triggers.
1745 AfterTriggerFireDeferred();
1748 * Convert any open holdable cursors into static portals. If there
1749 * weren't any, we are done ... otherwise loop back to check if they
1750 * queued deferred triggers. Lather, rinse, repeat.
1752 if (!PrepareHoldablePortals())
1756 /* Now we can shut down the deferred-trigger manager */
1757 AfterTriggerEndXact(true);
1759 /* Close any open regular cursors */
1763 * Let ON COMMIT management do its thing (must happen after closing
1764 * cursors, to avoid dangling-reference problems)
1766 PreCommit_on_commit_actions();
1768 /* close large objects before lower-level cleanup */
1769 AtEOXact_LargeObject(true);
1771 /* NOTIFY and flatfiles will be handled below */
1773 /* Prevent cancel/die interrupt while cleaning up */
1777 * set the current transaction state information appropriately during
1778 * prepare processing
1780 s->state = TRANS_PREPARE;
1782 prepared_at = GetCurrentTimestamp();
1784 /* Tell bufmgr and smgr to prepare for commit */
1788 * Reserve the GID for this transaction. This could fail if the requested
1789 * GID is invalid or already in use.
1791 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1792 GetUserId(), MyDatabaseId);
1796 * Collect data for the 2PC state file. Note that in general, no actual
1797 * state change should happen in the called modules during this step,
1798 * since it's still possible to fail before commit, and in that case we
1799 * want transaction abort to be able to clean up. (In particular, the
1800 * AtPrepare routines may error out if they find cases they cannot
1801 * handle.) State cleanup should happen in the PostPrepare routines
1802 * below. However, some modules can go ahead and clear state here because
1803 * they wouldn't do anything with it during abort anyway.
1805 * Note: because the 2PC state file records will be replayed in the same
1806 * order they are made, the order of these calls has to match the order in
1807 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1808 * PREPARED; in particular, pay attention to whether things should happen
1809 * before or after releasing the transaction's locks.
1811 StartPrepare(gxact);
1814 AtPrepare_UpdateFlatFiles();
1820 * Here is where we really truly prepare.
1822 * We have to record transaction prepares even if we didn't make any
1823 * updates, because the transaction manager might get confused if we lose
1824 * a global transaction.
1829 * Now we clean up backend-internal state and release internal resources.
1832 /* Reset XactLastRecEnd until the next transaction writes something */
1833 XactLastRecEnd.xrecoff = 0;
1836 * Let others know about no transaction in progress by me. This has to be
1837 * done *after* the prepared transaction has been marked valid, else
1838 * someone may think it is unlocked and recyclable.
1840 ProcArrayClearTransaction(MyProc);
1843 * This is all post-transaction cleanup. Note that if an error is raised
1844 * here, it's too late to abort the transaction. This should be just
1845 * noncritical resource releasing. See notes in CommitTransaction.
1848 CallXactCallbacks(XACT_EVENT_PREPARE);
1850 ResourceOwnerRelease(TopTransactionResourceOwner,
1851 RESOURCE_RELEASE_BEFORE_LOCKS,
1854 /* Check we've released all buffer pins */
1855 AtEOXact_Buffers(true);
1857 /* Clean up the relation cache */
1858 AtEOXact_RelationCache(true);
1860 /* notify and flatfiles don't need a postprepare call */
1862 PostPrepare_PgStat();
1864 PostPrepare_Inval();
1868 AtEOXact_MultiXact();
1870 PostPrepare_Locks(xid);
1872 ResourceOwnerRelease(TopTransactionResourceOwner,
1873 RESOURCE_RELEASE_LOCKS,
1875 ResourceOwnerRelease(TopTransactionResourceOwner,
1876 RESOURCE_RELEASE_AFTER_LOCKS,
1879 /* Check we've released all catcache entries */
1880 AtEOXact_CatCache(true);
1882 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1883 AtEOXact_GUC(true, 1);
1886 AtEOXact_on_commit_actions(true);
1887 AtEOXact_Namespace(true);
1888 /* smgrcommit already done */
1890 AtEOXact_ComboCid();
1891 AtEOXact_HashTables(true);
1892 /* don't call AtEOXact_PgStat here */
1894 CurrentResourceOwner = NULL;
1895 ResourceOwnerDelete(TopTransactionResourceOwner);
1896 s->curTransactionOwner = NULL;
1897 CurTransactionResourceOwner = NULL;
1898 TopTransactionResourceOwner = NULL;
1902 s->transactionId = InvalidTransactionId;
1903 s->subTransactionId = InvalidSubTransactionId;
1904 s->nestingLevel = 0;
1905 s->gucNestLevel = 0;
1909 * done with 1st phase commit processing, set current transaction state
1912 s->state = TRANS_DEFAULT;
1914 RESUME_INTERRUPTS();
1922 AbortTransaction(void)
1924 TransactionState s = CurrentTransactionState;
1925 TransactionId latestXid;
1927 /* Prevent cancel/die interrupt while cleaning up */
1930 /* Make sure we have a valid memory context and resource owner */
1932 AtAbort_ResourceOwner();
1935 * Release any LW locks we might be holding as quickly as possible.
1936 * (Regular locks, however, must be held till we finish aborting.)
1937 * Releasing LW locks is critical since we might try to grab them again
1938 * while cleaning up!
1942 /* Clean up buffer I/O and buffer context locks, too */
1947 * Also clean up any open wait for lock, since the lock manager will choke
1948 * if we try to wait for another lock before doing this.
1953 * check the current transaction state
1955 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1956 elog(WARNING, "AbortTransaction while in %s state",
1957 TransStateAsString(s->state));
1958 Assert(s->parent == NULL);
1961 * set the current transaction state information appropriately during the
1964 s->state = TRANS_ABORT;
1967 * Reset user ID which might have been changed transiently. We need this
1968 * to clean up in case control escaped out of a SECURITY DEFINER function
1969 * or other local change of CurrentUserId; therefore, the prior value
1970 * of SecurityDefinerContext also needs to be restored.
1972 * (Note: it is not necessary to restore session authorization or role
1973 * settings here because those can only be changed via GUC, and GUC will
1974 * take care of rolling them back if need be.)
1976 SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
1979 * do abort processing
1981 AfterTriggerEndXact(false);
1983 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1985 AtEOXact_UpdateFlatFiles(false);
1988 * Advertise the fact that we aborted in pg_clog (assuming that we got as
1989 * far as assigning an XID to advertise).
1991 latestXid = RecordTransactionAbort(false);
1993 PG_TRACE1(transaction__abort, MyProc->lxid);
1996 * Let others know about no transaction in progress by me. Note that this
1997 * must be done _before_ releasing locks we hold and _after_
1998 * RecordTransactionAbort.
2000 ProcArrayEndTransaction(MyProc, latestXid);
2003 * Post-abort cleanup. See notes in CommitTransaction() concerning
2007 CallXactCallbacks(XACT_EVENT_ABORT);
2009 ResourceOwnerRelease(TopTransactionResourceOwner,
2010 RESOURCE_RELEASE_BEFORE_LOCKS,
2012 AtEOXact_Buffers(false);
2013 AtEOXact_RelationCache(false);
2014 AtEOXact_Inval(false);
2015 smgrDoPendingDeletes(false);
2016 AtEOXact_MultiXact();
2017 ResourceOwnerRelease(TopTransactionResourceOwner,
2018 RESOURCE_RELEASE_LOCKS,
2020 ResourceOwnerRelease(TopTransactionResourceOwner,
2021 RESOURCE_RELEASE_AFTER_LOCKS,
2023 AtEOXact_CatCache(false);
2025 AtEOXact_GUC(false, 1);
2026 AtEOXact_SPI(false);
2028 AtEOXact_on_commit_actions(false);
2029 AtEOXact_Namespace(false);
2032 AtEOXact_ComboCid();
2033 AtEOXact_HashTables(false);
2034 AtEOXact_PgStat(false);
2035 pgstat_report_xact_timestamp(0);
2038 * State remains TRANS_ABORT until CleanupTransaction().
2040 RESUME_INTERRUPTS();
2044 * CleanupTransaction
2047 CleanupTransaction(void)
2049 TransactionState s = CurrentTransactionState;
2052 * State should still be TRANS_ABORT from AbortTransaction().
2054 if (s->state != TRANS_ABORT)
2055 elog(FATAL, "CleanupTransaction: unexpected state %s",
2056 TransStateAsString(s->state));
2059 * do abort cleanup processing
2061 AtCleanup_Portals(); /* now safe to release portal memory */
2063 CurrentResourceOwner = NULL; /* and resource owner */
2064 if (TopTransactionResourceOwner)
2065 ResourceOwnerDelete(TopTransactionResourceOwner);
2066 s->curTransactionOwner = NULL;
2067 CurTransactionResourceOwner = NULL;
2068 TopTransactionResourceOwner = NULL;
2070 AtCleanup_Memory(); /* and transaction memory */
2072 s->transactionId = InvalidTransactionId;
2073 s->subTransactionId = InvalidSubTransactionId;
2074 s->nestingLevel = 0;
2075 s->gucNestLevel = 0;
2079 * done with abort processing, set current transaction state back to
2082 s->state = TRANS_DEFAULT;
2086 * StartTransactionCommand
2089 StartTransactionCommand(void)
2091 TransactionState s = CurrentTransactionState;
2093 switch (s->blockState)
2096 * if we aren't in a transaction block, we just do our usual start
2099 case TBLOCK_DEFAULT:
2101 s->blockState = TBLOCK_STARTED;
2105 * We are somewhere in a transaction block or subtransaction and
2106 * about to start a new command. For now we do nothing, but
2107 * someday we may do command-local resource initialization. (Note
2108 * that any needed CommandCounterIncrement was done by the
2109 * previous CommitTransactionCommand.)
2111 case TBLOCK_INPROGRESS:
2112 case TBLOCK_SUBINPROGRESS:
2116 * Here we are in a failed transaction block (one of the commands
2117 * caused an abort) so we do nothing but remain in the abort
2118 * state. Eventually we will get a ROLLBACK command which will
2119 * get us out of this state. (It is up to other code to ensure
2120 * that no commands other than ROLLBACK will be processed in these
2124 case TBLOCK_SUBABORT:
2127 /* These cases are invalid. */
2128 case TBLOCK_STARTED:
2130 case TBLOCK_SUBBEGIN:
2133 case TBLOCK_ABORT_END:
2134 case TBLOCK_SUBABORT_END:
2135 case TBLOCK_ABORT_PENDING:
2136 case TBLOCK_SUBABORT_PENDING:
2137 case TBLOCK_SUBRESTART:
2138 case TBLOCK_SUBABORT_RESTART:
2139 case TBLOCK_PREPARE:
2140 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2141 BlockStateAsString(s->blockState));
2146 * We must switch to CurTransactionContext before returning. This is
2147 * already done if we called StartTransaction, otherwise not.
2149 Assert(CurTransactionContext != NULL);
2150 MemoryContextSwitchTo(CurTransactionContext);
2154 * CommitTransactionCommand
2157 CommitTransactionCommand(void)
2159 TransactionState s = CurrentTransactionState;
2161 switch (s->blockState)
2164 * This shouldn't happen, because it means the previous
2165 * StartTransactionCommand didn't set the STARTED state
2168 case TBLOCK_DEFAULT:
2169 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2170 BlockStateAsString(s->blockState));
2174 * If we aren't in a transaction block, just do our usual
2175 * transaction commit, and return to the idle state.
2177 case TBLOCK_STARTED:
2178 CommitTransaction();
2179 s->blockState = TBLOCK_DEFAULT;
2183 * We are completing a "BEGIN TRANSACTION" command, so we change
2184 * to the "transaction block in progress" state and return. (We
2185 * assume the BEGIN did nothing to the database, so we need no
2186 * CommandCounterIncrement.)
2189 s->blockState = TBLOCK_INPROGRESS;
2193 * This is the case when we have finished executing a command
2194 * someplace within a transaction block. We increment the command
2195 * counter and return.
2197 case TBLOCK_INPROGRESS:
2198 case TBLOCK_SUBINPROGRESS:
2199 CommandCounterIncrement();
2203 * We are completing a "COMMIT" command. Do it and return to the
2207 CommitTransaction();
2208 s->blockState = TBLOCK_DEFAULT;
2212 * Here we are in the middle of a transaction block but one of the
2213 * commands caused an abort so we do nothing but remain in the
2214 * abort state. Eventually we will get a ROLLBACK comand.
2217 case TBLOCK_SUBABORT:
2221 * Here we were in an aborted transaction block and we just got
2222 * the ROLLBACK command from the user, so clean up the
2223 * already-aborted transaction and return to the idle state.
2225 case TBLOCK_ABORT_END:
2226 CleanupTransaction();
2227 s->blockState = TBLOCK_DEFAULT;
2231 * Here we were in a perfectly good transaction block but the user
2232 * told us to ROLLBACK anyway. We have to abort the transaction
2233 * and then clean up.
2235 case TBLOCK_ABORT_PENDING:
2237 CleanupTransaction();
2238 s->blockState = TBLOCK_DEFAULT;
2242 * We are completing a "PREPARE TRANSACTION" command. Do it and
2243 * return to the idle state.
2245 case TBLOCK_PREPARE:
2246 PrepareTransaction();
2247 s->blockState = TBLOCK_DEFAULT;
2251 * We were just issued a SAVEPOINT inside a transaction block.
2252 * Start a subtransaction. (DefineSavepoint already did
2253 * PushTransaction, so as to have someplace to put the SUBBEGIN
2256 case TBLOCK_SUBBEGIN:
2257 StartSubTransaction();
2258 s->blockState = TBLOCK_SUBINPROGRESS;
2262 * We were issued a COMMIT or RELEASE command, so we end the
2263 * current subtransaction and return to the parent transaction.
2264 * The parent might be ended too, so repeat till we are all the
2265 * way out or find an INPROGRESS transaction.
2270 CommitSubTransaction();
2271 s = CurrentTransactionState; /* changed by pop */
2272 } while (s->blockState == TBLOCK_SUBEND);
2273 /* If we had a COMMIT command, finish off the main xact too */
2274 if (s->blockState == TBLOCK_END)
2276 Assert(s->parent == NULL);
2277 CommitTransaction();
2278 s->blockState = TBLOCK_DEFAULT;
2280 else if (s->blockState == TBLOCK_PREPARE)
2282 Assert(s->parent == NULL);
2283 PrepareTransaction();
2284 s->blockState = TBLOCK_DEFAULT;
2288 Assert(s->blockState == TBLOCK_INPROGRESS ||
2289 s->blockState == TBLOCK_SUBINPROGRESS);
2294 * The current already-failed subtransaction is ending due to a
2295 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2296 * examine the parent (which could be in any of several states).
2298 case TBLOCK_SUBABORT_END:
2299 CleanupSubTransaction();
2300 CommitTransactionCommand();
2304 * As above, but it's not dead yet, so abort first.
2306 case TBLOCK_SUBABORT_PENDING:
2307 AbortSubTransaction();
2308 CleanupSubTransaction();
2309 CommitTransactionCommand();
2313 * The current subtransaction is the target of a ROLLBACK TO
2314 * command. Abort and pop it, then start a new subtransaction
2315 * with the same name.
2317 case TBLOCK_SUBRESTART:
2322 /* save name and keep Cleanup from freeing it */
2325 savepointLevel = s->savepointLevel;
2327 AbortSubTransaction();
2328 CleanupSubTransaction();
2330 DefineSavepoint(NULL);
2331 s = CurrentTransactionState; /* changed by push */
2333 s->savepointLevel = savepointLevel;
2335 /* This is the same as TBLOCK_SUBBEGIN case */
2336 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2337 StartSubTransaction();
2338 s->blockState = TBLOCK_SUBINPROGRESS;
2343 * Same as above, but the subtransaction had already failed, so we
2344 * don't need AbortSubTransaction.
2346 case TBLOCK_SUBABORT_RESTART:
2351 /* save name and keep Cleanup from freeing it */
2354 savepointLevel = s->savepointLevel;
2356 CleanupSubTransaction();
2358 DefineSavepoint(NULL);
2359 s = CurrentTransactionState; /* changed by push */
2361 s->savepointLevel = savepointLevel;
2363 /* This is the same as TBLOCK_SUBBEGIN case */
2364 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2365 StartSubTransaction();
2366 s->blockState = TBLOCK_SUBINPROGRESS;
2373 * AbortCurrentTransaction
2376 AbortCurrentTransaction(void)
2378 TransactionState s = CurrentTransactionState;
2380 switch (s->blockState)
2382 case TBLOCK_DEFAULT:
2383 if (s->state == TRANS_DEFAULT)
2385 /* we are idle, so nothing to do */
2390 * We can get here after an error during transaction start
2391 * (state will be TRANS_START). Need to clean up the
2392 * incompletely started transaction. First, adjust the
2393 * low-level state to suppress warning message from
2396 if (s->state == TRANS_START)
2397 s->state = TRANS_INPROGRESS;
2399 CleanupTransaction();
2404 * if we aren't in a transaction block, we just do the basic abort
2405 * & cleanup transaction.
2407 case TBLOCK_STARTED:
2409 CleanupTransaction();
2410 s->blockState = TBLOCK_DEFAULT;
2414 * If we are in TBLOCK_BEGIN it means something screwed up right
2415 * after reading "BEGIN TRANSACTION". We assume that the user
2416 * will interpret the error as meaning the BEGIN failed to get him
2417 * into a transaction block, so we should abort and return to idle
2422 CleanupTransaction();
2423 s->blockState = TBLOCK_DEFAULT;
2427 * We are somewhere in a transaction block and we've gotten a
2428 * failure, so we abort the transaction and set up the persistent
2429 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2431 case TBLOCK_INPROGRESS:
2433 s->blockState = TBLOCK_ABORT;
2434 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2438 * Here, we failed while trying to COMMIT. Clean up the
2439 * transaction and return to idle state (we do not want to stay in
2444 CleanupTransaction();
2445 s->blockState = TBLOCK_DEFAULT;
2449 * Here, we are already in an aborted transaction state and are
2450 * waiting for a ROLLBACK, but for some reason we failed again! So
2451 * we just remain in the abort state.
2454 case TBLOCK_SUBABORT:
2458 * We are in a failed transaction and we got the ROLLBACK command.
2459 * We have already aborted, we just need to cleanup and go to idle
2462 case TBLOCK_ABORT_END:
2463 CleanupTransaction();
2464 s->blockState = TBLOCK_DEFAULT;
2468 * We are in a live transaction and we got a ROLLBACK command.
2469 * Abort, cleanup, go to idle state.
2471 case TBLOCK_ABORT_PENDING:
2473 CleanupTransaction();
2474 s->blockState = TBLOCK_DEFAULT;
2478 * Here, we failed while trying to PREPARE. Clean up the
2479 * transaction and return to idle state (we do not want to stay in
2482 case TBLOCK_PREPARE:
2484 CleanupTransaction();
2485 s->blockState = TBLOCK_DEFAULT;
2489 * We got an error inside a subtransaction. Abort just the
2490 * subtransaction, and go to the persistent SUBABORT state until
2493 case TBLOCK_SUBINPROGRESS:
2494 AbortSubTransaction();
2495 s->blockState = TBLOCK_SUBABORT;
2499 * If we failed while trying to create a subtransaction, clean up
2500 * the broken subtransaction and abort the parent. The same
2501 * applies if we get a failure while ending a subtransaction.
2503 case TBLOCK_SUBBEGIN:
2505 case TBLOCK_SUBABORT_PENDING:
2506 case TBLOCK_SUBRESTART:
2507 AbortSubTransaction();
2508 CleanupSubTransaction();
2509 AbortCurrentTransaction();
2513 * Same as above, except the Abort() was already done.
2515 case TBLOCK_SUBABORT_END:
2516 case TBLOCK_SUBABORT_RESTART:
2517 CleanupSubTransaction();
2518 AbortCurrentTransaction();
2524 * PreventTransactionChain
2526 * This routine is to be called by statements that must not run inside
2527 * a transaction block, typically because they have non-rollback-able
2528 * side effects or do internal commits.
2530 * If we have already started a transaction block, issue an error; also issue
2531 * an error if we appear to be running inside a user-defined function (which
2532 * could issue more commands and possibly cause a failure after the statement
2533 * completes). Subtransactions are verboten too.
2535 * isTopLevel: passed down from ProcessUtility to determine whether we are
2536 * inside a function or multi-query querystring. (We will always fail if
2537 * this is false, but it's convenient to centralize the check here instead of
2538 * making callers do it.)
2539 * stmtType: statement type name, for error messages.
2542 PreventTransactionChain(bool isTopLevel, const char *stmtType)
2545 * xact block already started?
2547 if (IsTransactionBlock())
2549 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2550 /* translator: %s represents an SQL statement name */
2551 errmsg("%s cannot run inside a transaction block",
2557 if (IsSubTransaction())
2559 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2560 /* translator: %s represents an SQL statement name */
2561 errmsg("%s cannot run inside a subtransaction",
2565 * inside a function call?
2569 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2570 /* translator: %s represents an SQL statement name */
2571 errmsg("%s cannot be executed from a function or multi-command string",
2574 /* If we got past IsTransactionBlock test, should be in default state */
2575 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2576 CurrentTransactionState->blockState != TBLOCK_STARTED)
2577 elog(FATAL, "cannot prevent transaction chain");
2582 * RequireTransactionChain
2584 * This routine is to be called by statements that must run inside
2585 * a transaction block, because they have no effects that persist past
2586 * transaction end (and so calling them outside a transaction block
2587 * is presumably an error). DECLARE CURSOR is an example.
2589 * If we appear to be running inside a user-defined function, we do not
2590 * issue an error, since the function could issue more commands that make
2591 * use of the current statement's results. Likewise subtransactions.
2592 * Thus this is an inverse for PreventTransactionChain.
2594 * isTopLevel: passed down from ProcessUtility to determine whether we are
2595 * inside a function.
2596 * stmtType: statement type name, for error messages.
2599 RequireTransactionChain(bool isTopLevel, const char *stmtType)
2602 * xact block already started?
2604 if (IsTransactionBlock())
2610 if (IsSubTransaction())
2614 * inside a function call?
2620 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2621 /* translator: %s represents an SQL statement name */
2622 errmsg("%s can only be used in transaction blocks",
2627 * IsInTransactionChain
2629 * This routine is for statements that need to behave differently inside
2630 * a transaction block than when running as single commands. ANALYZE is
2631 * currently the only example.
2633 * isTopLevel: passed down from ProcessUtility to determine whether we are
2634 * inside a function.
2637 IsInTransactionChain(bool isTopLevel)
2640 * Return true on same conditions that would make PreventTransactionChain
2643 if (IsTransactionBlock())
2646 if (IsSubTransaction())
2652 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2653 CurrentTransactionState->blockState != TBLOCK_STARTED)
2661 * Register or deregister callback functions for start- and end-of-xact
2664 * These functions are intended for use by dynamically loaded modules.
2665 * For built-in modules we generally just hardwire the appropriate calls
2666 * (mainly because it's easier to control the order that way, where needed).
2668 * At transaction end, the callback occurs post-commit or post-abort, so the
2669 * callback functions can only do noncritical cleanup.
2672 RegisterXactCallback(XactCallback callback, void *arg)
2674 XactCallbackItem *item;
2676 item = (XactCallbackItem *)
2677 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2678 item->callback = callback;
2680 item->next = Xact_callbacks;
2681 Xact_callbacks = item;
2685 UnregisterXactCallback(XactCallback callback, void *arg)
2687 XactCallbackItem *item;
2688 XactCallbackItem *prev;
2691 for (item = Xact_callbacks; item; prev = item, item = item->next)
2693 if (item->callback == callback && item->arg == arg)
2696 prev->next = item->next;
2698 Xact_callbacks = item->next;
2706 CallXactCallbacks(XactEvent event)
2708 XactCallbackItem *item;
2710 for (item = Xact_callbacks; item; item = item->next)
2711 (*item->callback) (event, item->arg);
2716 * Register or deregister callback functions for start- and end-of-subxact
2719 * Pretty much same as above, but for subtransaction events.
2721 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2722 * so the callback functions can only do noncritical cleanup. At
2723 * subtransaction start, the callback is called when the subtransaction has
2724 * finished initializing.
2727 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2729 SubXactCallbackItem *item;
2731 item = (SubXactCallbackItem *)
2732 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2733 item->callback = callback;
2735 item->next = SubXact_callbacks;
2736 SubXact_callbacks = item;
2740 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2742 SubXactCallbackItem *item;
2743 SubXactCallbackItem *prev;
2746 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2748 if (item->callback == callback && item->arg == arg)
2751 prev->next = item->next;
2753 SubXact_callbacks = item->next;
2761 CallSubXactCallbacks(SubXactEvent event,
2762 SubTransactionId mySubid,
2763 SubTransactionId parentSubid)
2765 SubXactCallbackItem *item;
2767 for (item = SubXact_callbacks; item; item = item->next)
2768 (*item->callback) (event, mySubid, parentSubid, item->arg);
2772 /* ----------------------------------------------------------------
2773 * transaction block support
2774 * ----------------------------------------------------------------
2778 * BeginTransactionBlock
2779 * This executes a BEGIN command.
2782 BeginTransactionBlock(void)
2784 TransactionState s = CurrentTransactionState;
2786 switch (s->blockState)
2789 * We are not inside a transaction block, so allow one to begin.
2791 case TBLOCK_STARTED:
2792 s->blockState = TBLOCK_BEGIN;
2796 * Already a transaction block in progress.
2798 case TBLOCK_INPROGRESS:
2799 case TBLOCK_SUBINPROGRESS:
2801 case TBLOCK_SUBABORT:
2803 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2804 errmsg("there is already a transaction in progress")));
2807 /* These cases are invalid. */
2808 case TBLOCK_DEFAULT:
2810 case TBLOCK_SUBBEGIN:
2813 case TBLOCK_ABORT_END:
2814 case TBLOCK_SUBABORT_END:
2815 case TBLOCK_ABORT_PENDING:
2816 case TBLOCK_SUBABORT_PENDING:
2817 case TBLOCK_SUBRESTART:
2818 case TBLOCK_SUBABORT_RESTART:
2819 case TBLOCK_PREPARE:
2820 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2821 BlockStateAsString(s->blockState));
2827 * PrepareTransactionBlock
2828 * This executes a PREPARE command.
2830 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2831 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2833 * Note that we don't actually do anything here except change blockState.
2834 * The real work will be done in the upcoming PrepareTransaction().
2835 * We do it this way because it's not convenient to change memory context,
2836 * resource owner, etc while executing inside a Portal.
2839 PrepareTransactionBlock(char *gid)
2844 /* Set up to commit the current transaction */
2845 result = EndTransactionBlock();
2847 /* If successful, change outer tblock state to PREPARE */
2850 s = CurrentTransactionState;
2852 while (s->parent != NULL)
2855 if (s->blockState == TBLOCK_END)
2857 /* Save GID where PrepareTransaction can find it again */
2858 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2860 s->blockState = TBLOCK_PREPARE;
2865 * ignore case where we are not in a transaction;
2866 * EndTransactionBlock already issued a warning.
2868 Assert(s->blockState == TBLOCK_STARTED);
2869 /* Don't send back a PREPARE result tag... */
2878 * EndTransactionBlock
2879 * This executes a COMMIT command.
2881 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2882 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2884 * Note that we don't actually do anything here except change blockState.
2885 * The real work will be done in the upcoming CommitTransactionCommand().
2886 * We do it this way because it's not convenient to change memory context,
2887 * resource owner, etc while executing inside a Portal.
2890 EndTransactionBlock(void)
2892 TransactionState s = CurrentTransactionState;
2893 bool result = false;
2895 switch (s->blockState)
2898 * We are in a transaction block, so tell CommitTransactionCommand
2901 case TBLOCK_INPROGRESS:
2902 s->blockState = TBLOCK_END;
2907 * We are in a failed transaction block. Tell
2908 * CommitTransactionCommand it's time to exit the block.
2911 s->blockState = TBLOCK_ABORT_END;
2915 * We are in a live subtransaction block. Set up to subcommit all
2916 * open subtransactions and then commit the main transaction.
2918 case TBLOCK_SUBINPROGRESS:
2919 while (s->parent != NULL)
2921 if (s->blockState == TBLOCK_SUBINPROGRESS)
2922 s->blockState = TBLOCK_SUBEND;
2924 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2925 BlockStateAsString(s->blockState));
2928 if (s->blockState == TBLOCK_INPROGRESS)
2929 s->blockState = TBLOCK_END;
2931 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2932 BlockStateAsString(s->blockState));
2937 * Here we are inside an aborted subtransaction. Treat the COMMIT
2938 * as ROLLBACK: set up to abort everything and exit the main
2941 case TBLOCK_SUBABORT:
2942 while (s->parent != NULL)
2944 if (s->blockState == TBLOCK_SUBINPROGRESS)
2945 s->blockState = TBLOCK_SUBABORT_PENDING;
2946 else if (s->blockState == TBLOCK_SUBABORT)
2947 s->blockState = TBLOCK_SUBABORT_END;
2949 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2950 BlockStateAsString(s->blockState));
2953 if (s->blockState == TBLOCK_INPROGRESS)
2954 s->blockState = TBLOCK_ABORT_PENDING;
2955 else if (s->blockState == TBLOCK_ABORT)
2956 s->blockState = TBLOCK_ABORT_END;
2958 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2959 BlockStateAsString(s->blockState));
2963 * The user issued COMMIT when not inside a transaction. Issue a
2964 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
2965 * CommitTransactionCommand() will then close the transaction and
2966 * put us back into the default state.
2968 case TBLOCK_STARTED:
2970 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2971 errmsg("there is no transaction in progress")));
2975 /* These cases are invalid. */
2976 case TBLOCK_DEFAULT:
2978 case TBLOCK_SUBBEGIN:
2981 case TBLOCK_ABORT_END:
2982 case TBLOCK_SUBABORT_END:
2983 case TBLOCK_ABORT_PENDING:
2984 case TBLOCK_SUBABORT_PENDING:
2985 case TBLOCK_SUBRESTART:
2986 case TBLOCK_SUBABORT_RESTART:
2987 case TBLOCK_PREPARE:
2988 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2989 BlockStateAsString(s->blockState));
2997 * UserAbortTransactionBlock
2998 * This executes a ROLLBACK command.
3000 * As above, we don't actually do anything here except change blockState.
3003 UserAbortTransactionBlock(void)
3005 TransactionState s = CurrentTransactionState;
3007 switch (s->blockState)
3010 * We are inside a transaction block and we got a ROLLBACK command
3011 * from the user, so tell CommitTransactionCommand to abort and
3012 * exit the transaction block.
3014 case TBLOCK_INPROGRESS:
3015 s->blockState = TBLOCK_ABORT_PENDING;
3019 * We are inside a failed transaction block and we got a ROLLBACK
3020 * command from the user. Abort processing is already done, so
3021 * CommitTransactionCommand just has to cleanup and go back to
3025 s->blockState = TBLOCK_ABORT_END;
3029 * We are inside a subtransaction. Mark everything up to top
3030 * level as exitable.
3032 case TBLOCK_SUBINPROGRESS:
3033 case TBLOCK_SUBABORT:
3034 while (s->parent != NULL)
3036 if (s->blockState == TBLOCK_SUBINPROGRESS)
3037 s->blockState = TBLOCK_SUBABORT_PENDING;
3038 else if (s->blockState == TBLOCK_SUBABORT)
3039 s->blockState = TBLOCK_SUBABORT_END;
3041 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3042 BlockStateAsString(s->blockState));
3045 if (s->blockState == TBLOCK_INPROGRESS)
3046 s->blockState = TBLOCK_ABORT_PENDING;
3047 else if (s->blockState == TBLOCK_ABORT)
3048 s->blockState = TBLOCK_ABORT_END;
3050 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3051 BlockStateAsString(s->blockState));
3055 * The user issued ABORT when not inside a transaction. Issue a
3056 * WARNING and go to abort state. The upcoming call to
3057 * CommitTransactionCommand() will then put us back into the
3060 case TBLOCK_STARTED:
3062 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3063 errmsg("there is no transaction in progress")));
3064 s->blockState = TBLOCK_ABORT_PENDING;
3067 /* These cases are invalid. */
3068 case TBLOCK_DEFAULT:
3070 case TBLOCK_SUBBEGIN:
3073 case TBLOCK_ABORT_END:
3074 case TBLOCK_SUBABORT_END:
3075 case TBLOCK_ABORT_PENDING:
3076 case TBLOCK_SUBABORT_PENDING:
3077 case TBLOCK_SUBRESTART:
3078 case TBLOCK_SUBABORT_RESTART:
3079 case TBLOCK_PREPARE:
3080 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3081 BlockStateAsString(s->blockState));
3088 * This executes a SAVEPOINT command.
3091 DefineSavepoint(char *name)
3093 TransactionState s = CurrentTransactionState;
3095 switch (s->blockState)
3097 case TBLOCK_INPROGRESS:
3098 case TBLOCK_SUBINPROGRESS:
3099 /* Normal subtransaction start */
3101 s = CurrentTransactionState; /* changed by push */
3104 * Savepoint names, like the TransactionState block itself, live
3105 * in TopTransactionContext.
3108 s->name = MemoryContextStrdup(TopTransactionContext, name);
3111 /* These cases are invalid. */
3112 case TBLOCK_DEFAULT:
3113 case TBLOCK_STARTED:
3115 case TBLOCK_SUBBEGIN:
3119 case TBLOCK_SUBABORT:
3120 case TBLOCK_ABORT_END:
3121 case TBLOCK_SUBABORT_END:
3122 case TBLOCK_ABORT_PENDING:
3123 case TBLOCK_SUBABORT_PENDING:
3124 case TBLOCK_SUBRESTART:
3125 case TBLOCK_SUBABORT_RESTART:
3126 case TBLOCK_PREPARE:
3127 elog(FATAL, "DefineSavepoint: unexpected state %s",
3128 BlockStateAsString(s->blockState));
3135 * This executes a RELEASE command.
3137 * As above, we don't actually do anything here except change blockState.
3140 ReleaseSavepoint(List *options)
3142 TransactionState s = CurrentTransactionState;
3143 TransactionState target,
3148 switch (s->blockState)
3151 * We can't rollback to a savepoint if there is no savepoint
3154 case TBLOCK_INPROGRESS:
3156 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3157 errmsg("no such savepoint")));
3161 * We are in a non-aborted subtransaction. This is the only valid
3164 case TBLOCK_SUBINPROGRESS:
3167 /* These cases are invalid. */
3168 case TBLOCK_DEFAULT:
3169 case TBLOCK_STARTED:
3171 case TBLOCK_SUBBEGIN:
3175 case TBLOCK_SUBABORT:
3176 case TBLOCK_ABORT_END:
3177 case TBLOCK_SUBABORT_END:
3178 case TBLOCK_ABORT_PENDING:
3179 case TBLOCK_SUBABORT_PENDING:
3180 case TBLOCK_SUBRESTART:
3181 case TBLOCK_SUBABORT_RESTART:
3182 case TBLOCK_PREPARE:
3183 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3184 BlockStateAsString(s->blockState));
3188 foreach(cell, options)
3190 DefElem *elem = lfirst(cell);
3192 if (strcmp(elem->defname, "savepoint_name") == 0)
3193 name = strVal(elem->arg);
3196 Assert(PointerIsValid(name));
3198 for (target = s; PointerIsValid(target); target = target->parent)
3200 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3204 if (!PointerIsValid(target))
3206 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3207 errmsg("no such savepoint")));
3209 /* disallow crossing savepoint level boundaries */
3210 if (target->savepointLevel != s->savepointLevel)
3212 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3213 errmsg("no such savepoint")));
3216 * Mark "commit pending" all subtransactions up to the target
3217 * subtransaction. The actual commits will happen when control gets to
3218 * CommitTransactionCommand.
3220 xact = CurrentTransactionState;
3223 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3224 xact->blockState = TBLOCK_SUBEND;
3227 xact = xact->parent;
3228 Assert(PointerIsValid(xact));
3233 * RollbackToSavepoint
3234 * This executes a ROLLBACK TO <savepoint> command.
3236 * As above, we don't actually do anything here except change blockState.
3239 RollbackToSavepoint(List *options)
3241 TransactionState s = CurrentTransactionState;
3242 TransactionState target,
3247 switch (s->blockState)
3250 * We can't rollback to a savepoint if there is no savepoint
3253 case TBLOCK_INPROGRESS:
3256 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3257 errmsg("no such savepoint")));
3261 * There is at least one savepoint, so proceed.
3263 case TBLOCK_SUBINPROGRESS:
3264 case TBLOCK_SUBABORT:
3267 /* These cases are invalid. */
3268 case TBLOCK_DEFAULT:
3269 case TBLOCK_STARTED:
3271 case TBLOCK_SUBBEGIN:
3274 case TBLOCK_ABORT_END:
3275 case TBLOCK_SUBABORT_END:
3276 case TBLOCK_ABORT_PENDING:
3277 case TBLOCK_SUBABORT_PENDING:
3278 case TBLOCK_SUBRESTART:
3279 case TBLOCK_SUBABORT_RESTART:
3280 case TBLOCK_PREPARE:
3281 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3282 BlockStateAsString(s->blockState));
3286 foreach(cell, options)
3288 DefElem *elem = lfirst(cell);
3290 if (strcmp(elem->defname, "savepoint_name") == 0)
3291 name = strVal(elem->arg);
3294 Assert(PointerIsValid(name));
3296 for (target = s; PointerIsValid(target); target = target->parent)
3298 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3302 if (!PointerIsValid(target))
3304 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3305 errmsg("no such savepoint")));
3307 /* disallow crossing savepoint level boundaries */
3308 if (target->savepointLevel != s->savepointLevel)
3310 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3311 errmsg("no such savepoint")));
3314 * Mark "abort pending" all subtransactions up to the target
3315 * subtransaction. The actual aborts will happen when control gets to
3316 * CommitTransactionCommand.
3318 xact = CurrentTransactionState;
3323 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3324 xact->blockState = TBLOCK_SUBABORT_PENDING;
3325 else if (xact->blockState == TBLOCK_SUBABORT)
3326 xact->blockState = TBLOCK_SUBABORT_END;
3328 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3329 BlockStateAsString(xact->blockState));
3330 xact = xact->parent;
3331 Assert(PointerIsValid(xact));
3334 /* And mark the target as "restart pending" */
3335 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3336 xact->blockState = TBLOCK_SUBRESTART;
3337 else if (xact->blockState == TBLOCK_SUBABORT)
3338 xact->blockState = TBLOCK_SUBABORT_RESTART;
3340 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3341 BlockStateAsString(xact->blockState));
3345 * BeginInternalSubTransaction
3346 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3347 * TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3348 * used in functions that might be called when not inside a BEGIN block
3349 * or when running deferred triggers at COMMIT/PREPARE time. Also, it
3350 * automatically does CommitTransactionCommand/StartTransactionCommand
3351 * instead of expecting the caller to do it.
3354 BeginInternalSubTransaction(char *name)
3356 TransactionState s = CurrentTransactionState;
3358 switch (s->blockState)
3360 case TBLOCK_STARTED:
3361 case TBLOCK_INPROGRESS:
3363 case TBLOCK_PREPARE:
3364 case TBLOCK_SUBINPROGRESS:
3365 /* Normal subtransaction start */
3367 s = CurrentTransactionState; /* changed by push */
3370 * Savepoint names, like the TransactionState block itself, live
3371 * in TopTransactionContext.
3374 s->name = MemoryContextStrdup(TopTransactionContext, name);
3377 /* These cases are invalid. */
3378 case TBLOCK_DEFAULT:
3380 case TBLOCK_SUBBEGIN:
3383 case TBLOCK_SUBABORT:
3384 case TBLOCK_ABORT_END:
3385 case TBLOCK_SUBABORT_END:
3386 case TBLOCK_ABORT_PENDING:
3387 case TBLOCK_SUBABORT_PENDING:
3388 case TBLOCK_SUBRESTART:
3389 case TBLOCK_SUBABORT_RESTART:
3390 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3391 BlockStateAsString(s->blockState));
3395 CommitTransactionCommand();
3396 StartTransactionCommand();
3400 * ReleaseCurrentSubTransaction
3402 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3403 * savepoint name (if any).
3404 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3407 ReleaseCurrentSubTransaction(void)
3409 TransactionState s = CurrentTransactionState;
3411 if (s->blockState != TBLOCK_SUBINPROGRESS)
3412 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3413 BlockStateAsString(s->blockState));
3414 Assert(s->state == TRANS_INPROGRESS);
3415 MemoryContextSwitchTo(CurTransactionContext);
3416 CommitSubTransaction();
3417 s = CurrentTransactionState; /* changed by pop */
3418 Assert(s->state == TRANS_INPROGRESS);
3422 * RollbackAndReleaseCurrentSubTransaction
3424 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3425 * of its savepoint name (if any).
3426 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3429 RollbackAndReleaseCurrentSubTransaction(void)
3431 TransactionState s = CurrentTransactionState;
3433 switch (s->blockState)
3435 /* Must be in a subtransaction */
3436 case TBLOCK_SUBINPROGRESS:
3437 case TBLOCK_SUBABORT:
3440 /* These cases are invalid. */
3441 case TBLOCK_DEFAULT:
3442 case TBLOCK_STARTED:
3444 case TBLOCK_SUBBEGIN:
3445 case TBLOCK_INPROGRESS:
3449 case TBLOCK_ABORT_END:
3450 case TBLOCK_SUBABORT_END:
3451 case TBLOCK_ABORT_PENDING:
3452 case TBLOCK_SUBABORT_PENDING:
3453 case TBLOCK_SUBRESTART:
3454 case TBLOCK_SUBABORT_RESTART:
3455 case TBLOCK_PREPARE:
3456 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3457 BlockStateAsString(s->blockState));
3462 * Abort the current subtransaction, if needed.
3464 if (s->blockState == TBLOCK_SUBINPROGRESS)
3465 AbortSubTransaction();
3467 /* And clean it up, too */
3468 CleanupSubTransaction();
3470 s = CurrentTransactionState; /* changed by pop */
3471 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3472 s->blockState == TBLOCK_INPROGRESS ||
3473 s->blockState == TBLOCK_STARTED);
3477 * AbortOutOfAnyTransaction
3479 * This routine is provided for error recovery purposes. It aborts any
3480 * active transaction or transaction block, leaving the system in a known
3484 AbortOutOfAnyTransaction(void)
3486 TransactionState s = CurrentTransactionState;
3489 * Get out of any transaction or nested transaction
3493 switch (s->blockState)
3495 case TBLOCK_DEFAULT:
3496 /* Not in a transaction, do nothing */
3498 case TBLOCK_STARTED:
3500 case TBLOCK_INPROGRESS:
3502 case TBLOCK_ABORT_PENDING:
3503 case TBLOCK_PREPARE:
3504 /* In a transaction, so clean up */
3506 CleanupTransaction();
3507 s->blockState = TBLOCK_DEFAULT;
3510 case TBLOCK_ABORT_END:
3511 /* AbortTransaction already done, still need Cleanup */
3512 CleanupTransaction();
3513 s->blockState = TBLOCK_DEFAULT;
3517 * In a subtransaction, so clean it up and abort parent too
3519 case TBLOCK_SUBBEGIN:
3520 case TBLOCK_SUBINPROGRESS:
3522 case TBLOCK_SUBABORT_PENDING:
3523 case TBLOCK_SUBRESTART:
3524 AbortSubTransaction();
3525 CleanupSubTransaction();
3526 s = CurrentTransactionState; /* changed by pop */
3529 case TBLOCK_SUBABORT:
3530 case TBLOCK_SUBABORT_END:
3531 case TBLOCK_SUBABORT_RESTART:
3532 /* As above, but AbortSubTransaction already done */
3533 CleanupSubTransaction();
3534 s = CurrentTransactionState; /* changed by pop */
3537 } while (s->blockState != TBLOCK_DEFAULT);
3539 /* Should be out of all subxacts now */
3540 Assert(s->parent == NULL);
3544 * IsTransactionBlock --- are we within a transaction block?
3547 IsTransactionBlock(void)
3549 TransactionState s = CurrentTransactionState;
3551 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3558 * IsTransactionOrTransactionBlock --- are we within either a transaction
3559 * or a transaction block? (The backend is only really "idle" when this
3562 * This should match up with IsTransactionBlock and IsTransactionState.
3565 IsTransactionOrTransactionBlock(void)
3567 TransactionState s = CurrentTransactionState;
3569 if (s->blockState == TBLOCK_DEFAULT)
3576 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3579 TransactionBlockStatusCode(void)
3581 TransactionState s = CurrentTransactionState;
3583 switch (s->blockState)
3585 case TBLOCK_DEFAULT:
3586 case TBLOCK_STARTED:
3587 return 'I'; /* idle --- not in transaction */
3589 case TBLOCK_SUBBEGIN:
3590 case TBLOCK_INPROGRESS:
3591 case TBLOCK_SUBINPROGRESS:
3594 case TBLOCK_PREPARE:
3595 return 'T'; /* in transaction */
3597 case TBLOCK_SUBABORT:
3598 case TBLOCK_ABORT_END:
3599 case TBLOCK_SUBABORT_END:
3600 case TBLOCK_ABORT_PENDING:
3601 case TBLOCK_SUBABORT_PENDING:
3602 case TBLOCK_SUBRESTART:
3603 case TBLOCK_SUBABORT_RESTART:
3604 return 'E'; /* in failed transaction */
3607 /* should never get here */
3608 elog(FATAL, "invalid transaction block state: %s",
3609 BlockStateAsString(s->blockState));
3610 return 0; /* keep compiler quiet */
3617 IsSubTransaction(void)
3619 TransactionState s = CurrentTransactionState;
3621 if (s->nestingLevel >= 2)
3628 * StartSubTransaction
3630 * If you're wondering why this is separate from PushTransaction: it's because
3631 * we can't conveniently do this stuff right inside DefineSavepoint. The
3632 * SAVEPOINT utility command will be executed inside a Portal, and if we
3633 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3634 * the Portal will undo those settings. So we make DefineSavepoint just
3635 * push a dummy transaction block, and when control returns to the main
3636 * idle loop, CommitTransactionCommand will be called, and we'll come here
3637 * to finish starting the subtransaction.
3640 StartSubTransaction(void)
3642 TransactionState s = CurrentTransactionState;
3644 if (s->state != TRANS_DEFAULT)
3645 elog(WARNING, "StartSubTransaction while in %s state",
3646 TransStateAsString(s->state));
3648 s->state = TRANS_START;
3651 * Initialize subsystems for new subtransaction
3653 * must initialize resource-management stuff first
3655 AtSubStart_Memory();
3656 AtSubStart_ResourceOwner();
3658 AtSubStart_Notify();
3659 AfterTriggerBeginSubXact();
3661 s->state = TRANS_INPROGRESS;
3664 * Call start-of-subxact callbacks
3666 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3667 s->parent->subTransactionId);
3669 ShowTransactionState("StartSubTransaction");
3673 * CommitSubTransaction
3675 * The caller has to make sure to always reassign CurrentTransactionState
3676 * if it has a local pointer to it after calling this function.
3679 CommitSubTransaction(void)
3681 TransactionState s = CurrentTransactionState;
3683 ShowTransactionState("CommitSubTransaction");
3685 if (s->state != TRANS_INPROGRESS)
3686 elog(WARNING, "CommitSubTransaction while in %s state",
3687 TransStateAsString(s->state));
3689 /* Pre-commit processing goes here -- nothing to do at the moment */
3691 s->state = TRANS_COMMIT;
3693 /* Must CCI to ensure commands of subtransaction are seen as done */
3694 CommandCounterIncrement();
3696 /* Mark subtransaction as subcommitted */
3697 RecordSubTransactionCommit();
3699 /* Post-commit cleanup */
3700 if (TransactionIdIsValid(s->transactionId))
3701 AtSubCommit_childXids();
3702 AfterTriggerEndSubXact(true);
3703 AtSubCommit_Portals(s->subTransactionId,
3704 s->parent->subTransactionId,
3705 s->parent->curTransactionOwner);
3706 AtEOSubXact_LargeObject(true, s->subTransactionId,
3707 s->parent->subTransactionId);
3708 AtSubCommit_Notify();
3709 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3710 s->parent->subTransactionId);
3712 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3713 s->parent->subTransactionId);
3715 ResourceOwnerRelease(s->curTransactionOwner,
3716 RESOURCE_RELEASE_BEFORE_LOCKS,
3718 AtEOSubXact_RelationCache(true, s->subTransactionId,
3719 s->parent->subTransactionId);
3720 AtEOSubXact_Inval(true);
3724 * The only lock we actually release here is the subtransaction XID lock.
3725 * The rest just get transferred to the parent resource owner.
3727 CurrentResourceOwner = s->curTransactionOwner;
3728 if (TransactionIdIsValid(s->transactionId))
3729 XactLockTableDelete(s->transactionId);
3731 ResourceOwnerRelease(s->curTransactionOwner,
3732 RESOURCE_RELEASE_LOCKS,
3734 ResourceOwnerRelease(s->curTransactionOwner,
3735 RESOURCE_RELEASE_AFTER_LOCKS,
3738 AtEOXact_GUC(true, s->gucNestLevel);
3739 AtEOSubXact_SPI(true, s->subTransactionId);
3740 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3741 s->parent->subTransactionId);
3742 AtEOSubXact_Namespace(true, s->subTransactionId,
3743 s->parent->subTransactionId);
3744 AtEOSubXact_Files(true, s->subTransactionId,
3745 s->parent->subTransactionId);
3746 AtEOSubXact_HashTables(true, s->nestingLevel);
3747 AtEOSubXact_PgStat(true, s->nestingLevel);
3750 * We need to restore the upper transaction's read-only state, in case the
3751 * upper is read-write while the child is read-only; GUC will incorrectly
3752 * think it should leave the child state in place.
3754 XactReadOnly = s->prevXactReadOnly;
3756 CurrentResourceOwner = s->parent->curTransactionOwner;
3757 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3758 ResourceOwnerDelete(s->curTransactionOwner);
3759 s->curTransactionOwner = NULL;
3761 AtSubCommit_Memory();
3763 s->state = TRANS_DEFAULT;
3769 * AbortSubTransaction
3772 AbortSubTransaction(void)
3774 TransactionState s = CurrentTransactionState;
3776 /* Prevent cancel/die interrupt while cleaning up */
3779 /* Make sure we have a valid memory context and resource owner */
3780 AtSubAbort_Memory();
3781 AtSubAbort_ResourceOwner();
3784 * Release any LW locks we might be holding as quickly as possible.
3785 * (Regular locks, however, must be held till we finish aborting.)
3786 * Releasing LW locks is critical since we might try to grab them again
3787 * while cleaning up!
3789 * FIXME This may be incorrect --- Are there some locks we should keep?
3790 * Buffer locks, for example? I don't think so but I'm not sure.
3800 * check the current transaction state
3802 ShowTransactionState("AbortSubTransaction");
3804 if (s->state != TRANS_INPROGRESS)
3805 elog(WARNING, "AbortSubTransaction while in %s state",
3806 TransStateAsString(s->state));
3808 s->state = TRANS_ABORT;
3811 * Reset user ID which might have been changed transiently. (See notes
3812 * in AbortTransaction.)
3814 SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
3817 * We can skip all this stuff if the subxact failed before creating a
3820 if (s->curTransactionOwner)
3822 AfterTriggerEndSubXact(false);
3823 AtSubAbort_Portals(s->subTransactionId,
3824 s->parent->subTransactionId,
3825 s->parent->curTransactionOwner);
3826 AtEOSubXact_LargeObject(false, s->subTransactionId,
3827 s->parent->subTransactionId);
3828 AtSubAbort_Notify();
3829 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3830 s->parent->subTransactionId);
3832 /* Advertise the fact that we aborted in pg_clog. */
3833 (void) RecordTransactionAbort(true);
3835 /* Post-abort cleanup */
3836 if (TransactionIdIsValid(s->transactionId))
3837 AtSubAbort_childXids();
3839 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3840 s->parent->subTransactionId);
3842 ResourceOwnerRelease(s->curTransactionOwner,
3843 RESOURCE_RELEASE_BEFORE_LOCKS,
3845 AtEOSubXact_RelationCache(false, s->subTransactionId,
3846 s->parent->subTransactionId);
3847 AtEOSubXact_Inval(false);
3849 ResourceOwnerRelease(s->curTransactionOwner,
3850 RESOURCE_RELEASE_LOCKS,
3852 ResourceOwnerRelease(s->curTransactionOwner,
3853 RESOURCE_RELEASE_AFTER_LOCKS,
3856 AtEOXact_GUC(false, s->gucNestLevel);
3857 AtEOSubXact_SPI(false, s->subTransactionId);
3859 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3860 s->parent->subTransactionId);
3861 AtEOSubXact_Namespace(false, s->subTransactionId,
3862 s->parent->subTransactionId);
3863 AtEOSubXact_Files(false, s->subTransactionId,
3864 s->parent->subTransactionId);
3865 AtEOSubXact_HashTables(false, s->nestingLevel);
3866 AtEOSubXact_PgStat(false, s->nestingLevel);
3870 * Restore the upper transaction's read-only state, too. This should be
3871 * redundant with GUC's cleanup but we may as well do it for consistency
3872 * with the commit case.
3874 XactReadOnly = s->prevXactReadOnly;
3876 RESUME_INTERRUPTS();
3880 * CleanupSubTransaction
3882 * The caller has to make sure to always reassign CurrentTransactionState
3883 * if it has a local pointer to it after calling this function.
3886 CleanupSubTransaction(void)
3888 TransactionState s = CurrentTransactionState;
3890 ShowTransactionState("CleanupSubTransaction");
3892 if (s->state != TRANS_ABORT)
3893 elog(WARNING, "CleanupSubTransaction while in %s state",
3894 TransStateAsString(s->state));
3896 AtSubCleanup_Portals(s->subTransactionId);
3898 CurrentResourceOwner = s->parent->curTransactionOwner;
3899 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3900 if (s->curTransactionOwner)
3901 ResourceOwnerDelete(s->curTransactionOwner);
3902 s->curTransactionOwner = NULL;
3904 AtSubCleanup_Memory();
3906 s->state = TRANS_DEFAULT;
3913 * Create transaction state stack entry for a subtransaction
3915 * The caller has to make sure to always reassign CurrentTransactionState
3916 * if it has a local pointer to it after calling this function.
3919 PushTransaction(void)
3921 TransactionState p = CurrentTransactionState;
3925 * We keep subtransaction state nodes in TopTransactionContext.
3927 s = (TransactionState)
3928 MemoryContextAllocZero(TopTransactionContext,
3929 sizeof(TransactionStateData));
3932 * Assign a subtransaction ID, watching out for counter wraparound.
3934 currentSubTransactionId += 1;
3935 if (currentSubTransactionId == InvalidSubTransactionId)
3937 currentSubTransactionId -= 1;
3940 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3941 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3945 * We can now stack a minimally valid subtransaction without fear of
3948 s->transactionId = InvalidTransactionId; /* until assigned */
3949 s->subTransactionId = currentSubTransactionId;
3951 s->nestingLevel = p->nestingLevel + 1;
3952 s->gucNestLevel = NewGUCNestLevel();
3953 s->savepointLevel = p->savepointLevel;
3954 s->state = TRANS_DEFAULT;
3955 s->blockState = TBLOCK_SUBBEGIN;
3956 GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
3957 s->prevXactReadOnly = XactReadOnly;
3959 CurrentTransactionState = s;
3962 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
3963 * with the subtransaction from here on out; in particular they should not
3964 * assume that it necessarily has a transaction context, resource owner,
3971 * Pop back to parent transaction state
3973 * The caller has to make sure to always reassign CurrentTransactionState
3974 * if it has a local pointer to it after calling this function.
3977 PopTransaction(void)
3979 TransactionState s = CurrentTransactionState;
3981 if (s->state != TRANS_DEFAULT)
3982 elog(WARNING, "PopTransaction while in %s state",
3983 TransStateAsString(s->state));
3985 if (s->parent == NULL)
3986 elog(FATAL, "PopTransaction with no parent");
3988 CurrentTransactionState = s->parent;
3990 /* Let's just make sure CurTransactionContext is good */
3991 CurTransactionContext = s->parent->curTransactionContext;
3992 MemoryContextSwitchTo(CurTransactionContext);
3994 /* Ditto for ResourceOwner links */
3995 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3996 CurrentResourceOwner = s->parent->curTransactionOwner;
3998 /* Free the old child structure */
4005 * ShowTransactionState
4009 ShowTransactionState(const char *str)
4011 /* skip work if message will definitely not be printed */
4012 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
4014 elog(DEBUG3, "%s", str);
4015 ShowTransactionStateRec(CurrentTransactionState);
4020 * ShowTransactionStateRec
4021 * Recursive subroutine for ShowTransactionState
4024 ShowTransactionStateRec(TransactionState s)
4027 ShowTransactionStateRec(s->parent);
4029 /* use ereport to suppress computation if msg will not be printed */
4031 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
4032 PointerIsValid(s->name) ? s->name : "unnamed",
4033 BlockStateAsString(s->blockState),
4034 TransStateAsString(s->state),
4035 (unsigned int) s->transactionId,
4036 (unsigned int) s->subTransactionId,
4037 (unsigned int) currentCommandId,
4038 currentCommandIdUsed ? " (used)" : "",
4040 nodeToString(s->childXids))));
4044 * BlockStateAsString
4048 BlockStateAsString(TBlockState blockState)
4052 case TBLOCK_DEFAULT:
4054 case TBLOCK_STARTED:
4058 case TBLOCK_INPROGRESS:
4059 return "INPROGRESS";
4064 case TBLOCK_ABORT_END:
4066 case TBLOCK_ABORT_PENDING:
4067 return "ABORT PEND";
4068 case TBLOCK_PREPARE:
4070 case TBLOCK_SUBBEGIN:
4072 case TBLOCK_SUBINPROGRESS:
4073 return "SUB INPROGRS";
4076 case TBLOCK_SUBABORT:
4078 case TBLOCK_SUBABORT_END:
4079 return "SUB ABORT END";
4080 case TBLOCK_SUBABORT_PENDING:
4081 return "SUB ABRT PEND";
4082 case TBLOCK_SUBRESTART:
4083 return "SUB RESTART";
4084 case TBLOCK_SUBABORT_RESTART:
4085 return "SUB AB RESTRT";
4087 return "UNRECOGNIZED";
4091 * TransStateAsString
4095 TransStateAsString(TransState state)
4103 case TRANS_INPROGRESS:
4112 return "UNRECOGNIZED";
4116 * xactGetCommittedChildren
4118 * Gets the list of committed children of the current transaction. The return
4119 * value is the number of child transactions. *children is set to point to a
4120 * palloc'd array of TransactionIds. If there are no subxacts, *children is
4124 xactGetCommittedChildren(TransactionId **ptr)
4126 TransactionState s = CurrentTransactionState;
4128 TransactionId *children;
4131 nchildren = list_length(s->childXids);
4138 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4141 foreach(p, s->childXids)
4143 TransactionId child = lfirst_xid(p);
4145 *children++ = child;
4152 * XLOG support routines
4156 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4158 TransactionId *sub_xids;
4159 TransactionId max_xid;
4162 TransactionIdCommit(xid);
4164 /* Mark committed subtransactions as committed */
4165 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4166 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4168 /* Make sure nextXid is beyond any XID mentioned in the record */
4170 for (i = 0; i < xlrec->nsubxacts; i++)
4172 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4173 max_xid = sub_xids[i];
4175 if (TransactionIdFollowsOrEquals(max_xid,
4176 ShmemVariableCache->nextXid))
4178 ShmemVariableCache->nextXid = max_xid;
4179 TransactionIdAdvance(ShmemVariableCache->nextXid);
4182 /* Make sure files supposed to be dropped are dropped */
4183 for (i = 0; i < xlrec->nrels; i++)
4185 XLogDropRelation(xlrec->xnodes[i]);
4186 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4191 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4193 TransactionId *sub_xids;
4194 TransactionId max_xid;
4197 TransactionIdAbort(xid);
4199 /* Mark subtransactions as aborted */
4200 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4201 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4203 /* Make sure nextXid is beyond any XID mentioned in the record */
4205 for (i = 0; i < xlrec->nsubxacts; i++)
4207 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4208 max_xid = sub_xids[i];
4210 if (TransactionIdFollowsOrEquals(max_xid,
4211 ShmemVariableCache->nextXid))
4213 ShmemVariableCache->nextXid = max_xid;
4214 TransactionIdAdvance(ShmemVariableCache->nextXid);
4217 /* Make sure files supposed to be dropped are dropped */
4218 for (i = 0; i < xlrec->nrels; i++)
4220 XLogDropRelation(xlrec->xnodes[i]);
4221 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4226 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4228 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4230 if (info == XLOG_XACT_COMMIT)
4232 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4234 xact_redo_commit(xlrec, record->xl_xid);
4236 else if (info == XLOG_XACT_ABORT)
4238 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4240 xact_redo_abort(xlrec, record->xl_xid);
4242 else if (info == XLOG_XACT_PREPARE)
4244 /* the record contents are exactly the 2PC file */
4245 RecreateTwoPhaseFile(record->xl_xid,
4246 XLogRecGetData(record), record->xl_len);
4248 else if (info == XLOG_XACT_COMMIT_PREPARED)
4250 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4252 xact_redo_commit(&xlrec->crec, xlrec->xid);
4253 RemoveTwoPhaseFile(xlrec->xid, false);
4255 else if (info == XLOG_XACT_ABORT_PREPARED)
4257 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4259 xact_redo_abort(&xlrec->arec, xlrec->xid);
4260 RemoveTwoPhaseFile(xlrec->xid, false);
4263 elog(PANIC, "xact_redo: unknown op code %u", info);
4267 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4271 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4272 if (xlrec->nrels > 0)
4274 appendStringInfo(buf, "; rels:");
4275 for (i = 0; i < xlrec->nrels; i++)
4277 RelFileNode rnode = xlrec->xnodes[i];
4279 appendStringInfo(buf, " %u/%u/%u",
4280 rnode.spcNode, rnode.dbNode, rnode.relNode);
4283 if (xlrec->nsubxacts > 0)
4285 TransactionId *xacts = (TransactionId *)
4286 &xlrec->xnodes[xlrec->nrels];
4288 appendStringInfo(buf, "; subxacts:");
4289 for (i = 0; i < xlrec->nsubxacts; i++)
4290 appendStringInfo(buf, " %u", xacts[i]);
4295 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4299 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4300 if (xlrec->nrels > 0)
4302 appendStringInfo(buf, "; rels:");
4303 for (i = 0; i < xlrec->nrels; i++)
4305 RelFileNode rnode = xlrec->xnodes[i];
4307 appendStringInfo(buf, " %u/%u/%u",
4308 rnode.spcNode, rnode.dbNode, rnode.relNode);
4311 if (xlrec->nsubxacts > 0)
4313 TransactionId *xacts = (TransactionId *)
4314 &xlrec->xnodes[xlrec->nrels];
4316 appendStringInfo(buf, "; subxacts:");
4317 for (i = 0; i < xlrec->nsubxacts; i++)
4318 appendStringInfo(buf, " %u", xacts[i]);
4323 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4325 uint8 info = xl_info & ~XLR_INFO_MASK;
4327 if (info == XLOG_XACT_COMMIT)
4329 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4331 appendStringInfo(buf, "commit: ");
4332 xact_desc_commit(buf, xlrec);
4334 else if (info == XLOG_XACT_ABORT)
4336 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4338 appendStringInfo(buf, "abort: ");
4339 xact_desc_abort(buf, xlrec);
4341 else if (info == XLOG_XACT_PREPARE)
4343 appendStringInfo(buf, "prepare");
4345 else if (info == XLOG_XACT_COMMIT_PREPARED)
4347 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4349 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4350 xact_desc_commit(buf, &xlrec->crec);
4352 else if (info == XLOG_XACT_ABORT_PREPARED)
4354 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4356 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4357 xact_desc_abort(buf, &xlrec->arec);
4360 appendStringInfo(buf, "UNKNOWN");