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
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/bufmgr.h"
38 #include "storage/fd.h"
39 #include "storage/lmgr.h"
40 #include "storage/procarray.h"
41 #include "storage/sinvaladt.h"
42 #include "storage/smgr.h"
43 #include "utils/combocid.h"
44 #include "utils/flatfiles.h"
45 #include "utils/guc.h"
46 #include "utils/inval.h"
47 #include "utils/memutils.h"
48 #include "utils/relcache.h"
49 #include "utils/snapmgr.h"
50 #include "utils/xml.h"
55 * User-tweakable parameters
57 int DefaultXactIsoLevel
= XACT_READ_COMMITTED
;
60 bool DefaultXactReadOnly
= false;
63 bool XactSyncCommit
= true;
65 int CommitDelay
= 0; /* precommit delay in microseconds */
66 int CommitSiblings
= 5; /* # concurrent xacts needed to sleep */
69 * MyXactAccessedTempRel is set when a temporary relation is accessed.
70 * We don't allow PREPARE TRANSACTION in that case. (This is global
71 * so that it can be set from heapam.c.)
73 bool MyXactAccessedTempRel
= false;
77 * transaction states - transaction state from server perspective
79 typedef enum TransState
81 TRANS_DEFAULT
, /* idle */
82 TRANS_START
, /* transaction starting */
83 TRANS_INPROGRESS
, /* inside a valid transaction */
84 TRANS_COMMIT
, /* commit in progress */
85 TRANS_ABORT
, /* abort in progress */
86 TRANS_PREPARE
/* prepare in progress */
90 * transaction block states - transaction state of client queries
92 * Note: the subtransaction states are used only for non-topmost
93 * transactions; the others appear only in the topmost transaction.
95 typedef enum TBlockState
97 /* not-in-transaction-block states */
98 TBLOCK_DEFAULT
, /* idle */
99 TBLOCK_STARTED
, /* running single-query transaction */
101 /* transaction block states */
102 TBLOCK_BEGIN
, /* starting transaction block */
103 TBLOCK_INPROGRESS
, /* live transaction */
104 TBLOCK_END
, /* COMMIT received */
105 TBLOCK_ABORT
, /* failed xact, awaiting ROLLBACK */
106 TBLOCK_ABORT_END
, /* failed xact, ROLLBACK received */
107 TBLOCK_ABORT_PENDING
, /* live xact, ROLLBACK received */
108 TBLOCK_PREPARE
, /* live xact, PREPARE received */
110 /* subtransaction states */
111 TBLOCK_SUBBEGIN
, /* starting a subtransaction */
112 TBLOCK_SUBINPROGRESS
, /* live subtransaction */
113 TBLOCK_SUBEND
, /* RELEASE received */
114 TBLOCK_SUBABORT
, /* failed subxact, awaiting ROLLBACK */
115 TBLOCK_SUBABORT_END
, /* failed subxact, ROLLBACK received */
116 TBLOCK_SUBABORT_PENDING
, /* live subxact, ROLLBACK received */
117 TBLOCK_SUBRESTART
, /* live subxact, ROLLBACK TO received */
118 TBLOCK_SUBABORT_RESTART
/* failed subxact, ROLLBACK TO received */
122 * transaction state structure
124 typedef struct TransactionStateData
126 TransactionId transactionId
; /* my XID, or Invalid if none */
127 SubTransactionId subTransactionId
; /* my subxact ID */
128 char *name
; /* savepoint name, if any */
129 int savepointLevel
; /* savepoint level */
130 TransState state
; /* low-level state */
131 TBlockState blockState
; /* high-level state */
132 int nestingLevel
; /* transaction nesting depth */
133 int gucNestLevel
; /* GUC context nesting depth */
134 MemoryContext curTransactionContext
; /* my xact-lifetime context */
135 ResourceOwner curTransactionOwner
; /* my query resources */
136 TransactionId
*childXids
; /* subcommitted child XIDs, in XID order */
137 int nChildXids
; /* # of subcommitted child XIDs */
138 int maxChildXids
; /* allocated size of childXids[] */
139 Oid prevUser
; /* previous CurrentUserId setting */
140 bool prevSecDefCxt
; /* previous SecurityDefinerContext setting */
141 bool prevXactReadOnly
; /* entry-time xact r/o state */
142 struct TransactionStateData
*parent
; /* back link to parent */
143 } TransactionStateData
;
145 typedef TransactionStateData
*TransactionState
;
148 * CurrentTransactionState always points to the current transaction state
149 * block. It will point to TopTransactionStateData when not in a
150 * transaction at all, or when in a top-level transaction.
152 static TransactionStateData TopTransactionStateData
= {
153 0, /* transaction id */
154 0, /* subtransaction id */
155 NULL
, /* savepoint name */
156 0, /* savepoint level */
157 TRANS_DEFAULT
, /* transaction state */
158 TBLOCK_DEFAULT
, /* transaction block state from the client
160 0, /* transaction nesting depth */
161 0, /* GUC context nesting depth */
162 NULL
, /* cur transaction context */
163 NULL
, /* cur transaction resource owner */
164 NULL
, /* subcommitted child Xids */
165 0, /* # of subcommitted child Xids */
166 0, /* allocated size of childXids[] */
167 InvalidOid
, /* previous CurrentUserId setting */
168 false, /* previous SecurityDefinerContext setting */
169 false, /* entry-time xact r/o state */
170 NULL
/* link to parent state block */
173 static TransactionState CurrentTransactionState
= &TopTransactionStateData
;
176 * The subtransaction ID and command ID assignment counters are global
177 * to a whole transaction, so we do not keep them in the state stack.
179 static SubTransactionId currentSubTransactionId
;
180 static CommandId currentCommandId
;
181 static bool currentCommandIdUsed
;
184 * xactStartTimestamp is the value of transaction_timestamp().
185 * stmtStartTimestamp is the value of statement_timestamp().
186 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
187 * These do not change as we enter and exit subtransactions, so we don't
188 * keep them inside the TransactionState stack.
190 static TimestampTz xactStartTimestamp
;
191 static TimestampTz stmtStartTimestamp
;
192 static TimestampTz xactStopTimestamp
;
195 * GID to be used for preparing the current transaction. This is also
196 * global to a whole transaction, so we don't keep it in the state stack.
198 static char *prepareGID
;
201 * Some commands want to force synchronous commit.
203 static bool forceSyncCommit
= false;
206 * Private context for transaction-abort work --- we reserve space for this
207 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
208 * when we've run out of memory.
210 static MemoryContext TransactionAbortContext
= NULL
;
213 * List of add-on start- and end-of-xact callbacks
215 typedef struct XactCallbackItem
217 struct XactCallbackItem
*next
;
218 XactCallback callback
;
222 static XactCallbackItem
*Xact_callbacks
= NULL
;
225 * List of add-on start- and end-of-subxact callbacks
227 typedef struct SubXactCallbackItem
229 struct SubXactCallbackItem
*next
;
230 SubXactCallback callback
;
232 } SubXactCallbackItem
;
234 static SubXactCallbackItem
*SubXact_callbacks
= NULL
;
237 /* local function prototypes */
238 static void AssignTransactionId(TransactionState s
);
239 static void AbortTransaction(void);
240 static void AtAbort_Memory(void);
241 static void AtCleanup_Memory(void);
242 static void AtAbort_ResourceOwner(void);
243 static void AtCommit_LocalCache(void);
244 static void AtCommit_Memory(void);
245 static void AtStart_Cache(void);
246 static void AtStart_Memory(void);
247 static void AtStart_ResourceOwner(void);
248 static void CallXactCallbacks(XactEvent event
);
249 static void CallSubXactCallbacks(SubXactEvent event
,
250 SubTransactionId mySubid
,
251 SubTransactionId parentSubid
);
252 static void CleanupTransaction(void);
253 static void CommitTransaction(void);
254 static TransactionId
RecordTransactionAbort(bool isSubXact
);
255 static void StartTransaction(void);
257 static void RecordSubTransactionCommit(void);
258 static void StartSubTransaction(void);
259 static void CommitSubTransaction(void);
260 static void AbortSubTransaction(void);
261 static void CleanupSubTransaction(void);
262 static void PushTransaction(void);
263 static void PopTransaction(void);
265 static void AtSubAbort_Memory(void);
266 static void AtSubCleanup_Memory(void);
267 static void AtSubAbort_ResourceOwner(void);
268 static void AtSubCommit_Memory(void);
269 static void AtSubStart_Memory(void);
270 static void AtSubStart_ResourceOwner(void);
272 static void ShowTransactionState(const char *str
);
273 static void ShowTransactionStateRec(TransactionState state
);
274 static const char *BlockStateAsString(TBlockState blockState
);
275 static const char *TransStateAsString(TransState state
);
278 /* ----------------------------------------------------------------
279 * transaction state accessors
280 * ----------------------------------------------------------------
286 * This returns true if we are inside a valid transaction; that is,
287 * it is safe to initiate database access, take heavyweight locks, etc.
290 IsTransactionState(void)
292 TransactionState s
= CurrentTransactionState
;
295 * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we
296 * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
297 * TRANS_PREPARE since it might be too soon or too late within those
298 * transition states to do anything interesting. Hence, the only "valid"
299 * state is TRANS_INPROGRESS.
301 return (s
->state
== TRANS_INPROGRESS
);
305 * IsAbortedTransactionBlockState
307 * This returns true if we are currently running a query
308 * within an aborted transaction block.
311 IsAbortedTransactionBlockState(void)
313 TransactionState s
= CurrentTransactionState
;
315 if (s
->blockState
== TBLOCK_ABORT
||
316 s
->blockState
== TBLOCK_SUBABORT
)
324 * GetTopTransactionId
326 * This will return the XID of the main transaction, assigning one if
327 * it's not yet set. Be careful to call this only inside a valid xact.
330 GetTopTransactionId(void)
332 if (!TransactionIdIsValid(TopTransactionStateData
.transactionId
))
333 AssignTransactionId(&TopTransactionStateData
);
334 return TopTransactionStateData
.transactionId
;
338 * GetTopTransactionIdIfAny
340 * This will return the XID of the main transaction, if one is assigned.
341 * It will return InvalidTransactionId if we are not currently inside a
342 * transaction, or inside a transaction that hasn't yet been assigned an XID.
345 GetTopTransactionIdIfAny(void)
347 return TopTransactionStateData
.transactionId
;
351 * GetCurrentTransactionId
353 * This will return the XID of the current transaction (main or sub
354 * transaction), assigning one if it's not yet set. Be careful to call this
355 * only inside a valid xact.
358 GetCurrentTransactionId(void)
360 TransactionState s
= CurrentTransactionState
;
362 if (!TransactionIdIsValid(s
->transactionId
))
363 AssignTransactionId(s
);
364 return s
->transactionId
;
368 * GetCurrentTransactionIdIfAny
370 * This will return the XID of the current sub xact, if one is assigned.
371 * It will return InvalidTransactionId if we are not currently inside a
372 * transaction, or inside a transaction that hasn't been assigned an XID yet.
375 GetCurrentTransactionIdIfAny(void)
377 return CurrentTransactionState
->transactionId
;
382 * AssignTransactionId
384 * Assigns a new permanent XID to the given TransactionState.
385 * We do not assign XIDs to transactions until/unless this is called.
386 * Also, any parent TransactionStates that don't yet have XIDs are assigned
387 * one; this maintains the invariant that a child transaction has an XID
388 * following its parent's.
391 AssignTransactionId(TransactionState s
)
393 bool isSubXact
= (s
->parent
!= NULL
);
394 ResourceOwner currentOwner
;
396 /* Assert that caller didn't screw up */
397 Assert(!TransactionIdIsValid(s
->transactionId
));
398 Assert(s
->state
== TRANS_INPROGRESS
);
401 * Ensure parent(s) have XIDs, so that a child always has an XID later
404 if (isSubXact
&& !TransactionIdIsValid(s
->parent
->transactionId
))
405 AssignTransactionId(s
->parent
);
408 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
410 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
411 * shared storage other than PG_PROC; because if there's no room for it in
412 * PG_PROC, the subtrans entry is needed to ensure that other backends see
413 * the Xid as "running". See GetNewTransactionId.
415 s
->transactionId
= GetNewTransactionId(isSubXact
);
418 SubTransSetParent(s
->transactionId
, s
->parent
->transactionId
);
421 * Acquire lock on the transaction XID. (We assume this cannot block.) We
422 * have to ensure that the lock is assigned to the transaction's own
425 currentOwner
= CurrentResourceOwner
;
428 CurrentResourceOwner
= s
->curTransactionOwner
;
429 XactLockTableInsert(s
->transactionId
);
433 /* Ensure CurrentResourceOwner is restored on error */
434 CurrentResourceOwner
= currentOwner
;
438 CurrentResourceOwner
= currentOwner
;
443 * GetCurrentSubTransactionId
446 GetCurrentSubTransactionId(void)
448 TransactionState s
= CurrentTransactionState
;
450 return s
->subTransactionId
;
455 * GetCurrentCommandId
457 * "used" must be TRUE if the caller intends to use the command ID to mark
458 * inserted/updated/deleted tuples. FALSE means the ID is being fetched
459 * for read-only purposes (ie, as a snapshot validity cutoff). See
460 * CommandCounterIncrement() for discussion.
463 GetCurrentCommandId(bool used
)
465 /* this is global to a transaction, not subtransaction-local */
467 currentCommandIdUsed
= true;
468 return currentCommandId
;
472 * GetCurrentTransactionStartTimestamp
475 GetCurrentTransactionStartTimestamp(void)
477 return xactStartTimestamp
;
481 * GetCurrentStatementStartTimestamp
484 GetCurrentStatementStartTimestamp(void)
486 return stmtStartTimestamp
;
490 * GetCurrentTransactionStopTimestamp
492 * We return current time if the transaction stop time hasn't been set
493 * (which can happen if we decide we don't need to log an XLOG record).
496 GetCurrentTransactionStopTimestamp(void)
498 if (xactStopTimestamp
!= 0)
499 return xactStopTimestamp
;
500 return GetCurrentTimestamp();
504 * SetCurrentStatementStartTimestamp
507 SetCurrentStatementStartTimestamp(void)
509 stmtStartTimestamp
= GetCurrentTimestamp();
513 * SetCurrentTransactionStopTimestamp
516 SetCurrentTransactionStopTimestamp(void)
518 xactStopTimestamp
= GetCurrentTimestamp();
522 * GetCurrentTransactionNestLevel
524 * Note: this will return zero when not inside any transaction, one when
525 * inside a top-level transaction, etc.
528 GetCurrentTransactionNestLevel(void)
530 TransactionState s
= CurrentTransactionState
;
532 return s
->nestingLevel
;
537 * TransactionIdIsCurrentTransactionId
540 TransactionIdIsCurrentTransactionId(TransactionId xid
)
545 * We always say that BootstrapTransactionId is "not my transaction ID"
546 * even when it is (ie, during bootstrap). Along with the fact that
547 * transam.c always treats BootstrapTransactionId as already committed,
548 * this causes the tqual.c routines to see all tuples as committed, which
549 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
550 * it never updates or deletes them, so all tuples can be presumed good
553 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
554 * not my transaction ID, so we can just return "false" immediately for
555 * any non-normal XID.
557 if (!TransactionIdIsNormal(xid
))
561 * We will return true for the Xid of the current subtransaction, any of
562 * its subcommitted children, any of its parents, or any of their
563 * previously subcommitted children. However, a transaction being aborted
564 * is no longer "current", even though it may still have an entry on the
567 for (s
= CurrentTransactionState
; s
!= NULL
; s
= s
->parent
)
571 if (s
->state
== TRANS_ABORT
)
573 if (!TransactionIdIsValid(s
->transactionId
))
574 continue; /* it can't have any child XIDs either */
575 if (TransactionIdEquals(xid
, s
->transactionId
))
577 /* As the childXids array is ordered, we can use binary search */
579 high
= s
->nChildXids
- 1;
585 middle
= low
+ (high
- low
) / 2;
586 probe
= s
->childXids
[middle
];
587 if (TransactionIdEquals(probe
, xid
))
589 else if (TransactionIdPrecedes(probe
, xid
))
601 * CommandCounterIncrement
604 CommandCounterIncrement(void)
607 * If the current value of the command counter hasn't been "used" to
608 * mark tuples, we need not increment it, since there's no need to
609 * distinguish a read-only command from others. This helps postpone
610 * command counter overflow, and keeps no-op CommandCounterIncrement
613 if (currentCommandIdUsed
)
615 currentCommandId
+= 1;
616 if (currentCommandId
== FirstCommandId
) /* check for overflow */
618 currentCommandId
-= 1;
620 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
621 errmsg("cannot have more than 2^32-1 commands in a transaction")));
623 currentCommandIdUsed
= false;
625 /* Propagate new command ID into static snapshots */
626 SnapshotSetCommandId(currentCommandId
);
629 * Make any catalog changes done by the just-completed command
630 * visible in the local syscache. We obviously don't need to do
631 * this after a read-only command. (But see hacks in inval.c
632 * to make real sure we don't think a command that queued inval
633 * messages was read-only.)
635 AtCommit_LocalCache();
639 * Make any other backends' catalog changes visible to me.
641 * XXX this is probably in the wrong place: CommandCounterIncrement
642 * should be purely a local operation, most likely. However fooling
643 * with this will affect asynchronous cross-backend interactions,
644 * which doesn't seem like a wise thing to do in late beta, so save
645 * improving this for another day - tgl 2007-11-30
653 * Interface routine to allow commands to force a synchronous commit of the
654 * current top-level transaction
657 ForceSyncCommit(void)
659 forceSyncCommit
= true;
663 /* ----------------------------------------------------------------
664 * StartTransaction stuff
665 * ----------------------------------------------------------------
674 AcceptInvalidationMessages();
683 TransactionState s
= CurrentTransactionState
;
686 * If this is the first time through, create a private context for
687 * AbortTransaction to work in. By reserving some space now, we can
688 * insulate AbortTransaction from out-of-memory scenarios. Like
689 * ErrorContext, we set it up with slow growth rate and a nonzero minimum
690 * size, so that space will be reserved immediately.
692 if (TransactionAbortContext
== NULL
)
693 TransactionAbortContext
=
694 AllocSetContextCreate(TopMemoryContext
,
695 "TransactionAbortContext",
701 * We shouldn't have a transaction context already.
703 Assert(TopTransactionContext
== NULL
);
706 * Create a toplevel context for the transaction.
708 TopTransactionContext
=
709 AllocSetContextCreate(TopMemoryContext
,
710 "TopTransactionContext",
711 ALLOCSET_DEFAULT_MINSIZE
,
712 ALLOCSET_DEFAULT_INITSIZE
,
713 ALLOCSET_DEFAULT_MAXSIZE
);
716 * In a top-level transaction, CurTransactionContext is the same as
717 * TopTransactionContext.
719 CurTransactionContext
= TopTransactionContext
;
720 s
->curTransactionContext
= CurTransactionContext
;
722 /* Make the CurTransactionContext active. */
723 MemoryContextSwitchTo(CurTransactionContext
);
727 * AtStart_ResourceOwner
730 AtStart_ResourceOwner(void)
732 TransactionState s
= CurrentTransactionState
;
735 * We shouldn't have a transaction resource owner already.
737 Assert(TopTransactionResourceOwner
== NULL
);
740 * Create a toplevel resource owner for the transaction.
742 s
->curTransactionOwner
= ResourceOwnerCreate(NULL
, "TopTransaction");
744 TopTransactionResourceOwner
= s
->curTransactionOwner
;
745 CurTransactionResourceOwner
= s
->curTransactionOwner
;
746 CurrentResourceOwner
= s
->curTransactionOwner
;
749 /* ----------------------------------------------------------------
750 * StartSubTransaction stuff
751 * ----------------------------------------------------------------
758 AtSubStart_Memory(void)
760 TransactionState s
= CurrentTransactionState
;
762 Assert(CurTransactionContext
!= NULL
);
765 * Create a CurTransactionContext, which will be used to hold data that
766 * survives subtransaction commit but disappears on subtransaction abort.
767 * We make it a child of the immediate parent's CurTransactionContext.
769 CurTransactionContext
= AllocSetContextCreate(CurTransactionContext
,
770 "CurTransactionContext",
771 ALLOCSET_DEFAULT_MINSIZE
,
772 ALLOCSET_DEFAULT_INITSIZE
,
773 ALLOCSET_DEFAULT_MAXSIZE
);
774 s
->curTransactionContext
= CurTransactionContext
;
776 /* Make the CurTransactionContext active. */
777 MemoryContextSwitchTo(CurTransactionContext
);
781 * AtSubStart_ResourceOwner
784 AtSubStart_ResourceOwner(void)
786 TransactionState s
= CurrentTransactionState
;
788 Assert(s
->parent
!= NULL
);
791 * Create a resource owner for the subtransaction. We make it a child of
792 * the immediate parent's resource owner.
794 s
->curTransactionOwner
=
795 ResourceOwnerCreate(s
->parent
->curTransactionOwner
,
798 CurTransactionResourceOwner
= s
->curTransactionOwner
;
799 CurrentResourceOwner
= s
->curTransactionOwner
;
802 /* ----------------------------------------------------------------
803 * CommitTransaction stuff
804 * ----------------------------------------------------------------
808 * RecordTransactionCommit
810 * Returns latest XID among xact and its children, or InvalidTransactionId
811 * if the xact has no XID. (We compute that here just because it's easier.)
813 * This is exported only to support an ugly hack in VACUUM FULL.
816 RecordTransactionCommit(void)
818 TransactionId xid
= GetTopTransactionIdIfAny();
819 bool markXidCommitted
= TransactionIdIsValid(xid
);
820 TransactionId latestXid
= InvalidTransactionId
;
825 TransactionId
*children
;
827 /* Get data needed for commit record */
828 nrels
= smgrGetPendingDeletes(true, &rels
, &haveNonTemp
);
829 nchildren
= xactGetCommittedChildren(&children
);
832 * If we haven't been assigned an XID yet, we neither can, nor do we want
833 * to write a COMMIT record.
835 if (!markXidCommitted
)
838 * We expect that every smgrscheduleunlink is followed by a catalog
839 * update, and hence XID assignment, so we shouldn't get here with any
840 * pending deletes. Use a real test not just an Assert to check this,
841 * since it's a bit fragile.
844 elog(ERROR
, "cannot commit a transaction that deleted files but has no xid");
846 /* Can't have child XIDs either; AssignTransactionId enforces this */
847 Assert(nchildren
== 0);
850 * If we didn't create XLOG entries, we're done here; otherwise we
851 * should flush those entries the same as a commit record. (An
852 * example of a possible record that wouldn't cause an XID to be
853 * assigned is a sequence advance record due to nextval() --- we want
854 * to flush that to disk before reporting commit.)
856 if (XactLastRecEnd
.xrecoff
== 0)
862 * Begin commit critical section and insert the commit XLOG record.
864 XLogRecData rdata
[3];
866 xl_xact_commit xlrec
;
868 /* Tell bufmgr and smgr to prepare for commit */
872 * Mark ourselves as within our "commit critical section". This
873 * forces any concurrent checkpoint to wait until we've updated
874 * pg_clog. Without this, it is possible for the checkpoint to set
875 * REDO after the XLOG record but fail to flush the pg_clog update to
876 * disk, leading to loss of the transaction commit if the system
877 * crashes a little later.
879 * Note: we could, but don't bother to, set this flag in
880 * RecordTransactionAbort. That's because loss of a transaction abort
881 * is noncritical; the presumption would be that it aborted, anyway.
883 * It's safe to change the inCommit flag of our own backend without
884 * holding the ProcArrayLock, since we're the only one modifying it.
885 * This makes checkpoint's determination of which xacts are inCommit a
886 * bit fuzzy, but it doesn't matter.
888 START_CRIT_SECTION();
889 MyProc
->inCommit
= true;
891 SetCurrentTransactionStopTimestamp();
892 xlrec
.xact_time
= xactStopTimestamp
;
894 xlrec
.nsubxacts
= nchildren
;
895 rdata
[0].data
= (char *) (&xlrec
);
896 rdata
[0].len
= MinSizeOfXactCommit
;
897 rdata
[0].buffer
= InvalidBuffer
;
898 /* dump rels to delete */
901 rdata
[0].next
= &(rdata
[1]);
902 rdata
[1].data
= (char *) rels
;
903 rdata
[1].len
= nrels
* sizeof(RelFileFork
);
904 rdata
[1].buffer
= InvalidBuffer
;
907 /* dump committed child Xids */
910 rdata
[lastrdata
].next
= &(rdata
[2]);
911 rdata
[2].data
= (char *) children
;
912 rdata
[2].len
= nchildren
* sizeof(TransactionId
);
913 rdata
[2].buffer
= InvalidBuffer
;
916 rdata
[lastrdata
].next
= NULL
;
918 (void) XLogInsert(RM_XACT_ID
, XLOG_XACT_COMMIT
, rdata
);
922 * Check if we want to commit asynchronously. If the user has set
923 * synchronous_commit = off, and we're not doing cleanup of any non-temp
924 * rels nor committing any command that wanted to force sync commit, then
925 * we can defer flushing XLOG. (We must not allow asynchronous commit if
926 * there are any non-temp tables to be deleted, because we might delete
927 * the files before the COMMIT record is flushed to disk. We do allow
928 * asynchronous commit if all to-be-deleted tables are temporary though,
929 * since they are lost anyway if we crash.)
931 if (XactSyncCommit
|| forceSyncCommit
|| haveNonTemp
)
934 * Synchronous commit case.
936 * Sleep before flush! So we can flush more than one commit records
937 * per single fsync. (The idea is some other backend may do the
938 * XLogFlush while we're sleeping. This needs work still, because on
939 * most Unixen, the minimum select() delay is 10msec or more, which is
942 * We do not sleep if enableFsync is not turned on, nor if there are
943 * fewer than CommitSiblings other backends with active transactions.
945 if (CommitDelay
> 0 && enableFsync
&&
946 CountActiveBackends() >= CommitSiblings
)
947 pg_usleep(CommitDelay
);
949 XLogFlush(XactLastRecEnd
);
952 * Now we may update the CLOG, if we wrote a COMMIT record above
954 if (markXidCommitted
)
956 TransactionIdCommit(xid
);
957 /* to avoid race conditions, the parent must commit first */
958 TransactionIdCommitTree(nchildren
, children
);
964 * Asynchronous commit case.
966 * Report the latest async commit LSN, so that the WAL writer knows to
969 XLogSetAsyncCommitLSN(XactLastRecEnd
);
972 * We must not immediately update the CLOG, since we didn't flush the
973 * XLOG. Instead, we store the LSN up to which the XLOG must be
974 * flushed before the CLOG may be updated.
976 if (markXidCommitted
)
978 TransactionIdAsyncCommit(xid
, XactLastRecEnd
);
979 /* to avoid race conditions, the parent must commit first */
980 TransactionIdAsyncCommitTree(nchildren
, children
, XactLastRecEnd
);
985 * If we entered a commit critical section, leave it now, and let
986 * checkpoints proceed.
988 if (markXidCommitted
)
990 MyProc
->inCommit
= false;
994 /* Compute latestXid while we have the child XIDs handy */
995 latestXid
= TransactionIdLatest(xid
, nchildren
, children
);
997 /* Reset XactLastRecEnd until the next transaction writes something */
998 XactLastRecEnd
.xrecoff
= 0;
1001 /* Clean up local data */
1010 * AtCommit_LocalCache
1013 AtCommit_LocalCache(void)
1016 * Make catalog changes visible to me for the next command.
1018 CommandEndInvalidationMessages();
1025 AtCommit_Memory(void)
1028 * Now that we're "out" of a transaction, have the system allocate things
1029 * in the top memory context instead of per-transaction contexts.
1031 MemoryContextSwitchTo(TopMemoryContext
);
1034 * Release all transaction-local memory.
1036 Assert(TopTransactionContext
!= NULL
);
1037 MemoryContextDelete(TopTransactionContext
);
1038 TopTransactionContext
= NULL
;
1039 CurTransactionContext
= NULL
;
1040 CurrentTransactionState
->curTransactionContext
= NULL
;
1043 /* ----------------------------------------------------------------
1044 * CommitSubTransaction stuff
1045 * ----------------------------------------------------------------
1049 * AtSubCommit_Memory
1052 AtSubCommit_Memory(void)
1054 TransactionState s
= CurrentTransactionState
;
1056 Assert(s
->parent
!= NULL
);
1058 /* Return to parent transaction level's memory context. */
1059 CurTransactionContext
= s
->parent
->curTransactionContext
;
1060 MemoryContextSwitchTo(CurTransactionContext
);
1063 * Ordinarily we cannot throw away the child's CurTransactionContext,
1064 * since the data it contains will be needed at upper commit. However, if
1065 * there isn't actually anything in it, we can throw it away. This avoids
1066 * a small memory leak in the common case of "trivial" subxacts.
1068 if (MemoryContextIsEmpty(s
->curTransactionContext
))
1070 MemoryContextDelete(s
->curTransactionContext
);
1071 s
->curTransactionContext
= NULL
;
1076 * AtSubCommit_childXids
1078 * Pass my own XID and my child XIDs up to my parent as committed children.
1081 AtSubCommit_childXids(void)
1083 TransactionState s
= CurrentTransactionState
;
1086 Assert(s
->parent
!= NULL
);
1089 * The parent childXids array will need to hold my XID and all my
1090 * childXids, in addition to the XIDs already there.
1092 new_nChildXids
= s
->parent
->nChildXids
+ s
->nChildXids
+ 1;
1094 /* Allocate or enlarge the parent array if necessary */
1095 if (s
->parent
->maxChildXids
< new_nChildXids
)
1097 int new_maxChildXids
;
1098 TransactionId
*new_childXids
;
1101 * Make it 2x what's needed right now, to avoid having to enlarge it
1102 * repeatedly. But we can't go above MaxAllocSize. (The latter
1103 * limit is what ensures that we don't need to worry about integer
1104 * overflow here or in the calculation of new_nChildXids.)
1106 new_maxChildXids
= Min(new_nChildXids
* 2,
1107 (int) (MaxAllocSize
/ sizeof(TransactionId
)));
1109 if (new_maxChildXids
< new_nChildXids
)
1111 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
1112 errmsg("maximum number of committed subtransactions (%d) exceeded",
1113 (int) (MaxAllocSize
/ sizeof(TransactionId
)))));
1116 * We keep the child-XID arrays in TopTransactionContext; this avoids
1117 * setting up child-transaction contexts for what might be just a few
1118 * bytes of grandchild XIDs.
1120 if (s
->parent
->childXids
== NULL
)
1122 MemoryContextAlloc(TopTransactionContext
,
1123 new_maxChildXids
* sizeof(TransactionId
));
1125 new_childXids
= repalloc(s
->parent
->childXids
,
1126 new_maxChildXids
* sizeof(TransactionId
));
1128 s
->parent
->childXids
= new_childXids
;
1129 s
->parent
->maxChildXids
= new_maxChildXids
;
1133 * Copy all my XIDs to parent's array.
1135 * Note: We rely on the fact that the XID of a child always follows that
1136 * of its parent. By copying the XID of this subtransaction before the
1137 * XIDs of its children, we ensure that the array stays ordered. Likewise,
1138 * all XIDs already in the array belong to subtransactions started and
1139 * subcommitted before us, so their XIDs must precede ours.
1141 s
->parent
->childXids
[s
->parent
->nChildXids
] = s
->transactionId
;
1143 if (s
->nChildXids
> 0)
1144 memcpy(&s
->parent
->childXids
[s
->parent
->nChildXids
+ 1],
1146 s
->nChildXids
* sizeof(TransactionId
));
1148 s
->parent
->nChildXids
= new_nChildXids
;
1150 /* Release child's array to avoid leakage */
1151 if (s
->childXids
!= NULL
)
1152 pfree(s
->childXids
);
1153 /* We must reset these to avoid double-free if fail later in commit */
1154 s
->childXids
= NULL
;
1156 s
->maxChildXids
= 0;
1160 * RecordSubTransactionCommit
1163 RecordSubTransactionCommit(void)
1165 TransactionId xid
= GetCurrentTransactionIdIfAny();
1168 * We do not log the subcommit in XLOG; it doesn't matter until the
1169 * top-level transaction commits.
1171 * We must mark the subtransaction subcommitted in the CLOG if it had a
1172 * valid XID assigned. If it did not, nobody else will ever know about
1173 * the existence of this subxact. We don't have to deal with deletions
1174 * scheduled for on-commit here, since they'll be reassigned to our parent
1175 * (who might still abort).
1177 if (TransactionIdIsValid(xid
))
1179 /* XXX does this really need to be a critical section? */
1180 START_CRIT_SECTION();
1182 /* Record subtransaction subcommit */
1183 TransactionIdSubCommit(xid
);
1189 /* ----------------------------------------------------------------
1190 * AbortTransaction stuff
1191 * ----------------------------------------------------------------
1195 * RecordTransactionAbort
1197 * Returns latest XID among xact and its children, or InvalidTransactionId
1198 * if the xact has no XID. (We compute that here just because it's easier.)
1200 static TransactionId
1201 RecordTransactionAbort(bool isSubXact
)
1203 TransactionId xid
= GetCurrentTransactionIdIfAny();
1204 TransactionId latestXid
;
1208 TransactionId
*children
;
1209 XLogRecData rdata
[3];
1211 xl_xact_abort xlrec
;
1214 * If we haven't been assigned an XID, nobody will care whether we aborted
1215 * or not. Hence, we're done in that case. It does not matter if we have
1216 * rels to delete (note that this routine is not responsible for actually
1217 * deleting 'em). We cannot have any child XIDs, either.
1219 if (!TransactionIdIsValid(xid
))
1221 /* Reset XactLastRecEnd until the next transaction writes something */
1223 XactLastRecEnd
.xrecoff
= 0;
1224 return InvalidTransactionId
;
1228 * We have a valid XID, so we should write an ABORT record for it.
1230 * We do not flush XLOG to disk here, since the default assumption after a
1231 * crash would be that we aborted, anyway. For the same reason, we don't
1232 * need to worry about interlocking against checkpoint start.
1236 * Check that we haven't aborted halfway through RecordTransactionCommit.
1238 if (TransactionIdDidCommit(xid
))
1239 elog(PANIC
, "cannot abort transaction %u, it was already committed",
1242 /* Fetch the data we need for the abort record */
1243 nrels
= smgrGetPendingDeletes(false, &rels
, NULL
);
1244 nchildren
= xactGetCommittedChildren(&children
);
1246 /* XXX do we really need a critical section here? */
1247 START_CRIT_SECTION();
1249 /* Write the ABORT record */
1251 xlrec
.xact_time
= GetCurrentTimestamp();
1254 SetCurrentTransactionStopTimestamp();
1255 xlrec
.xact_time
= xactStopTimestamp
;
1257 xlrec
.nrels
= nrels
;
1258 xlrec
.nsubxacts
= nchildren
;
1259 rdata
[0].data
= (char *) (&xlrec
);
1260 rdata
[0].len
= MinSizeOfXactAbort
;
1261 rdata
[0].buffer
= InvalidBuffer
;
1262 /* dump rels to delete */
1265 rdata
[0].next
= &(rdata
[1]);
1266 rdata
[1].data
= (char *) rels
;
1267 rdata
[1].len
= nrels
* sizeof(RelFileFork
);
1268 rdata
[1].buffer
= InvalidBuffer
;
1271 /* dump committed child Xids */
1274 rdata
[lastrdata
].next
= &(rdata
[2]);
1275 rdata
[2].data
= (char *) children
;
1276 rdata
[2].len
= nchildren
* sizeof(TransactionId
);
1277 rdata
[2].buffer
= InvalidBuffer
;
1280 rdata
[lastrdata
].next
= NULL
;
1282 (void) XLogInsert(RM_XACT_ID
, XLOG_XACT_ABORT
, rdata
);
1285 * Mark the transaction aborted in clog. This is not absolutely necessary
1286 * but we may as well do it while we are here; also, in the subxact case
1287 * it is helpful because XactLockTableWait makes use of it to avoid
1288 * waiting for already-aborted subtransactions. It is OK to do it without
1289 * having flushed the ABORT record to disk, because in event of a crash
1290 * we'd be assumed to have aborted anyway.
1292 * The ordering here isn't critical but it seems best to mark the parent
1293 * first. This assures an atomic transition of all the subtransactions to
1294 * aborted state from the point of view of concurrent
1295 * TransactionIdDidAbort calls.
1297 TransactionIdAbort(xid
);
1298 TransactionIdAbortTree(nchildren
, children
);
1302 /* Compute latestXid while we have the child XIDs handy */
1303 latestXid
= TransactionIdLatest(xid
, nchildren
, children
);
1306 * If we're aborting a subtransaction, we can immediately remove failed
1307 * XIDs from PGPROC's cache of running child XIDs. We do that here for
1308 * subxacts, because we already have the child XID array at hand. For
1309 * main xacts, the equivalent happens just after this function returns.
1312 XidCacheRemoveRunningXids(xid
, nchildren
, children
, latestXid
);
1314 /* Reset XactLastRecEnd until the next transaction writes something */
1316 XactLastRecEnd
.xrecoff
= 0;
1318 /* And clean up local data */
1329 AtAbort_Memory(void)
1332 * Switch into TransactionAbortContext, which should have some free space
1333 * even if nothing else does. We'll work in this context until we've
1334 * finished cleaning up.
1336 * It is barely possible to get here when we've not been able to create
1337 * TransactionAbortContext yet; if so use TopMemoryContext.
1339 if (TransactionAbortContext
!= NULL
)
1340 MemoryContextSwitchTo(TransactionAbortContext
);
1342 MemoryContextSwitchTo(TopMemoryContext
);
1349 AtSubAbort_Memory(void)
1351 Assert(TransactionAbortContext
!= NULL
);
1353 MemoryContextSwitchTo(TransactionAbortContext
);
1358 * AtAbort_ResourceOwner
1361 AtAbort_ResourceOwner(void)
1364 * Make sure we have a valid ResourceOwner, if possible (else it will be
1365 * NULL, which is OK)
1367 CurrentResourceOwner
= TopTransactionResourceOwner
;
1371 * AtSubAbort_ResourceOwner
1374 AtSubAbort_ResourceOwner(void)
1376 TransactionState s
= CurrentTransactionState
;
1378 /* Make sure we have a valid ResourceOwner */
1379 CurrentResourceOwner
= s
->curTransactionOwner
;
1384 * AtSubAbort_childXids
1387 AtSubAbort_childXids(void)
1389 TransactionState s
= CurrentTransactionState
;
1392 * We keep the child-XID arrays in TopTransactionContext (see
1393 * AtSubCommit_childXids). This means we'd better free the array
1394 * explicitly at abort to avoid leakage.
1396 if (s
->childXids
!= NULL
)
1397 pfree(s
->childXids
);
1398 s
->childXids
= NULL
;
1400 s
->maxChildXids
= 0;
1403 /* ----------------------------------------------------------------
1404 * CleanupTransaction stuff
1405 * ----------------------------------------------------------------
1412 AtCleanup_Memory(void)
1414 Assert(CurrentTransactionState
->parent
== NULL
);
1417 * Now that we're "out" of a transaction, have the system allocate things
1418 * in the top memory context instead of per-transaction contexts.
1420 MemoryContextSwitchTo(TopMemoryContext
);
1423 * Clear the special abort context for next time.
1425 if (TransactionAbortContext
!= NULL
)
1426 MemoryContextResetAndDeleteChildren(TransactionAbortContext
);
1429 * Release all transaction-local memory.
1431 if (TopTransactionContext
!= NULL
)
1432 MemoryContextDelete(TopTransactionContext
);
1433 TopTransactionContext
= NULL
;
1434 CurTransactionContext
= NULL
;
1435 CurrentTransactionState
->curTransactionContext
= NULL
;
1439 /* ----------------------------------------------------------------
1440 * CleanupSubTransaction stuff
1441 * ----------------------------------------------------------------
1445 * AtSubCleanup_Memory
1448 AtSubCleanup_Memory(void)
1450 TransactionState s
= CurrentTransactionState
;
1452 Assert(s
->parent
!= NULL
);
1454 /* Make sure we're not in an about-to-be-deleted context */
1455 MemoryContextSwitchTo(s
->parent
->curTransactionContext
);
1456 CurTransactionContext
= s
->parent
->curTransactionContext
;
1459 * Clear the special abort context for next time.
1461 if (TransactionAbortContext
!= NULL
)
1462 MemoryContextResetAndDeleteChildren(TransactionAbortContext
);
1465 * Delete the subxact local memory contexts. Its CurTransactionContext can
1466 * go too (note this also kills CurTransactionContexts from any children
1469 if (s
->curTransactionContext
)
1470 MemoryContextDelete(s
->curTransactionContext
);
1471 s
->curTransactionContext
= NULL
;
1474 /* ----------------------------------------------------------------
1475 * interface routines
1476 * ----------------------------------------------------------------
1483 StartTransaction(void)
1486 VirtualTransactionId vxid
;
1489 * Let's just make sure the state stack is empty
1491 s
= &TopTransactionStateData
;
1492 CurrentTransactionState
= s
;
1495 * check the current transaction state
1497 if (s
->state
!= TRANS_DEFAULT
)
1498 elog(WARNING
, "StartTransaction while in %s state",
1499 TransStateAsString(s
->state
));
1502 * set the current transaction state information appropriately during
1505 s
->state
= TRANS_START
;
1506 s
->transactionId
= InvalidTransactionId
; /* until assigned */
1509 * Make sure we've reset xact state variables
1511 XactIsoLevel
= DefaultXactIsoLevel
;
1512 XactReadOnly
= DefaultXactReadOnly
;
1513 forceSyncCommit
= false;
1514 MyXactAccessedTempRel
= false;
1517 * reinitialize within-transaction counters
1519 s
->subTransactionId
= TopSubTransactionId
;
1520 currentSubTransactionId
= TopSubTransactionId
;
1521 currentCommandId
= FirstCommandId
;
1522 currentCommandIdUsed
= false;
1525 * must initialize resource-management stuff first
1528 AtStart_ResourceOwner();
1531 * Assign a new LocalTransactionId, and combine it with the backendId to
1532 * form a virtual transaction id.
1534 vxid
.backendId
= MyBackendId
;
1535 vxid
.localTransactionId
= GetNextLocalTransactionId();
1538 * Lock the virtual transaction id before we announce it in the proc array
1540 VirtualXactLockTableInsert(vxid
);
1543 * Advertise it in the proc array. We assume assignment of
1544 * LocalTransactionID is atomic, and the backendId should be set already.
1546 Assert(MyProc
->backendId
== vxid
.backendId
);
1547 MyProc
->lxid
= vxid
.localTransactionId
;
1549 TRACE_POSTGRESQL_TRANSACTION_START(vxid
.localTransactionId
);
1552 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1553 * as the first command's statement_timestamp(), so don't do a fresh
1554 * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1555 * xactStopTimestamp as unset.
1557 xactStartTimestamp
= stmtStartTimestamp
;
1558 xactStopTimestamp
= 0;
1559 pgstat_report_xact_timestamp(xactStartTimestamp
);
1562 * initialize current transaction state fields
1564 * note: prevXactReadOnly is not used at the outermost level
1566 s
->nestingLevel
= 1;
1567 s
->gucNestLevel
= 1;
1568 s
->childXids
= NULL
;
1570 s
->maxChildXids
= 0;
1571 GetUserIdAndContext(&s
->prevUser
, &s
->prevSecDefCxt
);
1572 /* SecurityDefinerContext should never be set outside a transaction */
1573 Assert(!s
->prevSecDefCxt
);
1576 * initialize other subsystems for new transaction
1581 AfterTriggerBeginXact();
1584 * done with start processing, set current transaction state to "in
1587 s
->state
= TRANS_INPROGRESS
;
1589 ShowTransactionState("StartTransaction");
1596 * NB: if you change this routine, better look at PrepareTransaction too!
1599 CommitTransaction(void)
1601 TransactionState s
= CurrentTransactionState
;
1602 TransactionId latestXid
;
1604 ShowTransactionState("CommitTransaction");
1607 * check the current transaction state
1609 if (s
->state
!= TRANS_INPROGRESS
)
1610 elog(WARNING
, "CommitTransaction while in %s state",
1611 TransStateAsString(s
->state
));
1612 Assert(s
->parent
== NULL
);
1615 * Do pre-commit processing (most of this stuff requires database access,
1616 * and in fact could still cause an error...)
1618 * It is possible for CommitHoldablePortals to invoke functions that queue
1619 * deferred triggers, and it's also possible that triggers create holdable
1620 * cursors. So we have to loop until there's nothing left to do.
1625 * Fire all currently pending deferred triggers.
1627 AfterTriggerFireDeferred();
1630 * Convert any open holdable cursors into static portals. If there
1631 * weren't any, we are done ... otherwise loop back to check if they
1632 * queued deferred triggers. Lather, rinse, repeat.
1634 if (!CommitHoldablePortals())
1638 /* Now we can shut down the deferred-trigger manager */
1639 AfterTriggerEndXact(true);
1641 /* Close any open regular cursors */
1645 * Let ON COMMIT management do its thing (must happen after closing
1646 * cursors, to avoid dangling-reference problems)
1648 PreCommit_on_commit_actions();
1650 /* close large objects before lower-level cleanup */
1651 AtEOXact_LargeObject(true);
1653 /* NOTIFY commit must come before lower-level cleanup */
1657 * Update flat files if we changed pg_database, pg_authid or
1658 * pg_auth_members. This should be the last step before commit.
1660 AtEOXact_UpdateFlatFiles(true);
1662 /* Prevent cancel/die interrupt while cleaning up */
1666 * set the current transaction state information appropriately during
1669 s
->state
= TRANS_COMMIT
;
1672 * Here is where we really truly commit.
1674 latestXid
= RecordTransactionCommit();
1676 TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc
->lxid
);
1679 * Let others know about no transaction in progress by me. Note that this
1680 * must be done _before_ releasing locks we hold and _after_
1681 * RecordTransactionCommit.
1683 ProcArrayEndTransaction(MyProc
, latestXid
);
1686 * This is all post-commit cleanup. Note that if an error is raised here,
1687 * it's too late to abort the transaction. This should be just
1688 * noncritical resource releasing.
1690 * The ordering of operations is not entirely random. The idea is:
1691 * release resources visible to other backends (eg, files, buffer pins);
1692 * then release locks; then release backend-local resources. We want to
1693 * release locks at the point where any backend waiting for us will see
1694 * our transaction as being fully cleaned up.
1696 * Resources that can be associated with individual queries are handled by
1697 * the ResourceOwner mechanism. The other calls here are for backend-wide
1701 CallXactCallbacks(XACT_EVENT_COMMIT
);
1703 ResourceOwnerRelease(TopTransactionResourceOwner
,
1704 RESOURCE_RELEASE_BEFORE_LOCKS
,
1707 /* Check we've released all buffer pins */
1708 AtEOXact_Buffers(true);
1710 /* Clean up the relation cache */
1711 AtEOXact_RelationCache(true);
1714 * Make catalog changes visible to all backends. This has to happen after
1715 * relcache references are dropped (see comments for
1716 * AtEOXact_RelationCache), but before locks are released (if anyone is
1717 * waiting for lock on a relation we've modified, we want them to know
1718 * about the catalog change before they start using the relation).
1720 AtEOXact_Inval(true);
1723 * Likewise, dropping of files deleted during the transaction is best done
1724 * after releasing relcache and buffer pins. (This is not strictly
1725 * necessary during commit, since such pins should have been released
1726 * already, but this ordering is definitely critical during abort.)
1728 smgrDoPendingDeletes(true);
1730 AtEOXact_MultiXact();
1732 ResourceOwnerRelease(TopTransactionResourceOwner
,
1733 RESOURCE_RELEASE_LOCKS
,
1735 ResourceOwnerRelease(TopTransactionResourceOwner
,
1736 RESOURCE_RELEASE_AFTER_LOCKS
,
1739 /* Check we've released all catcache entries */
1740 AtEOXact_CatCache(true);
1742 AtEOXact_GUC(true, 1);
1745 AtEOXact_on_commit_actions(true);
1746 AtEOXact_Namespace(true);
1747 /* smgrcommit already done */
1749 AtEOXact_ComboCid();
1750 AtEOXact_HashTables(true);
1751 AtEOXact_PgStat(true);
1752 AtEOXact_Snapshot(true);
1753 pgstat_report_xact_timestamp(0);
1755 CurrentResourceOwner
= NULL
;
1756 ResourceOwnerDelete(TopTransactionResourceOwner
);
1757 s
->curTransactionOwner
= NULL
;
1758 CurTransactionResourceOwner
= NULL
;
1759 TopTransactionResourceOwner
= NULL
;
1763 s
->transactionId
= InvalidTransactionId
;
1764 s
->subTransactionId
= InvalidSubTransactionId
;
1765 s
->nestingLevel
= 0;
1766 s
->gucNestLevel
= 0;
1767 s
->childXids
= NULL
;
1769 s
->maxChildXids
= 0;
1772 * done with commit processing, set current transaction state back to
1775 s
->state
= TRANS_DEFAULT
;
1777 RESUME_INTERRUPTS();
1782 * PrepareTransaction
1784 * NB: if you change this routine, better look at CommitTransaction too!
1787 PrepareTransaction(void)
1789 TransactionState s
= CurrentTransactionState
;
1790 TransactionId xid
= GetCurrentTransactionId();
1791 GlobalTransaction gxact
;
1792 TimestampTz prepared_at
;
1794 ShowTransactionState("PrepareTransaction");
1797 * check the current transaction state
1799 if (s
->state
!= TRANS_INPROGRESS
)
1800 elog(WARNING
, "PrepareTransaction while in %s state",
1801 TransStateAsString(s
->state
));
1802 Assert(s
->parent
== NULL
);
1805 * Do pre-commit processing (most of this stuff requires database access,
1806 * and in fact could still cause an error...)
1808 * It is possible for PrepareHoldablePortals to invoke functions that
1809 * queue deferred triggers, and it's also possible that triggers create
1810 * holdable cursors. So we have to loop until there's nothing left to do.
1815 * Fire all currently pending deferred triggers.
1817 AfterTriggerFireDeferred();
1820 * Convert any open holdable cursors into static portals. If there
1821 * weren't any, we are done ... otherwise loop back to check if they
1822 * queued deferred triggers. Lather, rinse, repeat.
1824 if (!PrepareHoldablePortals())
1828 /* Now we can shut down the deferred-trigger manager */
1829 AfterTriggerEndXact(true);
1831 /* Close any open regular cursors */
1835 * Let ON COMMIT management do its thing (must happen after closing
1836 * cursors, to avoid dangling-reference problems)
1838 PreCommit_on_commit_actions();
1840 /* close large objects before lower-level cleanup */
1841 AtEOXact_LargeObject(true);
1843 /* NOTIFY and flatfiles will be handled below */
1846 * Don't allow PREPARE TRANSACTION if we've accessed a temporary table
1847 * in this transaction. Having the prepared xact hold locks on another
1848 * backend's temp table seems a bad idea --- for instance it would prevent
1849 * the backend from exiting. There are other problems too, such as how
1850 * to clean up the source backend's local buffers and ON COMMIT state
1851 * if the prepared xact includes a DROP of a temp table.
1853 * We must check this after executing any ON COMMIT actions, because
1854 * they might still access a temp relation.
1856 * XXX In principle this could be relaxed to allow some useful special
1857 * cases, such as a temp table created and dropped all within the
1858 * transaction. That seems to require much more bookkeeping though.
1860 if (MyXactAccessedTempRel
)
1862 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1863 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1865 /* Prevent cancel/die interrupt while cleaning up */
1869 * set the current transaction state information appropriately during
1870 * prepare processing
1872 s
->state
= TRANS_PREPARE
;
1874 prepared_at
= GetCurrentTimestamp();
1876 /* Tell bufmgr and smgr to prepare for commit */
1880 * Reserve the GID for this transaction. This could fail if the requested
1881 * GID is invalid or already in use.
1883 gxact
= MarkAsPreparing(xid
, prepareGID
, prepared_at
,
1884 GetUserId(), MyDatabaseId
);
1888 * Collect data for the 2PC state file. Note that in general, no actual
1889 * state change should happen in the called modules during this step,
1890 * since it's still possible to fail before commit, and in that case we
1891 * want transaction abort to be able to clean up. (In particular, the
1892 * AtPrepare routines may error out if they find cases they cannot
1893 * handle.) State cleanup should happen in the PostPrepare routines
1894 * below. However, some modules can go ahead and clear state here because
1895 * they wouldn't do anything with it during abort anyway.
1897 * Note: because the 2PC state file records will be replayed in the same
1898 * order they are made, the order of these calls has to match the order in
1899 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1900 * PREPARED; in particular, pay attention to whether things should happen
1901 * before or after releasing the transaction's locks.
1903 StartPrepare(gxact
);
1906 AtPrepare_UpdateFlatFiles();
1912 * Here is where we really truly prepare.
1914 * We have to record transaction prepares even if we didn't make any
1915 * updates, because the transaction manager might get confused if we lose
1916 * a global transaction.
1921 * Now we clean up backend-internal state and release internal resources.
1924 /* Reset XactLastRecEnd until the next transaction writes something */
1925 XactLastRecEnd
.xrecoff
= 0;
1928 * Let others know about no transaction in progress by me. This has to be
1929 * done *after* the prepared transaction has been marked valid, else
1930 * someone may think it is unlocked and recyclable.
1932 ProcArrayClearTransaction(MyProc
);
1935 * This is all post-transaction cleanup. Note that if an error is raised
1936 * here, it's too late to abort the transaction. This should be just
1937 * noncritical resource releasing. See notes in CommitTransaction.
1940 CallXactCallbacks(XACT_EVENT_PREPARE
);
1942 ResourceOwnerRelease(TopTransactionResourceOwner
,
1943 RESOURCE_RELEASE_BEFORE_LOCKS
,
1946 /* Check we've released all buffer pins */
1947 AtEOXact_Buffers(true);
1949 /* Clean up the relation cache */
1950 AtEOXact_RelationCache(true);
1952 /* notify and flatfiles don't need a postprepare call */
1954 PostPrepare_PgStat();
1956 PostPrepare_Inval();
1960 AtEOXact_MultiXact();
1962 PostPrepare_Locks(xid
);
1964 ResourceOwnerRelease(TopTransactionResourceOwner
,
1965 RESOURCE_RELEASE_LOCKS
,
1967 ResourceOwnerRelease(TopTransactionResourceOwner
,
1968 RESOURCE_RELEASE_AFTER_LOCKS
,
1971 /* Check we've released all catcache entries */
1972 AtEOXact_CatCache(true);
1974 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1975 AtEOXact_GUC(true, 1);
1978 AtEOXact_on_commit_actions(true);
1979 AtEOXact_Namespace(true);
1980 /* smgrcommit already done */
1982 AtEOXact_ComboCid();
1983 AtEOXact_HashTables(true);
1984 /* don't call AtEOXact_PgStat here */
1985 AtEOXact_Snapshot(true);
1987 CurrentResourceOwner
= NULL
;
1988 ResourceOwnerDelete(TopTransactionResourceOwner
);
1989 s
->curTransactionOwner
= NULL
;
1990 CurTransactionResourceOwner
= NULL
;
1991 TopTransactionResourceOwner
= NULL
;
1995 s
->transactionId
= InvalidTransactionId
;
1996 s
->subTransactionId
= InvalidSubTransactionId
;
1997 s
->nestingLevel
= 0;
1998 s
->gucNestLevel
= 0;
1999 s
->childXids
= NULL
;
2001 s
->maxChildXids
= 0;
2004 * done with 1st phase commit processing, set current transaction state
2007 s
->state
= TRANS_DEFAULT
;
2009 RESUME_INTERRUPTS();
2017 AbortTransaction(void)
2019 TransactionState s
= CurrentTransactionState
;
2020 TransactionId latestXid
;
2022 /* Prevent cancel/die interrupt while cleaning up */
2025 /* Make sure we have a valid memory context and resource owner */
2027 AtAbort_ResourceOwner();
2030 * Release any LW locks we might be holding as quickly as possible.
2031 * (Regular locks, however, must be held till we finish aborting.)
2032 * Releasing LW locks is critical since we might try to grab them again
2033 * while cleaning up!
2037 /* Clean up buffer I/O and buffer context locks, too */
2042 * Also clean up any open wait for lock, since the lock manager will choke
2043 * if we try to wait for another lock before doing this.
2048 * check the current transaction state
2050 if (s
->state
!= TRANS_INPROGRESS
&& s
->state
!= TRANS_PREPARE
)
2051 elog(WARNING
, "AbortTransaction while in %s state",
2052 TransStateAsString(s
->state
));
2053 Assert(s
->parent
== NULL
);
2056 * set the current transaction state information appropriately during the
2059 s
->state
= TRANS_ABORT
;
2062 * Reset user ID which might have been changed transiently. We need this
2063 * to clean up in case control escaped out of a SECURITY DEFINER function
2064 * or other local change of CurrentUserId; therefore, the prior value
2065 * of SecurityDefinerContext also needs to be restored.
2067 * (Note: it is not necessary to restore session authorization or role
2068 * settings here because those can only be changed via GUC, and GUC will
2069 * take care of rolling them back if need be.)
2071 SetUserIdAndContext(s
->prevUser
, s
->prevSecDefCxt
);
2074 * do abort processing
2076 AfterTriggerEndXact(false);
2078 AtEOXact_LargeObject(false); /* 'false' means it's abort */
2080 AtEOXact_UpdateFlatFiles(false);
2083 * Advertise the fact that we aborted in pg_clog (assuming that we got as
2084 * far as assigning an XID to advertise).
2086 latestXid
= RecordTransactionAbort(false);
2088 TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc
->lxid
);
2091 * Let others know about no transaction in progress by me. Note that this
2092 * must be done _before_ releasing locks we hold and _after_
2093 * RecordTransactionAbort.
2095 ProcArrayEndTransaction(MyProc
, latestXid
);
2098 * Post-abort cleanup. See notes in CommitTransaction() concerning
2102 CallXactCallbacks(XACT_EVENT_ABORT
);
2104 ResourceOwnerRelease(TopTransactionResourceOwner
,
2105 RESOURCE_RELEASE_BEFORE_LOCKS
,
2107 AtEOXact_Buffers(false);
2108 AtEOXact_RelationCache(false);
2109 AtEOXact_Inval(false);
2110 smgrDoPendingDeletes(false);
2111 AtEOXact_MultiXact();
2112 ResourceOwnerRelease(TopTransactionResourceOwner
,
2113 RESOURCE_RELEASE_LOCKS
,
2115 ResourceOwnerRelease(TopTransactionResourceOwner
,
2116 RESOURCE_RELEASE_AFTER_LOCKS
,
2118 AtEOXact_CatCache(false);
2120 AtEOXact_GUC(false, 1);
2121 AtEOXact_SPI(false);
2123 AtEOXact_on_commit_actions(false);
2124 AtEOXact_Namespace(false);
2127 AtEOXact_ComboCid();
2128 AtEOXact_HashTables(false);
2129 AtEOXact_PgStat(false);
2130 AtEOXact_Snapshot(false);
2131 pgstat_report_xact_timestamp(0);
2134 * State remains TRANS_ABORT until CleanupTransaction().
2136 RESUME_INTERRUPTS();
2140 * CleanupTransaction
2143 CleanupTransaction(void)
2145 TransactionState s
= CurrentTransactionState
;
2148 * State should still be TRANS_ABORT from AbortTransaction().
2150 if (s
->state
!= TRANS_ABORT
)
2151 elog(FATAL
, "CleanupTransaction: unexpected state %s",
2152 TransStateAsString(s
->state
));
2155 * do abort cleanup processing
2157 AtCleanup_Portals(); /* now safe to release portal memory */
2159 CurrentResourceOwner
= NULL
; /* and resource owner */
2160 if (TopTransactionResourceOwner
)
2161 ResourceOwnerDelete(TopTransactionResourceOwner
);
2162 s
->curTransactionOwner
= NULL
;
2163 CurTransactionResourceOwner
= NULL
;
2164 TopTransactionResourceOwner
= NULL
;
2166 AtCleanup_Memory(); /* and transaction memory */
2168 s
->transactionId
= InvalidTransactionId
;
2169 s
->subTransactionId
= InvalidSubTransactionId
;
2170 s
->nestingLevel
= 0;
2171 s
->gucNestLevel
= 0;
2172 s
->childXids
= NULL
;
2174 s
->maxChildXids
= 0;
2177 * done with abort processing, set current transaction state back to
2180 s
->state
= TRANS_DEFAULT
;
2184 * StartTransactionCommand
2187 StartTransactionCommand(void)
2189 TransactionState s
= CurrentTransactionState
;
2191 switch (s
->blockState
)
2194 * if we aren't in a transaction block, we just do our usual start
2197 case TBLOCK_DEFAULT
:
2199 s
->blockState
= TBLOCK_STARTED
;
2203 * We are somewhere in a transaction block or subtransaction and
2204 * about to start a new command. For now we do nothing, but
2205 * someday we may do command-local resource initialization. (Note
2206 * that any needed CommandCounterIncrement was done by the
2207 * previous CommitTransactionCommand.)
2209 case TBLOCK_INPROGRESS
:
2210 case TBLOCK_SUBINPROGRESS
:
2214 * Here we are in a failed transaction block (one of the commands
2215 * caused an abort) so we do nothing but remain in the abort
2216 * state. Eventually we will get a ROLLBACK command which will
2217 * get us out of this state. (It is up to other code to ensure
2218 * that no commands other than ROLLBACK will be processed in these
2222 case TBLOCK_SUBABORT
:
2225 /* These cases are invalid. */
2226 case TBLOCK_STARTED
:
2228 case TBLOCK_SUBBEGIN
:
2231 case TBLOCK_ABORT_END
:
2232 case TBLOCK_SUBABORT_END
:
2233 case TBLOCK_ABORT_PENDING
:
2234 case TBLOCK_SUBABORT_PENDING
:
2235 case TBLOCK_SUBRESTART
:
2236 case TBLOCK_SUBABORT_RESTART
:
2237 case TBLOCK_PREPARE
:
2238 elog(ERROR
, "StartTransactionCommand: unexpected state %s",
2239 BlockStateAsString(s
->blockState
));
2244 * We must switch to CurTransactionContext before returning. This is
2245 * already done if we called StartTransaction, otherwise not.
2247 Assert(CurTransactionContext
!= NULL
);
2248 MemoryContextSwitchTo(CurTransactionContext
);
2252 * CommitTransactionCommand
2255 CommitTransactionCommand(void)
2257 TransactionState s
= CurrentTransactionState
;
2259 switch (s
->blockState
)
2262 * This shouldn't happen, because it means the previous
2263 * StartTransactionCommand didn't set the STARTED state
2266 case TBLOCK_DEFAULT
:
2267 elog(FATAL
, "CommitTransactionCommand: unexpected state %s",
2268 BlockStateAsString(s
->blockState
));
2272 * If we aren't in a transaction block, just do our usual
2273 * transaction commit, and return to the idle state.
2275 case TBLOCK_STARTED
:
2276 CommitTransaction();
2277 s
->blockState
= TBLOCK_DEFAULT
;
2281 * We are completing a "BEGIN TRANSACTION" command, so we change
2282 * to the "transaction block in progress" state and return. (We
2283 * assume the BEGIN did nothing to the database, so we need no
2284 * CommandCounterIncrement.)
2287 s
->blockState
= TBLOCK_INPROGRESS
;
2291 * This is the case when we have finished executing a command
2292 * someplace within a transaction block. We increment the command
2293 * counter and return.
2295 case TBLOCK_INPROGRESS
:
2296 case TBLOCK_SUBINPROGRESS
:
2297 CommandCounterIncrement();
2301 * We are completing a "COMMIT" command. Do it and return to the
2305 CommitTransaction();
2306 s
->blockState
= TBLOCK_DEFAULT
;
2310 * Here we are in the middle of a transaction block but one of the
2311 * commands caused an abort so we do nothing but remain in the
2312 * abort state. Eventually we will get a ROLLBACK comand.
2315 case TBLOCK_SUBABORT
:
2319 * Here we were in an aborted transaction block and we just got
2320 * the ROLLBACK command from the user, so clean up the
2321 * already-aborted transaction and return to the idle state.
2323 case TBLOCK_ABORT_END
:
2324 CleanupTransaction();
2325 s
->blockState
= TBLOCK_DEFAULT
;
2329 * Here we were in a perfectly good transaction block but the user
2330 * told us to ROLLBACK anyway. We have to abort the transaction
2331 * and then clean up.
2333 case TBLOCK_ABORT_PENDING
:
2335 CleanupTransaction();
2336 s
->blockState
= TBLOCK_DEFAULT
;
2340 * We are completing a "PREPARE TRANSACTION" command. Do it and
2341 * return to the idle state.
2343 case TBLOCK_PREPARE
:
2344 PrepareTransaction();
2345 s
->blockState
= TBLOCK_DEFAULT
;
2349 * We were just issued a SAVEPOINT inside a transaction block.
2350 * Start a subtransaction. (DefineSavepoint already did
2351 * PushTransaction, so as to have someplace to put the SUBBEGIN
2354 case TBLOCK_SUBBEGIN
:
2355 StartSubTransaction();
2356 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2360 * We were issued a COMMIT or RELEASE command, so we end the
2361 * current subtransaction and return to the parent transaction.
2362 * The parent might be ended too, so repeat till we are all the
2363 * way out or find an INPROGRESS transaction.
2368 CommitSubTransaction();
2369 s
= CurrentTransactionState
; /* changed by pop */
2370 } while (s
->blockState
== TBLOCK_SUBEND
);
2371 /* If we had a COMMIT command, finish off the main xact too */
2372 if (s
->blockState
== TBLOCK_END
)
2374 Assert(s
->parent
== NULL
);
2375 CommitTransaction();
2376 s
->blockState
= TBLOCK_DEFAULT
;
2378 else if (s
->blockState
== TBLOCK_PREPARE
)
2380 Assert(s
->parent
== NULL
);
2381 PrepareTransaction();
2382 s
->blockState
= TBLOCK_DEFAULT
;
2386 Assert(s
->blockState
== TBLOCK_INPROGRESS
||
2387 s
->blockState
== TBLOCK_SUBINPROGRESS
);
2392 * The current already-failed subtransaction is ending due to a
2393 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2394 * examine the parent (which could be in any of several states).
2396 case TBLOCK_SUBABORT_END
:
2397 CleanupSubTransaction();
2398 CommitTransactionCommand();
2402 * As above, but it's not dead yet, so abort first.
2404 case TBLOCK_SUBABORT_PENDING
:
2405 AbortSubTransaction();
2406 CleanupSubTransaction();
2407 CommitTransactionCommand();
2411 * The current subtransaction is the target of a ROLLBACK TO
2412 * command. Abort and pop it, then start a new subtransaction
2413 * with the same name.
2415 case TBLOCK_SUBRESTART
:
2420 /* save name and keep Cleanup from freeing it */
2423 savepointLevel
= s
->savepointLevel
;
2425 AbortSubTransaction();
2426 CleanupSubTransaction();
2428 DefineSavepoint(NULL
);
2429 s
= CurrentTransactionState
; /* changed by push */
2431 s
->savepointLevel
= savepointLevel
;
2433 /* This is the same as TBLOCK_SUBBEGIN case */
2434 AssertState(s
->blockState
== TBLOCK_SUBBEGIN
);
2435 StartSubTransaction();
2436 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2441 * Same as above, but the subtransaction had already failed, so we
2442 * don't need AbortSubTransaction.
2444 case TBLOCK_SUBABORT_RESTART
:
2449 /* save name and keep Cleanup from freeing it */
2452 savepointLevel
= s
->savepointLevel
;
2454 CleanupSubTransaction();
2456 DefineSavepoint(NULL
);
2457 s
= CurrentTransactionState
; /* changed by push */
2459 s
->savepointLevel
= savepointLevel
;
2461 /* This is the same as TBLOCK_SUBBEGIN case */
2462 AssertState(s
->blockState
== TBLOCK_SUBBEGIN
);
2463 StartSubTransaction();
2464 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2471 * AbortCurrentTransaction
2474 AbortCurrentTransaction(void)
2476 TransactionState s
= CurrentTransactionState
;
2478 switch (s
->blockState
)
2480 case TBLOCK_DEFAULT
:
2481 if (s
->state
== TRANS_DEFAULT
)
2483 /* we are idle, so nothing to do */
2488 * We can get here after an error during transaction start
2489 * (state will be TRANS_START). Need to clean up the
2490 * incompletely started transaction. First, adjust the
2491 * low-level state to suppress warning message from
2494 if (s
->state
== TRANS_START
)
2495 s
->state
= TRANS_INPROGRESS
;
2497 CleanupTransaction();
2502 * if we aren't in a transaction block, we just do the basic abort
2503 * & cleanup transaction.
2505 case TBLOCK_STARTED
:
2507 CleanupTransaction();
2508 s
->blockState
= TBLOCK_DEFAULT
;
2512 * If we are in TBLOCK_BEGIN it means something screwed up right
2513 * after reading "BEGIN TRANSACTION". We assume that the user
2514 * will interpret the error as meaning the BEGIN failed to get him
2515 * into a transaction block, so we should abort and return to idle
2520 CleanupTransaction();
2521 s
->blockState
= TBLOCK_DEFAULT
;
2525 * We are somewhere in a transaction block and we've gotten a
2526 * failure, so we abort the transaction and set up the persistent
2527 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2529 case TBLOCK_INPROGRESS
:
2531 s
->blockState
= TBLOCK_ABORT
;
2532 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2536 * Here, we failed while trying to COMMIT. Clean up the
2537 * transaction and return to idle state (we do not want to stay in
2542 CleanupTransaction();
2543 s
->blockState
= TBLOCK_DEFAULT
;
2547 * Here, we are already in an aborted transaction state and are
2548 * waiting for a ROLLBACK, but for some reason we failed again! So
2549 * we just remain in the abort state.
2552 case TBLOCK_SUBABORT
:
2556 * We are in a failed transaction and we got the ROLLBACK command.
2557 * We have already aborted, we just need to cleanup and go to idle
2560 case TBLOCK_ABORT_END
:
2561 CleanupTransaction();
2562 s
->blockState
= TBLOCK_DEFAULT
;
2566 * We are in a live transaction and we got a ROLLBACK command.
2567 * Abort, cleanup, go to idle state.
2569 case TBLOCK_ABORT_PENDING
:
2571 CleanupTransaction();
2572 s
->blockState
= TBLOCK_DEFAULT
;
2576 * Here, we failed while trying to PREPARE. Clean up the
2577 * transaction and return to idle state (we do not want to stay in
2580 case TBLOCK_PREPARE
:
2582 CleanupTransaction();
2583 s
->blockState
= TBLOCK_DEFAULT
;
2587 * We got an error inside a subtransaction. Abort just the
2588 * subtransaction, and go to the persistent SUBABORT state until
2591 case TBLOCK_SUBINPROGRESS
:
2592 AbortSubTransaction();
2593 s
->blockState
= TBLOCK_SUBABORT
;
2597 * If we failed while trying to create a subtransaction, clean up
2598 * the broken subtransaction and abort the parent. The same
2599 * applies if we get a failure while ending a subtransaction.
2601 case TBLOCK_SUBBEGIN
:
2603 case TBLOCK_SUBABORT_PENDING
:
2604 case TBLOCK_SUBRESTART
:
2605 AbortSubTransaction();
2606 CleanupSubTransaction();
2607 AbortCurrentTransaction();
2611 * Same as above, except the Abort() was already done.
2613 case TBLOCK_SUBABORT_END
:
2614 case TBLOCK_SUBABORT_RESTART
:
2615 CleanupSubTransaction();
2616 AbortCurrentTransaction();
2622 * PreventTransactionChain
2624 * This routine is to be called by statements that must not run inside
2625 * a transaction block, typically because they have non-rollback-able
2626 * side effects or do internal commits.
2628 * If we have already started a transaction block, issue an error; also issue
2629 * an error if we appear to be running inside a user-defined function (which
2630 * could issue more commands and possibly cause a failure after the statement
2631 * completes). Subtransactions are verboten too.
2633 * isTopLevel: passed down from ProcessUtility to determine whether we are
2634 * inside a function or multi-query querystring. (We will always fail if
2635 * this is false, but it's convenient to centralize the check here instead of
2636 * making callers do it.)
2637 * stmtType: statement type name, for error messages.
2640 PreventTransactionChain(bool isTopLevel
, const char *stmtType
)
2643 * xact block already started?
2645 if (IsTransactionBlock())
2647 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2648 /* translator: %s represents an SQL statement name */
2649 errmsg("%s cannot run inside a transaction block",
2655 if (IsSubTransaction())
2657 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2658 /* translator: %s represents an SQL statement name */
2659 errmsg("%s cannot run inside a subtransaction",
2663 * inside a function call?
2667 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2668 /* translator: %s represents an SQL statement name */
2669 errmsg("%s cannot be executed from a function or multi-command string",
2672 /* If we got past IsTransactionBlock test, should be in default state */
2673 if (CurrentTransactionState
->blockState
!= TBLOCK_DEFAULT
&&
2674 CurrentTransactionState
->blockState
!= TBLOCK_STARTED
)
2675 elog(FATAL
, "cannot prevent transaction chain");
2680 * RequireTransactionChain
2682 * This routine is to be called by statements that must run inside
2683 * a transaction block, because they have no effects that persist past
2684 * transaction end (and so calling them outside a transaction block
2685 * is presumably an error). DECLARE CURSOR is an example.
2687 * If we appear to be running inside a user-defined function, we do not
2688 * issue an error, since the function could issue more commands that make
2689 * use of the current statement's results. Likewise subtransactions.
2690 * Thus this is an inverse for PreventTransactionChain.
2692 * isTopLevel: passed down from ProcessUtility to determine whether we are
2693 * inside a function.
2694 * stmtType: statement type name, for error messages.
2697 RequireTransactionChain(bool isTopLevel
, const char *stmtType
)
2700 * xact block already started?
2702 if (IsTransactionBlock())
2708 if (IsSubTransaction())
2712 * inside a function call?
2718 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
2719 /* translator: %s represents an SQL statement name */
2720 errmsg("%s can only be used in transaction blocks",
2725 * IsInTransactionChain
2727 * This routine is for statements that need to behave differently inside
2728 * a transaction block than when running as single commands. ANALYZE is
2729 * currently the only example.
2731 * isTopLevel: passed down from ProcessUtility to determine whether we are
2732 * inside a function.
2735 IsInTransactionChain(bool isTopLevel
)
2738 * Return true on same conditions that would make PreventTransactionChain
2741 if (IsTransactionBlock())
2744 if (IsSubTransaction())
2750 if (CurrentTransactionState
->blockState
!= TBLOCK_DEFAULT
&&
2751 CurrentTransactionState
->blockState
!= TBLOCK_STARTED
)
2759 * Register or deregister callback functions for start- and end-of-xact
2762 * These functions are intended for use by dynamically loaded modules.
2763 * For built-in modules we generally just hardwire the appropriate calls
2764 * (mainly because it's easier to control the order that way, where needed).
2766 * At transaction end, the callback occurs post-commit or post-abort, so the
2767 * callback functions can only do noncritical cleanup.
2770 RegisterXactCallback(XactCallback callback
, void *arg
)
2772 XactCallbackItem
*item
;
2774 item
= (XactCallbackItem
*)
2775 MemoryContextAlloc(TopMemoryContext
, sizeof(XactCallbackItem
));
2776 item
->callback
= callback
;
2778 item
->next
= Xact_callbacks
;
2779 Xact_callbacks
= item
;
2783 UnregisterXactCallback(XactCallback callback
, void *arg
)
2785 XactCallbackItem
*item
;
2786 XactCallbackItem
*prev
;
2789 for (item
= Xact_callbacks
; item
; prev
= item
, item
= item
->next
)
2791 if (item
->callback
== callback
&& item
->arg
== arg
)
2794 prev
->next
= item
->next
;
2796 Xact_callbacks
= item
->next
;
2804 CallXactCallbacks(XactEvent event
)
2806 XactCallbackItem
*item
;
2808 for (item
= Xact_callbacks
; item
; item
= item
->next
)
2809 (*item
->callback
) (event
, item
->arg
);
2814 * Register or deregister callback functions for start- and end-of-subxact
2817 * Pretty much same as above, but for subtransaction events.
2819 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2820 * so the callback functions can only do noncritical cleanup. At
2821 * subtransaction start, the callback is called when the subtransaction has
2822 * finished initializing.
2825 RegisterSubXactCallback(SubXactCallback callback
, void *arg
)
2827 SubXactCallbackItem
*item
;
2829 item
= (SubXactCallbackItem
*)
2830 MemoryContextAlloc(TopMemoryContext
, sizeof(SubXactCallbackItem
));
2831 item
->callback
= callback
;
2833 item
->next
= SubXact_callbacks
;
2834 SubXact_callbacks
= item
;
2838 UnregisterSubXactCallback(SubXactCallback callback
, void *arg
)
2840 SubXactCallbackItem
*item
;
2841 SubXactCallbackItem
*prev
;
2844 for (item
= SubXact_callbacks
; item
; prev
= item
, item
= item
->next
)
2846 if (item
->callback
== callback
&& item
->arg
== arg
)
2849 prev
->next
= item
->next
;
2851 SubXact_callbacks
= item
->next
;
2859 CallSubXactCallbacks(SubXactEvent event
,
2860 SubTransactionId mySubid
,
2861 SubTransactionId parentSubid
)
2863 SubXactCallbackItem
*item
;
2865 for (item
= SubXact_callbacks
; item
; item
= item
->next
)
2866 (*item
->callback
) (event
, mySubid
, parentSubid
, item
->arg
);
2870 /* ----------------------------------------------------------------
2871 * transaction block support
2872 * ----------------------------------------------------------------
2876 * BeginTransactionBlock
2877 * This executes a BEGIN command.
2880 BeginTransactionBlock(void)
2882 TransactionState s
= CurrentTransactionState
;
2884 switch (s
->blockState
)
2887 * We are not inside a transaction block, so allow one to begin.
2889 case TBLOCK_STARTED
:
2890 s
->blockState
= TBLOCK_BEGIN
;
2894 * Already a transaction block in progress.
2896 case TBLOCK_INPROGRESS
:
2897 case TBLOCK_SUBINPROGRESS
:
2899 case TBLOCK_SUBABORT
:
2901 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2902 errmsg("there is already a transaction in progress")));
2905 /* These cases are invalid. */
2906 case TBLOCK_DEFAULT
:
2908 case TBLOCK_SUBBEGIN
:
2911 case TBLOCK_ABORT_END
:
2912 case TBLOCK_SUBABORT_END
:
2913 case TBLOCK_ABORT_PENDING
:
2914 case TBLOCK_SUBABORT_PENDING
:
2915 case TBLOCK_SUBRESTART
:
2916 case TBLOCK_SUBABORT_RESTART
:
2917 case TBLOCK_PREPARE
:
2918 elog(FATAL
, "BeginTransactionBlock: unexpected state %s",
2919 BlockStateAsString(s
->blockState
));
2925 * PrepareTransactionBlock
2926 * This executes a PREPARE command.
2928 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2929 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2931 * Note that we don't actually do anything here except change blockState.
2932 * The real work will be done in the upcoming PrepareTransaction().
2933 * We do it this way because it's not convenient to change memory context,
2934 * resource owner, etc while executing inside a Portal.
2937 PrepareTransactionBlock(char *gid
)
2942 /* Set up to commit the current transaction */
2943 result
= EndTransactionBlock();
2945 /* If successful, change outer tblock state to PREPARE */
2948 s
= CurrentTransactionState
;
2950 while (s
->parent
!= NULL
)
2953 if (s
->blockState
== TBLOCK_END
)
2955 /* Save GID where PrepareTransaction can find it again */
2956 prepareGID
= MemoryContextStrdup(TopTransactionContext
, gid
);
2958 s
->blockState
= TBLOCK_PREPARE
;
2963 * ignore case where we are not in a transaction;
2964 * EndTransactionBlock already issued a warning.
2966 Assert(s
->blockState
== TBLOCK_STARTED
);
2967 /* Don't send back a PREPARE result tag... */
2976 * EndTransactionBlock
2977 * This executes a COMMIT command.
2979 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2980 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2982 * Note that we don't actually do anything here except change blockState.
2983 * The real work will be done in the upcoming CommitTransactionCommand().
2984 * We do it this way because it's not convenient to change memory context,
2985 * resource owner, etc while executing inside a Portal.
2988 EndTransactionBlock(void)
2990 TransactionState s
= CurrentTransactionState
;
2991 bool result
= false;
2993 switch (s
->blockState
)
2996 * We are in a transaction block, so tell CommitTransactionCommand
2999 case TBLOCK_INPROGRESS
:
3000 s
->blockState
= TBLOCK_END
;
3005 * We are in a failed transaction block. Tell
3006 * CommitTransactionCommand it's time to exit the block.
3009 s
->blockState
= TBLOCK_ABORT_END
;
3013 * We are in a live subtransaction block. Set up to subcommit all
3014 * open subtransactions and then commit the main transaction.
3016 case TBLOCK_SUBINPROGRESS
:
3017 while (s
->parent
!= NULL
)
3019 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3020 s
->blockState
= TBLOCK_SUBEND
;
3022 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3023 BlockStateAsString(s
->blockState
));
3026 if (s
->blockState
== TBLOCK_INPROGRESS
)
3027 s
->blockState
= TBLOCK_END
;
3029 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3030 BlockStateAsString(s
->blockState
));
3035 * Here we are inside an aborted subtransaction. Treat the COMMIT
3036 * as ROLLBACK: set up to abort everything and exit the main
3039 case TBLOCK_SUBABORT
:
3040 while (s
->parent
!= NULL
)
3042 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3043 s
->blockState
= TBLOCK_SUBABORT_PENDING
;
3044 else if (s
->blockState
== TBLOCK_SUBABORT
)
3045 s
->blockState
= TBLOCK_SUBABORT_END
;
3047 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3048 BlockStateAsString(s
->blockState
));
3051 if (s
->blockState
== TBLOCK_INPROGRESS
)
3052 s
->blockState
= TBLOCK_ABORT_PENDING
;
3053 else if (s
->blockState
== TBLOCK_ABORT
)
3054 s
->blockState
= TBLOCK_ABORT_END
;
3056 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3057 BlockStateAsString(s
->blockState
));
3061 * The user issued COMMIT when not inside a transaction. Issue a
3062 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
3063 * CommitTransactionCommand() will then close the transaction and
3064 * put us back into the default state.
3066 case TBLOCK_STARTED
:
3068 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
3069 errmsg("there is no transaction in progress")));
3073 /* These cases are invalid. */
3074 case TBLOCK_DEFAULT
:
3076 case TBLOCK_SUBBEGIN
:
3079 case TBLOCK_ABORT_END
:
3080 case TBLOCK_SUBABORT_END
:
3081 case TBLOCK_ABORT_PENDING
:
3082 case TBLOCK_SUBABORT_PENDING
:
3083 case TBLOCK_SUBRESTART
:
3084 case TBLOCK_SUBABORT_RESTART
:
3085 case TBLOCK_PREPARE
:
3086 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3087 BlockStateAsString(s
->blockState
));
3095 * UserAbortTransactionBlock
3096 * This executes a ROLLBACK command.
3098 * As above, we don't actually do anything here except change blockState.
3101 UserAbortTransactionBlock(void)
3103 TransactionState s
= CurrentTransactionState
;
3105 switch (s
->blockState
)
3108 * We are inside a transaction block and we got a ROLLBACK command
3109 * from the user, so tell CommitTransactionCommand to abort and
3110 * exit the transaction block.
3112 case TBLOCK_INPROGRESS
:
3113 s
->blockState
= TBLOCK_ABORT_PENDING
;
3117 * We are inside a failed transaction block and we got a ROLLBACK
3118 * command from the user. Abort processing is already done, so
3119 * CommitTransactionCommand just has to cleanup and go back to
3123 s
->blockState
= TBLOCK_ABORT_END
;
3127 * We are inside a subtransaction. Mark everything up to top
3128 * level as exitable.
3130 case TBLOCK_SUBINPROGRESS
:
3131 case TBLOCK_SUBABORT
:
3132 while (s
->parent
!= NULL
)
3134 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3135 s
->blockState
= TBLOCK_SUBABORT_PENDING
;
3136 else if (s
->blockState
== TBLOCK_SUBABORT
)
3137 s
->blockState
= TBLOCK_SUBABORT_END
;
3139 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3140 BlockStateAsString(s
->blockState
));
3143 if (s
->blockState
== TBLOCK_INPROGRESS
)
3144 s
->blockState
= TBLOCK_ABORT_PENDING
;
3145 else if (s
->blockState
== TBLOCK_ABORT
)
3146 s
->blockState
= TBLOCK_ABORT_END
;
3148 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3149 BlockStateAsString(s
->blockState
));
3153 * The user issued ABORT when not inside a transaction. Issue a
3154 * WARNING and go to abort state. The upcoming call to
3155 * CommitTransactionCommand() will then put us back into the
3158 case TBLOCK_STARTED
:
3160 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
3161 errmsg("there is no transaction in progress")));
3162 s
->blockState
= TBLOCK_ABORT_PENDING
;
3165 /* These cases are invalid. */
3166 case TBLOCK_DEFAULT
:
3168 case TBLOCK_SUBBEGIN
:
3171 case TBLOCK_ABORT_END
:
3172 case TBLOCK_SUBABORT_END
:
3173 case TBLOCK_ABORT_PENDING
:
3174 case TBLOCK_SUBABORT_PENDING
:
3175 case TBLOCK_SUBRESTART
:
3176 case TBLOCK_SUBABORT_RESTART
:
3177 case TBLOCK_PREPARE
:
3178 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3179 BlockStateAsString(s
->blockState
));
3186 * This executes a SAVEPOINT command.
3189 DefineSavepoint(char *name
)
3191 TransactionState s
= CurrentTransactionState
;
3193 switch (s
->blockState
)
3195 case TBLOCK_INPROGRESS
:
3196 case TBLOCK_SUBINPROGRESS
:
3197 /* Normal subtransaction start */
3199 s
= CurrentTransactionState
; /* changed by push */
3202 * Savepoint names, like the TransactionState block itself, live
3203 * in TopTransactionContext.
3206 s
->name
= MemoryContextStrdup(TopTransactionContext
, name
);
3209 /* These cases are invalid. */
3210 case TBLOCK_DEFAULT
:
3211 case TBLOCK_STARTED
:
3213 case TBLOCK_SUBBEGIN
:
3217 case TBLOCK_SUBABORT
:
3218 case TBLOCK_ABORT_END
:
3219 case TBLOCK_SUBABORT_END
:
3220 case TBLOCK_ABORT_PENDING
:
3221 case TBLOCK_SUBABORT_PENDING
:
3222 case TBLOCK_SUBRESTART
:
3223 case TBLOCK_SUBABORT_RESTART
:
3224 case TBLOCK_PREPARE
:
3225 elog(FATAL
, "DefineSavepoint: unexpected state %s",
3226 BlockStateAsString(s
->blockState
));
3233 * This executes a RELEASE command.
3235 * As above, we don't actually do anything here except change blockState.
3238 ReleaseSavepoint(List
*options
)
3240 TransactionState s
= CurrentTransactionState
;
3241 TransactionState target
,
3246 switch (s
->blockState
)
3249 * We can't rollback to a savepoint if there is no savepoint
3252 case TBLOCK_INPROGRESS
:
3254 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3255 errmsg("no such savepoint")));
3259 * We are in a non-aborted subtransaction. This is the only valid
3262 case TBLOCK_SUBINPROGRESS
:
3265 /* These cases are invalid. */
3266 case TBLOCK_DEFAULT
:
3267 case TBLOCK_STARTED
:
3269 case TBLOCK_SUBBEGIN
:
3273 case TBLOCK_SUBABORT
:
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
, "ReleaseSavepoint: 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 "commit pending" all subtransactions up to the target
3315 * subtransaction. The actual commits will happen when control gets to
3316 * CommitTransactionCommand.
3318 xact
= CurrentTransactionState
;
3321 Assert(xact
->blockState
== TBLOCK_SUBINPROGRESS
);
3322 xact
->blockState
= TBLOCK_SUBEND
;
3325 xact
= xact
->parent
;
3326 Assert(PointerIsValid(xact
));
3331 * RollbackToSavepoint
3332 * This executes a ROLLBACK TO <savepoint> command.
3334 * As above, we don't actually do anything here except change blockState.
3337 RollbackToSavepoint(List
*options
)
3339 TransactionState s
= CurrentTransactionState
;
3340 TransactionState target
,
3345 switch (s
->blockState
)
3348 * We can't rollback to a savepoint if there is no savepoint
3351 case TBLOCK_INPROGRESS
:
3354 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3355 errmsg("no such savepoint")));
3359 * There is at least one savepoint, so proceed.
3361 case TBLOCK_SUBINPROGRESS
:
3362 case TBLOCK_SUBABORT
:
3365 /* These cases are invalid. */
3366 case TBLOCK_DEFAULT
:
3367 case TBLOCK_STARTED
:
3369 case TBLOCK_SUBBEGIN
:
3372 case TBLOCK_ABORT_END
:
3373 case TBLOCK_SUBABORT_END
:
3374 case TBLOCK_ABORT_PENDING
:
3375 case TBLOCK_SUBABORT_PENDING
:
3376 case TBLOCK_SUBRESTART
:
3377 case TBLOCK_SUBABORT_RESTART
:
3378 case TBLOCK_PREPARE
:
3379 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3380 BlockStateAsString(s
->blockState
));
3384 foreach(cell
, options
)
3386 DefElem
*elem
= lfirst(cell
);
3388 if (strcmp(elem
->defname
, "savepoint_name") == 0)
3389 name
= strVal(elem
->arg
);
3392 Assert(PointerIsValid(name
));
3394 for (target
= s
; PointerIsValid(target
); target
= target
->parent
)
3396 if (PointerIsValid(target
->name
) && strcmp(target
->name
, name
) == 0)
3400 if (!PointerIsValid(target
))
3402 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3403 errmsg("no such savepoint")));
3405 /* disallow crossing savepoint level boundaries */
3406 if (target
->savepointLevel
!= s
->savepointLevel
)
3408 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3409 errmsg("no such savepoint")));
3412 * Mark "abort pending" all subtransactions up to the target
3413 * subtransaction. The actual aborts will happen when control gets to
3414 * CommitTransactionCommand.
3416 xact
= CurrentTransactionState
;
3421 if (xact
->blockState
== TBLOCK_SUBINPROGRESS
)
3422 xact
->blockState
= TBLOCK_SUBABORT_PENDING
;
3423 else if (xact
->blockState
== TBLOCK_SUBABORT
)
3424 xact
->blockState
= TBLOCK_SUBABORT_END
;
3426 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3427 BlockStateAsString(xact
->blockState
));
3428 xact
= xact
->parent
;
3429 Assert(PointerIsValid(xact
));
3432 /* And mark the target as "restart pending" */
3433 if (xact
->blockState
== TBLOCK_SUBINPROGRESS
)
3434 xact
->blockState
= TBLOCK_SUBRESTART
;
3435 else if (xact
->blockState
== TBLOCK_SUBABORT
)
3436 xact
->blockState
= TBLOCK_SUBABORT_RESTART
;
3438 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3439 BlockStateAsString(xact
->blockState
));
3443 * BeginInternalSubTransaction
3444 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3445 * TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3446 * used in functions that might be called when not inside a BEGIN block
3447 * or when running deferred triggers at COMMIT/PREPARE time. Also, it
3448 * automatically does CommitTransactionCommand/StartTransactionCommand
3449 * instead of expecting the caller to do it.
3452 BeginInternalSubTransaction(char *name
)
3454 TransactionState s
= CurrentTransactionState
;
3456 switch (s
->blockState
)
3458 case TBLOCK_STARTED
:
3459 case TBLOCK_INPROGRESS
:
3461 case TBLOCK_PREPARE
:
3462 case TBLOCK_SUBINPROGRESS
:
3463 /* Normal subtransaction start */
3465 s
= CurrentTransactionState
; /* changed by push */
3468 * Savepoint names, like the TransactionState block itself, live
3469 * in TopTransactionContext.
3472 s
->name
= MemoryContextStrdup(TopTransactionContext
, name
);
3475 /* These cases are invalid. */
3476 case TBLOCK_DEFAULT
:
3478 case TBLOCK_SUBBEGIN
:
3481 case TBLOCK_SUBABORT
:
3482 case TBLOCK_ABORT_END
:
3483 case TBLOCK_SUBABORT_END
:
3484 case TBLOCK_ABORT_PENDING
:
3485 case TBLOCK_SUBABORT_PENDING
:
3486 case TBLOCK_SUBRESTART
:
3487 case TBLOCK_SUBABORT_RESTART
:
3488 elog(FATAL
, "BeginInternalSubTransaction: unexpected state %s",
3489 BlockStateAsString(s
->blockState
));
3493 CommitTransactionCommand();
3494 StartTransactionCommand();
3498 * ReleaseCurrentSubTransaction
3500 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3501 * savepoint name (if any).
3502 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3505 ReleaseCurrentSubTransaction(void)
3507 TransactionState s
= CurrentTransactionState
;
3509 if (s
->blockState
!= TBLOCK_SUBINPROGRESS
)
3510 elog(ERROR
, "ReleaseCurrentSubTransaction: unexpected state %s",
3511 BlockStateAsString(s
->blockState
));
3512 Assert(s
->state
== TRANS_INPROGRESS
);
3513 MemoryContextSwitchTo(CurTransactionContext
);
3514 CommitSubTransaction();
3515 s
= CurrentTransactionState
; /* changed by pop */
3516 Assert(s
->state
== TRANS_INPROGRESS
);
3520 * RollbackAndReleaseCurrentSubTransaction
3522 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3523 * of its savepoint name (if any).
3524 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3527 RollbackAndReleaseCurrentSubTransaction(void)
3529 TransactionState s
= CurrentTransactionState
;
3531 switch (s
->blockState
)
3533 /* Must be in a subtransaction */
3534 case TBLOCK_SUBINPROGRESS
:
3535 case TBLOCK_SUBABORT
:
3538 /* These cases are invalid. */
3539 case TBLOCK_DEFAULT
:
3540 case TBLOCK_STARTED
:
3542 case TBLOCK_SUBBEGIN
:
3543 case TBLOCK_INPROGRESS
:
3547 case TBLOCK_ABORT_END
:
3548 case TBLOCK_SUBABORT_END
:
3549 case TBLOCK_ABORT_PENDING
:
3550 case TBLOCK_SUBABORT_PENDING
:
3551 case TBLOCK_SUBRESTART
:
3552 case TBLOCK_SUBABORT_RESTART
:
3553 case TBLOCK_PREPARE
:
3554 elog(FATAL
, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3555 BlockStateAsString(s
->blockState
));
3560 * Abort the current subtransaction, if needed.
3562 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3563 AbortSubTransaction();
3565 /* And clean it up, too */
3566 CleanupSubTransaction();
3568 s
= CurrentTransactionState
; /* changed by pop */
3569 AssertState(s
->blockState
== TBLOCK_SUBINPROGRESS
||
3570 s
->blockState
== TBLOCK_INPROGRESS
||
3571 s
->blockState
== TBLOCK_STARTED
);
3575 * AbortOutOfAnyTransaction
3577 * This routine is provided for error recovery purposes. It aborts any
3578 * active transaction or transaction block, leaving the system in a known
3582 AbortOutOfAnyTransaction(void)
3584 TransactionState s
= CurrentTransactionState
;
3587 * Get out of any transaction or nested transaction
3591 switch (s
->blockState
)
3593 case TBLOCK_DEFAULT
:
3594 /* Not in a transaction, do nothing */
3596 case TBLOCK_STARTED
:
3598 case TBLOCK_INPROGRESS
:
3600 case TBLOCK_ABORT_PENDING
:
3601 case TBLOCK_PREPARE
:
3602 /* In a transaction, so clean up */
3604 CleanupTransaction();
3605 s
->blockState
= TBLOCK_DEFAULT
;
3608 case TBLOCK_ABORT_END
:
3609 /* AbortTransaction already done, still need Cleanup */
3610 CleanupTransaction();
3611 s
->blockState
= TBLOCK_DEFAULT
;
3615 * In a subtransaction, so clean it up and abort parent too
3617 case TBLOCK_SUBBEGIN
:
3618 case TBLOCK_SUBINPROGRESS
:
3620 case TBLOCK_SUBABORT_PENDING
:
3621 case TBLOCK_SUBRESTART
:
3622 AbortSubTransaction();
3623 CleanupSubTransaction();
3624 s
= CurrentTransactionState
; /* changed by pop */
3627 case TBLOCK_SUBABORT
:
3628 case TBLOCK_SUBABORT_END
:
3629 case TBLOCK_SUBABORT_RESTART
:
3630 /* As above, but AbortSubTransaction already done */
3631 CleanupSubTransaction();
3632 s
= CurrentTransactionState
; /* changed by pop */
3635 } while (s
->blockState
!= TBLOCK_DEFAULT
);
3637 /* Should be out of all subxacts now */
3638 Assert(s
->parent
== NULL
);
3642 * IsTransactionBlock --- are we within a transaction block?
3645 IsTransactionBlock(void)
3647 TransactionState s
= CurrentTransactionState
;
3649 if (s
->blockState
== TBLOCK_DEFAULT
|| s
->blockState
== TBLOCK_STARTED
)
3656 * IsTransactionOrTransactionBlock --- are we within either a transaction
3657 * or a transaction block? (The backend is only really "idle" when this
3660 * This should match up with IsTransactionBlock and IsTransactionState.
3663 IsTransactionOrTransactionBlock(void)
3665 TransactionState s
= CurrentTransactionState
;
3667 if (s
->blockState
== TBLOCK_DEFAULT
)
3674 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3677 TransactionBlockStatusCode(void)
3679 TransactionState s
= CurrentTransactionState
;
3681 switch (s
->blockState
)
3683 case TBLOCK_DEFAULT
:
3684 case TBLOCK_STARTED
:
3685 return 'I'; /* idle --- not in transaction */
3687 case TBLOCK_SUBBEGIN
:
3688 case TBLOCK_INPROGRESS
:
3689 case TBLOCK_SUBINPROGRESS
:
3692 case TBLOCK_PREPARE
:
3693 return 'T'; /* in transaction */
3695 case TBLOCK_SUBABORT
:
3696 case TBLOCK_ABORT_END
:
3697 case TBLOCK_SUBABORT_END
:
3698 case TBLOCK_ABORT_PENDING
:
3699 case TBLOCK_SUBABORT_PENDING
:
3700 case TBLOCK_SUBRESTART
:
3701 case TBLOCK_SUBABORT_RESTART
:
3702 return 'E'; /* in failed transaction */
3705 /* should never get here */
3706 elog(FATAL
, "invalid transaction block state: %s",
3707 BlockStateAsString(s
->blockState
));
3708 return 0; /* keep compiler quiet */
3715 IsSubTransaction(void)
3717 TransactionState s
= CurrentTransactionState
;
3719 if (s
->nestingLevel
>= 2)
3726 * StartSubTransaction
3728 * If you're wondering why this is separate from PushTransaction: it's because
3729 * we can't conveniently do this stuff right inside DefineSavepoint. The
3730 * SAVEPOINT utility command will be executed inside a Portal, and if we
3731 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3732 * the Portal will undo those settings. So we make DefineSavepoint just
3733 * push a dummy transaction block, and when control returns to the main
3734 * idle loop, CommitTransactionCommand will be called, and we'll come here
3735 * to finish starting the subtransaction.
3738 StartSubTransaction(void)
3740 TransactionState s
= CurrentTransactionState
;
3742 if (s
->state
!= TRANS_DEFAULT
)
3743 elog(WARNING
, "StartSubTransaction while in %s state",
3744 TransStateAsString(s
->state
));
3746 s
->state
= TRANS_START
;
3749 * Initialize subsystems for new subtransaction
3751 * must initialize resource-management stuff first
3753 AtSubStart_Memory();
3754 AtSubStart_ResourceOwner();
3756 AtSubStart_Notify();
3757 AfterTriggerBeginSubXact();
3759 s
->state
= TRANS_INPROGRESS
;
3762 * Call start-of-subxact callbacks
3764 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB
, s
->subTransactionId
,
3765 s
->parent
->subTransactionId
);
3767 ShowTransactionState("StartSubTransaction");
3771 * CommitSubTransaction
3773 * The caller has to make sure to always reassign CurrentTransactionState
3774 * if it has a local pointer to it after calling this function.
3777 CommitSubTransaction(void)
3779 TransactionState s
= CurrentTransactionState
;
3781 ShowTransactionState("CommitSubTransaction");
3783 if (s
->state
!= TRANS_INPROGRESS
)
3784 elog(WARNING
, "CommitSubTransaction while in %s state",
3785 TransStateAsString(s
->state
));
3787 /* Pre-commit processing goes here -- nothing to do at the moment */
3789 s
->state
= TRANS_COMMIT
;
3791 /* Must CCI to ensure commands of subtransaction are seen as done */
3792 CommandCounterIncrement();
3794 /* Mark subtransaction as subcommitted */
3795 RecordSubTransactionCommit();
3797 /* Post-commit cleanup */
3798 if (TransactionIdIsValid(s
->transactionId
))
3799 AtSubCommit_childXids();
3800 AfterTriggerEndSubXact(true);
3801 AtSubCommit_Portals(s
->subTransactionId
,
3802 s
->parent
->subTransactionId
,
3803 s
->parent
->curTransactionOwner
);
3804 AtEOSubXact_LargeObject(true, s
->subTransactionId
,
3805 s
->parent
->subTransactionId
);
3806 AtSubCommit_Notify();
3807 AtEOSubXact_UpdateFlatFiles(true, s
->subTransactionId
,
3808 s
->parent
->subTransactionId
);
3810 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB
, s
->subTransactionId
,
3811 s
->parent
->subTransactionId
);
3813 ResourceOwnerRelease(s
->curTransactionOwner
,
3814 RESOURCE_RELEASE_BEFORE_LOCKS
,
3816 AtEOSubXact_RelationCache(true, s
->subTransactionId
,
3817 s
->parent
->subTransactionId
);
3818 AtEOSubXact_Inval(true);
3822 * The only lock we actually release here is the subtransaction XID lock.
3823 * The rest just get transferred to the parent resource owner.
3825 CurrentResourceOwner
= s
->curTransactionOwner
;
3826 if (TransactionIdIsValid(s
->transactionId
))
3827 XactLockTableDelete(s
->transactionId
);
3829 ResourceOwnerRelease(s
->curTransactionOwner
,
3830 RESOURCE_RELEASE_LOCKS
,
3832 ResourceOwnerRelease(s
->curTransactionOwner
,
3833 RESOURCE_RELEASE_AFTER_LOCKS
,
3836 AtEOXact_GUC(true, s
->gucNestLevel
);
3837 AtEOSubXact_SPI(true, s
->subTransactionId
);
3838 AtEOSubXact_on_commit_actions(true, s
->subTransactionId
,
3839 s
->parent
->subTransactionId
);
3840 AtEOSubXact_Namespace(true, s
->subTransactionId
,
3841 s
->parent
->subTransactionId
);
3842 AtEOSubXact_Files(true, s
->subTransactionId
,
3843 s
->parent
->subTransactionId
);
3844 AtEOSubXact_HashTables(true, s
->nestingLevel
);
3845 AtEOSubXact_PgStat(true, s
->nestingLevel
);
3846 AtSubCommit_Snapshot(s
->nestingLevel
);
3849 * We need to restore the upper transaction's read-only state, in case the
3850 * upper is read-write while the child is read-only; GUC will incorrectly
3851 * think it should leave the child state in place.
3853 XactReadOnly
= s
->prevXactReadOnly
;
3855 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
3856 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
3857 ResourceOwnerDelete(s
->curTransactionOwner
);
3858 s
->curTransactionOwner
= NULL
;
3860 AtSubCommit_Memory();
3862 s
->state
= TRANS_DEFAULT
;
3868 * AbortSubTransaction
3871 AbortSubTransaction(void)
3873 TransactionState s
= CurrentTransactionState
;
3875 /* Prevent cancel/die interrupt while cleaning up */
3878 /* Make sure we have a valid memory context and resource owner */
3879 AtSubAbort_Memory();
3880 AtSubAbort_ResourceOwner();
3883 * Release any LW locks we might be holding as quickly as possible.
3884 * (Regular locks, however, must be held till we finish aborting.)
3885 * Releasing LW locks is critical since we might try to grab them again
3886 * while cleaning up!
3888 * FIXME This may be incorrect --- Are there some locks we should keep?
3889 * Buffer locks, for example? I don't think so but I'm not sure.
3899 * check the current transaction state
3901 ShowTransactionState("AbortSubTransaction");
3903 if (s
->state
!= TRANS_INPROGRESS
)
3904 elog(WARNING
, "AbortSubTransaction while in %s state",
3905 TransStateAsString(s
->state
));
3907 s
->state
= TRANS_ABORT
;
3910 * Reset user ID which might have been changed transiently. (See notes
3911 * in AbortTransaction.)
3913 SetUserIdAndContext(s
->prevUser
, s
->prevSecDefCxt
);
3916 * We can skip all this stuff if the subxact failed before creating a
3919 if (s
->curTransactionOwner
)
3921 AfterTriggerEndSubXact(false);
3922 AtSubAbort_Portals(s
->subTransactionId
,
3923 s
->parent
->subTransactionId
,
3924 s
->parent
->curTransactionOwner
);
3925 AtEOSubXact_LargeObject(false, s
->subTransactionId
,
3926 s
->parent
->subTransactionId
);
3927 AtSubAbort_Notify();
3928 AtEOSubXact_UpdateFlatFiles(false, s
->subTransactionId
,
3929 s
->parent
->subTransactionId
);
3931 /* Advertise the fact that we aborted in pg_clog. */
3932 (void) RecordTransactionAbort(true);
3934 /* Post-abort cleanup */
3935 if (TransactionIdIsValid(s
->transactionId
))
3936 AtSubAbort_childXids();
3938 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB
, s
->subTransactionId
,
3939 s
->parent
->subTransactionId
);
3941 ResourceOwnerRelease(s
->curTransactionOwner
,
3942 RESOURCE_RELEASE_BEFORE_LOCKS
,
3944 AtEOSubXact_RelationCache(false, s
->subTransactionId
,
3945 s
->parent
->subTransactionId
);
3946 AtEOSubXact_Inval(false);
3948 ResourceOwnerRelease(s
->curTransactionOwner
,
3949 RESOURCE_RELEASE_LOCKS
,
3951 ResourceOwnerRelease(s
->curTransactionOwner
,
3952 RESOURCE_RELEASE_AFTER_LOCKS
,
3955 AtEOXact_GUC(false, s
->gucNestLevel
);
3956 AtEOSubXact_SPI(false, s
->subTransactionId
);
3958 AtEOSubXact_on_commit_actions(false, s
->subTransactionId
,
3959 s
->parent
->subTransactionId
);
3960 AtEOSubXact_Namespace(false, s
->subTransactionId
,
3961 s
->parent
->subTransactionId
);
3962 AtEOSubXact_Files(false, s
->subTransactionId
,
3963 s
->parent
->subTransactionId
);
3964 AtEOSubXact_HashTables(false, s
->nestingLevel
);
3965 AtEOSubXact_PgStat(false, s
->nestingLevel
);
3966 AtSubAbort_Snapshot(s
->nestingLevel
);
3970 * Restore the upper transaction's read-only state, too. This should be
3971 * redundant with GUC's cleanup but we may as well do it for consistency
3972 * with the commit case.
3974 XactReadOnly
= s
->prevXactReadOnly
;
3976 RESUME_INTERRUPTS();
3980 * CleanupSubTransaction
3982 * The caller has to make sure to always reassign CurrentTransactionState
3983 * if it has a local pointer to it after calling this function.
3986 CleanupSubTransaction(void)
3988 TransactionState s
= CurrentTransactionState
;
3990 ShowTransactionState("CleanupSubTransaction");
3992 if (s
->state
!= TRANS_ABORT
)
3993 elog(WARNING
, "CleanupSubTransaction while in %s state",
3994 TransStateAsString(s
->state
));
3996 AtSubCleanup_Portals(s
->subTransactionId
);
3998 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
3999 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
4000 if (s
->curTransactionOwner
)
4001 ResourceOwnerDelete(s
->curTransactionOwner
);
4002 s
->curTransactionOwner
= NULL
;
4004 AtSubCleanup_Memory();
4006 s
->state
= TRANS_DEFAULT
;
4013 * Create transaction state stack entry for a subtransaction
4015 * The caller has to make sure to always reassign CurrentTransactionState
4016 * if it has a local pointer to it after calling this function.
4019 PushTransaction(void)
4021 TransactionState p
= CurrentTransactionState
;
4025 * We keep subtransaction state nodes in TopTransactionContext.
4027 s
= (TransactionState
)
4028 MemoryContextAllocZero(TopTransactionContext
,
4029 sizeof(TransactionStateData
));
4032 * Assign a subtransaction ID, watching out for counter wraparound.
4034 currentSubTransactionId
+= 1;
4035 if (currentSubTransactionId
== InvalidSubTransactionId
)
4037 currentSubTransactionId
-= 1;
4040 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
4041 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
4045 * We can now stack a minimally valid subtransaction without fear of
4048 s
->transactionId
= InvalidTransactionId
; /* until assigned */
4049 s
->subTransactionId
= currentSubTransactionId
;
4051 s
->nestingLevel
= p
->nestingLevel
+ 1;
4052 s
->gucNestLevel
= NewGUCNestLevel();
4053 s
->savepointLevel
= p
->savepointLevel
;
4054 s
->state
= TRANS_DEFAULT
;
4055 s
->blockState
= TBLOCK_SUBBEGIN
;
4056 GetUserIdAndContext(&s
->prevUser
, &s
->prevSecDefCxt
);
4057 s
->prevXactReadOnly
= XactReadOnly
;
4059 CurrentTransactionState
= s
;
4062 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
4063 * with the subtransaction from here on out; in particular they should not
4064 * assume that it necessarily has a transaction context, resource owner,
4071 * Pop back to parent transaction state
4073 * The caller has to make sure to always reassign CurrentTransactionState
4074 * if it has a local pointer to it after calling this function.
4077 PopTransaction(void)
4079 TransactionState s
= CurrentTransactionState
;
4081 if (s
->state
!= TRANS_DEFAULT
)
4082 elog(WARNING
, "PopTransaction while in %s state",
4083 TransStateAsString(s
->state
));
4085 if (s
->parent
== NULL
)
4086 elog(FATAL
, "PopTransaction with no parent");
4088 CurrentTransactionState
= s
->parent
;
4090 /* Let's just make sure CurTransactionContext is good */
4091 CurTransactionContext
= s
->parent
->curTransactionContext
;
4092 MemoryContextSwitchTo(CurTransactionContext
);
4094 /* Ditto for ResourceOwner links */
4095 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
4096 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
4098 /* Free the old child structure */
4105 * ShowTransactionState
4109 ShowTransactionState(const char *str
)
4111 /* skip work if message will definitely not be printed */
4112 if (log_min_messages
<= DEBUG3
|| client_min_messages
<= DEBUG3
)
4114 elog(DEBUG3
, "%s", str
);
4115 ShowTransactionStateRec(CurrentTransactionState
);
4120 * ShowTransactionStateRec
4121 * Recursive subroutine for ShowTransactionState
4124 ShowTransactionStateRec(TransactionState s
)
4128 initStringInfo(&buf
);
4130 if (s
->nChildXids
> 0)
4134 appendStringInfo(&buf
, "%u", s
->childXids
[0]);
4135 for (i
= 1; i
< s
->nChildXids
; i
++)
4136 appendStringInfo(&buf
, " %u", s
->childXids
[i
]);
4140 ShowTransactionStateRec(s
->parent
);
4142 /* use ereport to suppress computation if msg will not be printed */
4144 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
4145 PointerIsValid(s
->name
) ? s
->name
: "unnamed",
4146 BlockStateAsString(s
->blockState
),
4147 TransStateAsString(s
->state
),
4148 (unsigned int) s
->transactionId
,
4149 (unsigned int) s
->subTransactionId
,
4150 (unsigned int) currentCommandId
,
4151 currentCommandIdUsed
? " (used)" : "",
4152 s
->nestingLevel
, buf
.data
)));
4158 * BlockStateAsString
4162 BlockStateAsString(TBlockState blockState
)
4166 case TBLOCK_DEFAULT
:
4168 case TBLOCK_STARTED
:
4172 case TBLOCK_INPROGRESS
:
4173 return "INPROGRESS";
4178 case TBLOCK_ABORT_END
:
4180 case TBLOCK_ABORT_PENDING
:
4181 return "ABORT PEND";
4182 case TBLOCK_PREPARE
:
4184 case TBLOCK_SUBBEGIN
:
4186 case TBLOCK_SUBINPROGRESS
:
4187 return "SUB INPROGRS";
4190 case TBLOCK_SUBABORT
:
4192 case TBLOCK_SUBABORT_END
:
4193 return "SUB ABORT END";
4194 case TBLOCK_SUBABORT_PENDING
:
4195 return "SUB ABRT PEND";
4196 case TBLOCK_SUBRESTART
:
4197 return "SUB RESTART";
4198 case TBLOCK_SUBABORT_RESTART
:
4199 return "SUB AB RESTRT";
4201 return "UNRECOGNIZED";
4205 * TransStateAsString
4209 TransStateAsString(TransState state
)
4217 case TRANS_INPROGRESS
:
4226 return "UNRECOGNIZED";
4230 * xactGetCommittedChildren
4232 * Gets the list of committed children of the current transaction. The return
4233 * value is the number of child transactions. *ptr is set to point to an
4234 * array of TransactionIds. The array is allocated in TopTransactionContext;
4235 * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
4236 * If there are no subxacts, *ptr is set to NULL.
4239 xactGetCommittedChildren(TransactionId
**ptr
)
4241 TransactionState s
= CurrentTransactionState
;
4243 if (s
->nChildXids
== 0)
4246 *ptr
= s
->childXids
;
4248 return s
->nChildXids
;
4252 * XLOG support routines
4256 xact_redo_commit(xl_xact_commit
*xlrec
, TransactionId xid
)
4258 TransactionId
*sub_xids
;
4259 TransactionId max_xid
;
4262 TransactionIdCommit(xid
);
4264 /* Mark committed subtransactions as committed */
4265 sub_xids
= (TransactionId
*) &(xlrec
->xnodes
[xlrec
->nrels
]);
4266 TransactionIdCommitTree(xlrec
->nsubxacts
, sub_xids
);
4268 /* Make sure nextXid is beyond any XID mentioned in the record */
4270 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4272 if (TransactionIdPrecedes(max_xid
, sub_xids
[i
]))
4273 max_xid
= sub_xids
[i
];
4275 if (TransactionIdFollowsOrEquals(max_xid
,
4276 ShmemVariableCache
->nextXid
))
4278 ShmemVariableCache
->nextXid
= max_xid
;
4279 TransactionIdAdvance(ShmemVariableCache
->nextXid
);
4282 /* Make sure files supposed to be dropped are dropped */
4283 for (i
= 0; i
< xlrec
->nrels
; i
++)
4287 XLogDropRelation(xlrec
->xnodes
[i
].rnode
, xlrec
->xnodes
[i
].forknum
);
4289 srel
= smgropen(xlrec
->xnodes
[i
].rnode
);
4290 smgrdounlink(srel
, xlrec
->xnodes
[i
].forknum
, false, true);
4296 xact_redo_abort(xl_xact_abort
*xlrec
, TransactionId xid
)
4298 TransactionId
*sub_xids
;
4299 TransactionId max_xid
;
4302 TransactionIdAbort(xid
);
4304 /* Mark subtransactions as aborted */
4305 sub_xids
= (TransactionId
*) &(xlrec
->xnodes
[xlrec
->nrels
]);
4306 TransactionIdAbortTree(xlrec
->nsubxacts
, sub_xids
);
4308 /* Make sure nextXid is beyond any XID mentioned in the record */
4310 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4312 if (TransactionIdPrecedes(max_xid
, sub_xids
[i
]))
4313 max_xid
= sub_xids
[i
];
4315 if (TransactionIdFollowsOrEquals(max_xid
,
4316 ShmemVariableCache
->nextXid
))
4318 ShmemVariableCache
->nextXid
= max_xid
;
4319 TransactionIdAdvance(ShmemVariableCache
->nextXid
);
4322 /* Make sure files supposed to be dropped are dropped */
4323 for (i
= 0; i
< xlrec
->nrels
; i
++)
4327 XLogDropRelation(xlrec
->xnodes
[i
].rnode
, xlrec
->xnodes
[i
].forknum
);
4329 srel
= smgropen(xlrec
->xnodes
[i
].rnode
);
4330 smgrdounlink(srel
, xlrec
->xnodes
[i
].forknum
, false, true);
4336 xact_redo(XLogRecPtr lsn
, XLogRecord
*record
)
4338 uint8 info
= record
->xl_info
& ~XLR_INFO_MASK
;
4340 if (info
== XLOG_XACT_COMMIT
)
4342 xl_xact_commit
*xlrec
= (xl_xact_commit
*) XLogRecGetData(record
);
4344 xact_redo_commit(xlrec
, record
->xl_xid
);
4346 else if (info
== XLOG_XACT_ABORT
)
4348 xl_xact_abort
*xlrec
= (xl_xact_abort
*) XLogRecGetData(record
);
4350 xact_redo_abort(xlrec
, record
->xl_xid
);
4352 else if (info
== XLOG_XACT_PREPARE
)
4354 /* the record contents are exactly the 2PC file */
4355 RecreateTwoPhaseFile(record
->xl_xid
,
4356 XLogRecGetData(record
), record
->xl_len
);
4358 else if (info
== XLOG_XACT_COMMIT_PREPARED
)
4360 xl_xact_commit_prepared
*xlrec
= (xl_xact_commit_prepared
*) XLogRecGetData(record
);
4362 xact_redo_commit(&xlrec
->crec
, xlrec
->xid
);
4363 RemoveTwoPhaseFile(xlrec
->xid
, false);
4365 else if (info
== XLOG_XACT_ABORT_PREPARED
)
4367 xl_xact_abort_prepared
*xlrec
= (xl_xact_abort_prepared
*) XLogRecGetData(record
);
4369 xact_redo_abort(&xlrec
->arec
, xlrec
->xid
);
4370 RemoveTwoPhaseFile(xlrec
->xid
, false);
4373 elog(PANIC
, "xact_redo: unknown op code %u", info
);
4377 xact_desc_commit(StringInfo buf
, xl_xact_commit
*xlrec
)
4381 appendStringInfoString(buf
, timestamptz_to_str(xlrec
->xact_time
));
4382 if (xlrec
->nrels
> 0)
4384 appendStringInfo(buf
, "; rels:");
4385 for (i
= 0; i
< xlrec
->nrels
; i
++)
4387 RelFileNode rnode
= xlrec
->xnodes
[i
].rnode
;
4388 ForkNumber forknum
= xlrec
->xnodes
[i
].forknum
;
4390 appendStringInfo(buf
, " %u/%u/%u/%u",
4391 rnode
.spcNode
, rnode
.dbNode
, rnode
.relNode
,
4395 if (xlrec
->nsubxacts
> 0)
4397 TransactionId
*xacts
= (TransactionId
*)
4398 &xlrec
->xnodes
[xlrec
->nrels
];
4400 appendStringInfo(buf
, "; subxacts:");
4401 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4402 appendStringInfo(buf
, " %u", xacts
[i
]);
4407 xact_desc_abort(StringInfo buf
, xl_xact_abort
*xlrec
)
4411 appendStringInfoString(buf
, timestamptz_to_str(xlrec
->xact_time
));
4412 if (xlrec
->nrels
> 0)
4414 appendStringInfo(buf
, "; rels:");
4415 for (i
= 0; i
< xlrec
->nrels
; i
++)
4417 RelFileNode rnode
= xlrec
->xnodes
[i
].rnode
;
4418 ForkNumber forknum
= xlrec
->xnodes
[i
].forknum
;
4420 appendStringInfo(buf
, " %u/%u/%u/%u",
4421 rnode
.spcNode
, rnode
.dbNode
, rnode
.relNode
,
4425 if (xlrec
->nsubxacts
> 0)
4427 TransactionId
*xacts
= (TransactionId
*)
4428 &xlrec
->xnodes
[xlrec
->nrels
];
4430 appendStringInfo(buf
, "; subxacts:");
4431 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4432 appendStringInfo(buf
, " %u", xacts
[i
]);
4437 xact_desc(StringInfo buf
, uint8 xl_info
, char *rec
)
4439 uint8 info
= xl_info
& ~XLR_INFO_MASK
;
4441 if (info
== XLOG_XACT_COMMIT
)
4443 xl_xact_commit
*xlrec
= (xl_xact_commit
*) rec
;
4445 appendStringInfo(buf
, "commit: ");
4446 xact_desc_commit(buf
, xlrec
);
4448 else if (info
== XLOG_XACT_ABORT
)
4450 xl_xact_abort
*xlrec
= (xl_xact_abort
*) rec
;
4452 appendStringInfo(buf
, "abort: ");
4453 xact_desc_abort(buf
, xlrec
);
4455 else if (info
== XLOG_XACT_PREPARE
)
4457 appendStringInfo(buf
, "prepare");
4459 else if (info
== XLOG_XACT_COMMIT_PREPARED
)
4461 xl_xact_commit_prepared
*xlrec
= (xl_xact_commit_prepared
*) rec
;
4463 appendStringInfo(buf
, "commit %u: ", xlrec
->xid
);
4464 xact_desc_commit(buf
, &xlrec
->crec
);
4466 else if (info
== XLOG_XACT_ABORT_PREPARED
)
4468 xl_xact_abort_prepared
*xlrec
= (xl_xact_abort_prepared
*) rec
;
4470 appendStringInfo(buf
, "abort %u: ", xlrec
->xid
);
4471 xact_desc_abort(buf
, &xlrec
->arec
);
4474 appendStringInfo(buf
, "UNKNOWN");