1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.164 2004/02/11 22:55:24 tgl Exp $
14 * Transaction aborts can now occur two ways:
16 * 1) system dies from some internal cause (syntax error, etc..)
19 * These two cases used to be treated identically, but now
20 * we need to distinguish them. Why? consider the following
25 * 1) user types BEGIN 1) user types BEGIN
26 * 2) user does something 2) user does something
27 * 3) user does not like what 3) system aborts for some reason
28 * she sees and types ABORT
30 * In case 1, we want to abort the transaction and return to the
31 * default state. In case 2, there may be more commands coming
32 * our way which are part of the same transaction block and we have
33 * to ignore these commands until we see a COMMIT transaction or
36 * Internal aborts are now handled by AbortTransactionBlock(), just as
37 * they always have been, and user aborts are now handled by
38 * UserAbortTransactionBlock(). Both of them rely on AbortTransaction()
39 * to do all the real work. The only difference is what state we
40 * enter after AbortTransaction() does its work:
42 * * AbortTransactionBlock() leaves us in TBLOCK_ABORT and
43 * * UserAbortTransactionBlock() leaves us in TBLOCK_ENDABORT
45 * Low-level transaction abort handling is divided into two phases:
46 * * AbortTransaction() executes as soon as we realize the transaction
47 * has failed. It should release all shared resources (locks etc)
48 * so that we do not delay other backends unnecessarily.
49 * * CleanupTransaction() executes when we finally see a user COMMIT
50 * or ROLLBACK command; it cleans things up and gets us out of
51 * the transaction internally. In particular, we mustn't destroy
52 * TopTransactionContext until this point.
55 * The essential aspects of the transaction system are:
57 * o transaction id generation
58 * o transaction log updating
60 * o cache invalidation
63 * Hence, the functional division of the transaction code is
64 * based on which of the above things need to be done during
65 * a start/commit/abort transaction. For instance, the
66 * routine AtCommit_Memory() takes care of all the memory
67 * cleanup stuff done at commit time.
69 * The code is layered as follows:
76 * are provided to do the lower level work like recording
77 * the transaction status in the log and doing memory cleanup.
78 * above these routines are another set of functions:
80 * StartTransactionCommand
81 * CommitTransactionCommand
82 * AbortCurrentTransaction
84 * These are the routines used in the postgres main processing
85 * loop. They are sensitive to the current transaction block state
86 * and make calls to the lower level routines appropriately.
88 * Support for transaction blocks is provided via the functions:
90 * BeginTransactionBlock
91 * CommitTransactionBlock
92 * AbortTransactionBlock
94 * These are invoked only in response to a user "BEGIN WORK", "COMMIT",
95 * or "ROLLBACK" command. The tricky part about these functions
96 * is that they are called within the postgres main loop, in between
97 * the StartTransactionCommand() and CommitTransactionCommand().
99 * For example, consider the following sequence of user commands:
102 * 2) select * from foo
103 * 3) insert into foo (bar = baz)
106 * in the main processing loop, this results in the following
107 * transaction sequence:
109 * / StartTransactionCommand();
110 * 1) / ProcessUtility(); << begin
111 * \ BeginTransactionBlock();
112 * \ CommitTransactionCommand();
114 * / StartTransactionCommand();
115 * 2) < ProcessQuery(); << select * from foo
116 * \ CommitTransactionCommand();
118 * / StartTransactionCommand();
119 * 3) < ProcessQuery(); << insert into foo (bar = baz)
120 * \ CommitTransactionCommand();
122 * / StartTransactionCommand();
123 * 4) / ProcessUtility(); << commit
124 * \ CommitTransactionBlock();
125 * \ CommitTransactionCommand();
127 * The point of this example is to demonstrate the need for
128 * StartTransactionCommand() and CommitTransactionCommand() to
129 * be state smart -- they should do nothing in between the calls
130 * to BeginTransactionBlock() and EndTransactionBlock() and
131 * outside these calls they need to do normal start/commit
134 * Furthermore, suppose the "select * from foo" caused an abort
135 * condition. We would then want to abort the transaction and
136 * ignore all subsequent commands up to the "commit".
139 *-------------------------------------------------------------------------
142 #include "postgres.h"
146 #include "access/gistscan.h"
147 #include "access/hash.h"
148 #include "access/nbtree.h"
149 #include "access/rtree.h"
150 #include "access/xact.h"
151 #include "catalog/heap.h"
152 #include "catalog/index.h"
153 #include "catalog/namespace.h"
154 #include "commands/async.h"
155 #include "commands/tablecmds.h"
156 #include "commands/trigger.h"
157 #include "commands/user.h"
158 #include "executor/spi.h"
159 #include "libpq/be-fsstubs.h"
160 #include "miscadmin.h"
161 #include "storage/fd.h"
162 #include "storage/proc.h"
163 #include "storage/sinval.h"
164 #include "storage/smgr.h"
165 #include "utils/guc.h"
166 #include "utils/inval.h"
167 #include "utils/memutils.h"
168 #include "utils/portal.h"
169 #include "utils/catcache.h"
170 #include "utils/relcache.h"
174 static void AbortTransaction(void);
175 static void AtAbort_Cache(void);
176 static void AtAbort_Locks(void);
177 static void AtAbort_Memory(void);
178 static void AtCleanup_Memory(void);
179 static void AtCommit_Cache(void);
180 static void AtCommit_LocalCache(void);
181 static void AtCommit_Locks(void);
182 static void AtCommit_Memory(void);
183 static void AtStart_Cache(void);
184 static void AtStart_Locks(void);
185 static void AtStart_Memory(void);
186 static void CallEOXactCallbacks(bool isCommit);
187 static void CleanupTransaction(void);
188 static void CommitTransaction(void);
189 static void RecordTransactionAbort(void);
190 static void StartTransaction(void);
193 * global variables holding the current transaction state.
195 static TransactionStateData CurrentTransactionStateData = {
196 0, /* transaction id */
197 FirstCommandId, /* command id */
198 0, /* scan command id */
199 0x0, /* start time */
200 TRANS_DEFAULT, /* transaction state */
201 TBLOCK_DEFAULT /* transaction block state from the client
205 static TransactionState CurrentTransactionState = &CurrentTransactionStateData;
208 * User-tweakable parameters
210 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
213 bool DefaultXactReadOnly = false;
216 int CommitDelay = 0; /* precommit delay in microseconds */
217 int CommitSiblings = 5; /* number of concurrent xacts needed to
222 * List of add-on end-of-xact callbacks
224 typedef struct EOXactCallbackItem
226 struct EOXactCallbackItem *next;
227 EOXactCallback callback;
229 } EOXactCallbackItem;
231 static EOXactCallbackItem *EOXact_callbacks = NULL;
233 static void (*_RollbackFunc) (void *) = NULL;
234 static void *_RollbackData = NULL;
237 /* ----------------------------------------------------------------
238 * transaction state accessors
239 * ----------------------------------------------------------------
244 /* --------------------------------
245 * TransactionFlushEnabled()
246 * SetTransactionFlushEnabled()
248 * These are used to test and set the "TransactionFlushState"
249 * variable. If this variable is true (the default), then
250 * the system will flush all dirty buffers to disk at the end
251 * of each transaction. If false then we are assuming the
252 * buffer pool resides in stable main memory, in which case we
253 * only do writes as necessary.
254 * --------------------------------
256 static int TransactionFlushState = 1;
259 TransactionFlushEnabled(void)
261 return TransactionFlushState;
265 SetTransactionFlushEnabled(bool state)
267 TransactionFlushState = (state == true);
275 * This returns true if we are currently running a query
276 * within an executing transaction.
279 IsTransactionState(void)
281 TransactionState s = CurrentTransactionState;
289 case TRANS_INPROGRESS:
298 * Shouldn't get here, but lint is not happy with this...
304 * IsAbortedTransactionBlockState
306 * This returns true if we are currently running a query
307 * within an aborted transaction block.
310 IsAbortedTransactionBlockState(void)
312 TransactionState s = CurrentTransactionState;
314 if (s->blockState == TBLOCK_ABORT)
322 * GetCurrentTransactionId
325 GetCurrentTransactionId(void)
327 TransactionState s = CurrentTransactionState;
329 return s->transactionIdData;
334 * GetCurrentCommandId
337 GetCurrentCommandId(void)
339 TransactionState s = CurrentTransactionState;
346 * GetCurrentTransactionStartTime
349 GetCurrentTransactionStartTime(void)
351 TransactionState s = CurrentTransactionState;
358 * GetCurrentTransactionStartTimeUsec
361 GetCurrentTransactionStartTimeUsec(int *msec)
363 TransactionState s = CurrentTransactionState;
365 *msec = s->startTimeUsec;
372 * TransactionIdIsCurrentTransactionId
374 * During bootstrap, we cheat and say "it's not my transaction ID" even though
375 * it is. Along with transam.c's cheat to say that the bootstrap XID is
376 * already committed, this causes the tqual.c routines to see previously
377 * inserted tuples as committed, which is what we need during bootstrap.
380 TransactionIdIsCurrentTransactionId(TransactionId xid)
382 TransactionState s = CurrentTransactionState;
386 Assert(xid == BootstrapTransactionId);
390 return TransactionIdEquals(xid, s->transactionIdData);
395 * CommandIdIsCurrentCommandId
398 CommandIdIsCurrentCommandId(CommandId cid)
400 TransactionState s = CurrentTransactionState;
402 return (cid == s->commandId);
407 * CommandCounterIncrement
410 CommandCounterIncrement(void)
412 TransactionState s = CurrentTransactionState;
415 if (s->commandId == FirstCommandId) /* check for overflow */
417 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
418 errmsg("cannot have more than 2^32-1 commands in a transaction")));
420 /* Propagate new command ID into query snapshots, if set */
422 QuerySnapshot->curcid = s->commandId;
423 if (SerializableSnapshot)
424 SerializableSnapshot->curcid = s->commandId;
427 * make cache changes visible to me. AtCommit_LocalCache() instead of
428 * AtCommit_Cache() is called here.
430 AtCommit_LocalCache();
435 /* ----------------------------------------------------------------
436 * StartTransaction stuff
437 * ----------------------------------------------------------------
446 AcceptInvalidationMessages();
456 * at present, it is unknown to me what belongs here -cim 3/18/90
458 * There isn't anything to do at the start of a xact for locks. -mer
470 * We shouldn't have a transaction context already.
472 Assert(TopTransactionContext == NULL);
475 * Create a toplevel context for the transaction, and make it active.
477 TopTransactionContext =
478 AllocSetContextCreate(TopMemoryContext,
479 "TopTransactionContext",
480 ALLOCSET_DEFAULT_MINSIZE,
481 ALLOCSET_DEFAULT_INITSIZE,
482 ALLOCSET_DEFAULT_MAXSIZE);
484 MemoryContextSwitchTo(TopTransactionContext);
488 /* ----------------------------------------------------------------
489 * CommitTransaction stuff
490 * ----------------------------------------------------------------
494 * RecordTransactionCommit
497 RecordTransactionCommit(void)
500 * If we made neither any XLOG entries nor any temp-rel updates, we
501 * can omit recording the transaction commit at all.
503 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)
505 TransactionId xid = GetCurrentTransactionId();
508 /* Tell bufmgr and smgr to prepare for commit */
511 START_CRIT_SECTION();
514 * We only need to log the commit in xlog if the transaction made
515 * any transaction-controlled XLOG entries. (Otherwise, its XID
516 * appears nowhere in permanent storage, so no one else will ever
517 * care if it committed.)
519 if (MyLastRecPtr.xrecoff != 0)
521 /* Need to emit a commit record */
522 XLogRecData rdata[2];
523 xl_xact_commit xlrec;
527 nrels = smgrGetPendingDeletes(true, &rptr);
529 xlrec.xtime = time(NULL);
530 rdata[0].buffer = InvalidBuffer;
531 rdata[0].data = (char *) (&xlrec);
532 rdata[0].len = MinSizeOfXactCommit;
535 rdata[0].next = &(rdata[1]);
536 rdata[1].buffer = InvalidBuffer;
537 rdata[1].data = (char *) rptr;
538 rdata[1].len = nrels * sizeof(RelFileNode);
539 rdata[1].next = NULL;
542 rdata[0].next = NULL;
544 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
551 /* Just flush through last record written by me */
552 recptr = ProcLastRecEnd;
556 * We must flush our XLOG entries to disk if we made any XLOG
557 * entries, whether in or out of transaction control. For
558 * example, if we reported a nextval() result to the client, this
559 * ensures that any XLOG record generated by nextval will hit the
560 * disk before we report the transaction committed.
562 if (MyXactMadeXLogEntry)
565 * Sleep before flush! So we can flush more than one commit
566 * records per single fsync. (The idea is some other backend
567 * may do the XLogFlush while we're sleeping. This needs work
568 * still, because on most Unixen, the minimum select() delay
569 * is 10msec or more, which is way too long.)
571 * We do not sleep if enableFsync is not turned on, nor if there
572 * are fewer than CommitSiblings other backends with active
575 if (CommitDelay > 0 && enableFsync &&
576 CountActiveBackends() >= CommitSiblings)
577 pg_usleep(CommitDelay);
583 * We must mark the transaction committed in clog if its XID
584 * appears either in permanent rels or in local temporary rels. We
585 * test this by seeing if we made transaction-controlled entries
586 * *OR* local-rel tuple updates. Note that if we made only the
587 * latter, we have not emitted an XLOG record for our commit, and
588 * so in the event of a crash the clog update might be lost. This
589 * is okay because no one else will ever care whether we
592 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
593 TransactionIdCommit(xid);
598 /* Break the chain of back-links in the XLOG records I output */
599 MyLastRecPtr.xrecoff = 0;
600 MyXactMadeXLogEntry = false;
601 MyXactMadeTempRelUpdate = false;
603 /* Show myself as out of the transaction in PGPROC array */
604 MyProc->logRec.xrecoff = 0;
615 * Clean up the relation cache.
617 AtEOXact_RelationCache(true);
620 * Make catalog changes visible to all backends.
622 AtEOXactInvalidationMessages(true);
626 * AtCommit_LocalCache
629 AtCommit_LocalCache(void)
632 * Make catalog changes visible to me for the next command.
634 CommandEndInvalidationMessages(true);
644 * XXX What if ProcReleaseLocks fails? (race condition?)
646 * Then you're up a creek! -mer 5/24/92
648 ProcReleaseLocks(true);
655 AtCommit_Memory(void)
658 * Now that we're "out" of a transaction, have the system allocate
659 * things in the top memory context instead of per-transaction
662 MemoryContextSwitchTo(TopMemoryContext);
665 * Release all transaction-local memory.
667 Assert(TopTransactionContext != NULL);
668 MemoryContextDelete(TopTransactionContext);
669 TopTransactionContext = NULL;
672 /* ----------------------------------------------------------------
673 * AbortTransaction stuff
674 * ----------------------------------------------------------------
678 * RecordTransactionAbort
681 RecordTransactionAbort(void)
684 * If we made neither any transaction-controlled XLOG entries nor any
685 * temp-rel updates, we can omit recording the transaction abort at
686 * all. No one will ever care that it aborted.
688 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
690 TransactionId xid = GetCurrentTransactionId();
693 * Catch the scenario where we aborted partway through
694 * RecordTransactionCommit ...
696 if (TransactionIdDidCommit(xid))
697 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
699 START_CRIT_SECTION();
702 * We only need to log the abort in XLOG if the transaction made
703 * any transaction-controlled XLOG entries. (Otherwise, its XID
704 * appears nowhere in permanent storage, so no one else will ever
705 * care if it committed.) We do not flush XLOG to disk unless
706 * deleting files, since the default assumption after a crash
707 * would be that we aborted, anyway.
709 if (MyLastRecPtr.xrecoff != 0)
711 XLogRecData rdata[2];
717 nrels = smgrGetPendingDeletes(false, &rptr);
719 xlrec.xtime = time(NULL);
720 rdata[0].buffer = InvalidBuffer;
721 rdata[0].data = (char *) (&xlrec);
722 rdata[0].len = MinSizeOfXactAbort;
725 rdata[0].next = &(rdata[1]);
726 rdata[1].buffer = InvalidBuffer;
727 rdata[1].data = (char *) rptr;
728 rdata[1].len = nrels * sizeof(RelFileNode);
729 rdata[1].next = NULL;
732 rdata[0].next = NULL;
734 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
744 * Mark the transaction aborted in clog. This is not absolutely
745 * necessary but we may as well do it while we are here.
747 TransactionIdAbort(xid);
752 /* Break the chain of back-links in the XLOG records I output */
753 MyLastRecPtr.xrecoff = 0;
754 MyXactMadeXLogEntry = false;
755 MyXactMadeTempRelUpdate = false;
757 /* Show myself as out of the transaction in PGPROC array */
758 MyProc->logRec.xrecoff = 0;
767 AtEOXact_RelationCache(false);
768 AtEOXactInvalidationMessages(false);
778 * XXX What if ProcReleaseLocks() fails? (race condition?)
780 * Then you're up a creek without a paddle! -mer
782 ProcReleaseLocks(false);
793 * Make sure we are in a valid context (not a child of
794 * TopTransactionContext...). Note that it is possible for this code
795 * to be called when we aren't in a transaction at all; go directly to
796 * TopMemoryContext in that case.
798 if (TopTransactionContext != NULL)
800 MemoryContextSwitchTo(TopTransactionContext);
803 * We do not want to destroy the transaction's global state yet,
804 * so we can't free any memory here.
808 MemoryContextSwitchTo(TopMemoryContext);
812 /* ----------------------------------------------------------------
813 * CleanupTransaction stuff
814 * ----------------------------------------------------------------
821 AtCleanup_Memory(void)
824 * Now that we're "out" of a transaction, have the system allocate
825 * things in the top memory context instead of per-transaction
828 MemoryContextSwitchTo(TopMemoryContext);
831 * Release all transaction-local memory.
833 if (TopTransactionContext != NULL)
834 MemoryContextDelete(TopTransactionContext);
835 TopTransactionContext = NULL;
839 /* ----------------------------------------------------------------
841 * ----------------------------------------------------------------
848 StartTransaction(void)
850 TransactionState s = CurrentTransactionState;
853 * check the current transaction state
855 if (s->state != TRANS_DEFAULT)
856 elog(WARNING, "StartTransaction and not in default state");
859 * set the current transaction state information appropriately during
862 s->state = TRANS_START;
865 * Make sure we've freed any old snapshot, and reset xact state variables
868 XactIsoLevel = DefaultXactIsoLevel;
869 XactReadOnly = DefaultXactReadOnly;
872 * generate a new transaction id
874 s->transactionIdData = GetNewTransactionId();
876 XactLockTableInsert(s->transactionIdData);
879 * initialize current transaction state fields
881 s->commandId = FirstCommandId;
882 s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
885 * initialize the various transaction subsystems
892 * Tell the trigger manager we're starting a transaction
894 DeferredTriggerBeginXact();
897 * done with start processing, set current transaction state to "in
900 s->state = TRANS_INPROGRESS;
908 CommitTransaction(void)
910 TransactionState s = CurrentTransactionState;
913 * check the current transaction state
915 if (s->state != TRANS_INPROGRESS)
916 elog(WARNING, "CommitTransaction and not in in-progress state");
919 * Tell the trigger manager that this transaction is about to be
920 * committed. He'll invoke all trigger deferred until XACT before we
921 * really start on committing the transaction.
923 DeferredTriggerEndXact();
926 * Similarly, let ON COMMIT management do its thing before we start to
929 PreCommit_on_commit_actions();
931 /* Prevent cancel/die interrupt while cleaning up */
935 * set the current transaction state information appropriately during
936 * the abort processing
938 s->state = TRANS_COMMIT;
941 * Do pre-commit processing (most of this stuff requires database
942 * access, and in fact could still cause an error...)
947 /* handle commit for large objects [ PA, 7/17/98 ] */
948 /* XXX probably this does not belong here */
951 /* NOTIFY commit must come before lower-level cleanup */
954 /* Update the flat password file if we changed pg_shadow or pg_group */
955 AtEOXact_UpdatePasswordFile(true);
958 * Here is where we really truly commit.
960 RecordTransactionCommit();
963 * Let others know about no transaction in progress by me. Note that
964 * this must be done _before_ releasing locks we hold and _after_
965 * RecordTransactionCommit.
967 * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
968 * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
969 * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
970 * as running as well or it will see two tuple versions - one deleted
971 * by xid 1 and one inserted by xid 0. See notes in GetSnapshotData.
975 /* Lock SInvalLock because that's what GetSnapshotData uses. */
976 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
977 MyProc->xid = InvalidTransactionId;
978 MyProc->xmin = InvalidTransactionId;
979 LWLockRelease(SInvalLock);
983 * This is all post-commit cleanup. Note that if an error is raised
984 * here, it's too late to abort the transaction. This should be just
985 * noncritical resource releasing.
987 * The ordering of operations is not entirely random. The idea is:
988 * release resources visible to other backends (eg, files, buffer
989 * pins); then release locks; then release backend-local resources. We
990 * want to release locks at the point where any backend waiting for us
991 * will see our transaction as being fully cleaned up.
994 smgrDoPendingDeletes(true);
996 AtEOXact_Buffers(true);
997 /* smgrcommit already done */
1001 CallEOXactCallbacks(true);
1008 AtEOXact_on_commit_actions(true);
1009 AtEOXact_Namespace(true);
1010 AtEOXact_CatCache(true);
1012 pgstat_count_xact_commit();
1016 * done with commit processing, set current transaction state back to
1019 s->state = TRANS_DEFAULT;
1021 RESUME_INTERRUPTS();
1028 AbortTransaction(void)
1030 TransactionState s = CurrentTransactionState;
1032 /* Prevent cancel/die interrupt while cleaning up */
1036 * Release any LW locks we might be holding as quickly as possible.
1037 * (Regular locks, however, must be held till we finish aborting.)
1038 * Releasing LW locks is critical since we might try to grab them
1039 * again while cleaning up!
1043 /* Clean up buffer I/O and buffer context locks, too */
1048 * Also clean up any open wait for lock, since the lock manager will
1049 * choke if we try to wait for another lock before doing this.
1054 * check the current transaction state
1056 if (s->state != TRANS_INPROGRESS)
1057 elog(WARNING, "AbortTransaction and not in in-progress state");
1060 * set the current transaction state information appropriately during
1061 * the abort processing
1063 s->state = TRANS_ABORT;
1065 /* Make sure we are in a valid memory context */
1069 * Reset user id which might have been changed transiently
1071 SetUserId(GetSessionUserId());
1074 * do abort processing
1076 DeferredTriggerAbortXact();
1078 lo_commit(false); /* 'false' means it's abort */
1080 AtEOXact_UpdatePasswordFile(false);
1082 /* Advertise the fact that we aborted in pg_clog. */
1083 RecordTransactionAbort();
1086 * Let others know about no transaction in progress by me. Note that
1087 * this must be done _before_ releasing locks we hold and _after_
1088 * RecordTransactionAbort.
1092 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1093 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1094 MyProc->xid = InvalidTransactionId;
1095 MyProc->xmin = InvalidTransactionId;
1096 LWLockRelease(SInvalLock);
1100 * Post-abort cleanup. See notes in CommitTransaction() concerning
1104 smgrDoPendingDeletes(false);
1106 AtEOXact_Buffers(false);
1111 CallEOXactCallbacks(false);
1112 AtEOXact_GUC(false);
1113 AtEOXact_SPI(false);
1118 AtEOXact_on_commit_actions(false);
1119 AtEOXact_Namespace(false);
1120 AtEOXact_CatCache(false);
1122 SetReindexProcessing(InvalidOid, InvalidOid);
1123 pgstat_count_xact_rollback();
1126 * State remains TRANS_ABORT until CleanupTransaction().
1128 RESUME_INTERRUPTS();
1132 * CleanupTransaction
1135 CleanupTransaction(void)
1137 TransactionState s = CurrentTransactionState;
1140 * State should still be TRANS_ABORT from AbortTransaction().
1142 if (s->state != TRANS_ABORT)
1143 elog(FATAL, "CleanupTransaction and not in abort state");
1146 * do abort cleanup processing
1148 AtCleanup_Portals(); /* now safe to release portal memory */
1149 AtCleanup_Memory(); /* and transaction memory */
1152 * done with abort processing, set current transaction state back to
1155 s->state = TRANS_DEFAULT;
1159 * StartTransactionCommand
1162 StartTransactionCommand(void)
1164 TransactionState s = CurrentTransactionState;
1166 switch (s->blockState)
1169 * if we aren't in a transaction block, we just do our usual
1170 * start transaction.
1172 case TBLOCK_DEFAULT:
1177 * We should never experience this -- if we do it means the
1178 * BEGIN state was not changed in the previous
1179 * CommitTransactionCommand(). If we get it, we print a
1180 * warning and change to the in-progress state.
1183 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_BEGIN");
1184 s->blockState = TBLOCK_INPROGRESS;
1188 * This is the case when are somewhere in a transaction block
1189 * and about to start a new command. For now we do nothing
1190 * but someday we may do command-local resource
1193 case TBLOCK_INPROGRESS:
1197 * As with BEGIN, we should never experience this if we do it
1198 * means the END state was not changed in the previous
1199 * CommitTransactionCommand(). If we get it, we print a
1200 * warning, commit the transaction, start a new transaction
1201 * and change to the default state.
1204 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_END");
1205 s->blockState = TBLOCK_DEFAULT;
1206 CommitTransaction();
1211 * Here we are in the middle of a transaction block but one of
1212 * the commands caused an abort so we do nothing but remain in
1213 * the abort state. Eventually we will get to the "END
1214 * TRANSACTION" which will set things straight.
1220 * This means we somehow aborted and the last call to
1221 * CommitTransactionCommand() didn't clear the state so we
1222 * remain in the ENDABORT state and maybe next time we get to
1223 * CommitTransactionCommand() the state will get reset to
1226 case TBLOCK_ENDABORT:
1227 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");
1232 * We must switch to TopTransactionContext before returning. This is
1233 * already done if we called StartTransaction, otherwise not.
1235 Assert(TopTransactionContext != NULL);
1236 MemoryContextSwitchTo(TopTransactionContext);
1240 * CommitTransactionCommand
1243 CommitTransactionCommand(void)
1245 TransactionState s = CurrentTransactionState;
1247 switch (s->blockState)
1250 * If we aren't in a transaction block, just do our usual
1251 * transaction commit.
1253 case TBLOCK_DEFAULT:
1254 CommitTransaction();
1258 * This is the case right after we get a "BEGIN TRANSACTION"
1259 * command, but the user hasn't done anything else yet, so we
1260 * change to the "transaction block in progress" state and
1264 s->blockState = TBLOCK_INPROGRESS;
1268 * This is the case when we have finished executing a command
1269 * someplace within a transaction block. We increment the
1270 * command counter and return.
1272 case TBLOCK_INPROGRESS:
1273 CommandCounterIncrement();
1277 * This is the case when we just got the "END TRANSACTION"
1278 * statement, so we commit the transaction and go back to the
1282 CommitTransaction();
1283 s->blockState = TBLOCK_DEFAULT;
1287 * Here we are in the middle of a transaction block but one of
1288 * the commands caused an abort so we do nothing but remain in
1289 * the abort state. Eventually we will get to the "END
1290 * TRANSACTION" which will set things straight.
1296 * Here we were in an aborted transaction block which just
1297 * processed the "END TRANSACTION" command from the user, so
1298 * clean up and return to the default state.
1300 case TBLOCK_ENDABORT:
1301 CleanupTransaction();
1302 s->blockState = TBLOCK_DEFAULT;
1308 * AbortCurrentTransaction
1311 AbortCurrentTransaction(void)
1313 TransactionState s = CurrentTransactionState;
1315 switch (s->blockState)
1318 * if we aren't in a transaction block, we just do the basic
1319 * abort & cleanup transaction.
1321 case TBLOCK_DEFAULT:
1323 CleanupTransaction();
1327 * If we are in the TBLOCK_BEGIN it means something screwed up
1328 * right after reading "BEGIN TRANSACTION" so we enter the
1329 * abort state. Eventually an "END TRANSACTION" will fix
1333 s->blockState = TBLOCK_ABORT;
1335 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1339 * This is the case when are somewhere in a transaction block
1340 * which aborted so we abort the transaction and set the ABORT
1341 * state. Eventually an "END TRANSACTION" will fix things and
1342 * restore us to a normal state.
1344 case TBLOCK_INPROGRESS:
1345 s->blockState = TBLOCK_ABORT;
1347 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1351 * Here, the system was fouled up just after the user wanted
1352 * to end the transaction block so we abort the transaction
1353 * and put us back into the default state.
1356 s->blockState = TBLOCK_DEFAULT;
1358 CleanupTransaction();
1362 * Here, we are already in an aborted transaction state and
1363 * are waiting for an "END TRANSACTION" to come along and lo
1364 * and behold, we abort again! So we just remain in the abort
1371 * Here we were in an aborted transaction block which just
1372 * processed the "END TRANSACTION" command but somehow aborted
1373 * again.. since we must have done the abort processing, we
1374 * clean up and return to the default state.
1376 case TBLOCK_ENDABORT:
1377 CleanupTransaction();
1378 s->blockState = TBLOCK_DEFAULT;
1384 * PreventTransactionChain
1386 * This routine is to be called by statements that must not run inside
1387 * a transaction block, typically because they have non-rollback-able
1388 * side effects or do internal commits.
1390 * If we have already started a transaction block, issue an error; also issue
1391 * an error if we appear to be running inside a user-defined function (which
1392 * could issue more commands and possibly cause a failure after the statement
1395 * stmtNode: pointer to parameter block for statement; this is used in
1396 * a very klugy way to determine whether we are inside a function.
1397 * stmtType: statement type name for error messages.
1400 PreventTransactionChain(void *stmtNode, const char *stmtType)
1403 * xact block already started?
1405 if (IsTransactionBlock())
1407 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1408 /* translator: %s represents an SQL statement name */
1409 errmsg("%s cannot run inside a transaction block",
1413 * Are we inside a function call? If the statement's parameter block
1414 * was allocated in QueryContext, assume it is an interactive command.
1415 * Otherwise assume it is coming from a function.
1417 if (!MemoryContextContains(QueryContext, stmtNode))
1419 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1420 /* translator: %s represents an SQL statement name */
1421 errmsg("%s cannot be executed from a function", stmtType)));
1422 /* If we got past IsTransactionBlock test, should be in default state */
1423 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)
1424 elog(ERROR, "cannot prevent transaction chain");
1429 * RequireTransactionChain
1431 * This routine is to be called by statements that must run inside
1432 * a transaction block, because they have no effects that persist past
1433 * transaction end (and so calling them outside a transaction block
1434 * is presumably an error). DECLARE CURSOR is an example.
1436 * If we appear to be running inside a user-defined function, we do not
1437 * issue an error, since the function could issue more commands that make
1438 * use of the current statement's results. Thus this is an inverse for
1439 * PreventTransactionChain.
1441 * stmtNode: pointer to parameter block for statement; this is used in
1442 * a very klugy way to determine whether we are inside a function.
1443 * stmtType: statement type name for error messages.
1446 RequireTransactionChain(void *stmtNode, const char *stmtType)
1449 * xact block already started?
1451 if (IsTransactionBlock())
1455 * Are we inside a function call? If the statement's parameter block
1456 * was allocated in QueryContext, assume it is an interactive command.
1457 * Otherwise assume it is coming from a function.
1459 if (!MemoryContextContains(QueryContext, stmtNode))
1462 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1463 /* translator: %s represents an SQL statement name */
1464 errmsg("%s may only be used in transaction blocks",
1470 * Register or deregister callback functions for end-of-xact cleanup
1472 * These functions are intended for use by dynamically loaded modules.
1473 * For built-in modules we generally just hardwire the appropriate calls
1474 * (mainly because it's easier to control the order that way, where needed).
1476 * Note that the callback occurs post-commit or post-abort, so the callback
1477 * functions can only do noncritical cleanup.
1480 RegisterEOXactCallback(EOXactCallback callback, void *arg)
1482 EOXactCallbackItem *item;
1484 item = (EOXactCallbackItem *)
1485 MemoryContextAlloc(TopMemoryContext, sizeof(EOXactCallbackItem));
1486 item->callback = callback;
1488 item->next = EOXact_callbacks;
1489 EOXact_callbacks = item;
1493 UnregisterEOXactCallback(EOXactCallback callback, void *arg)
1495 EOXactCallbackItem *item;
1496 EOXactCallbackItem *prev;
1499 for (item = EOXact_callbacks; item; prev = item, item = item->next)
1501 if (item->callback == callback && item->arg == arg)
1504 prev->next = item->next;
1506 EOXact_callbacks = item->next;
1514 CallEOXactCallbacks(bool isCommit)
1516 EOXactCallbackItem *item;
1518 for (item = EOXact_callbacks; item; item = item->next)
1520 (*item->callback) (isCommit, item->arg);
1525 /* ----------------------------------------------------------------
1526 * transaction block support
1527 * ----------------------------------------------------------------
1530 * BeginTransactionBlock
1533 BeginTransactionBlock(void)
1535 TransactionState s = CurrentTransactionState;
1538 * check the current transaction state
1540 if (s->blockState != TBLOCK_DEFAULT)
1542 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1543 errmsg("there is already a transaction in progress")));
1546 * set the current transaction block state information appropriately
1547 * during begin processing
1549 s->blockState = TBLOCK_BEGIN;
1552 * do begin processing here. Nothing to do at present.
1556 * done with begin processing, set block state to inprogress
1558 s->blockState = TBLOCK_INPROGRESS;
1562 * EndTransactionBlock
1565 EndTransactionBlock(void)
1567 TransactionState s = CurrentTransactionState;
1570 * check the current transaction state
1572 if (s->blockState == TBLOCK_INPROGRESS)
1575 * here we are in a transaction block which should commit when we
1576 * get to the upcoming CommitTransactionCommand() so we set the
1577 * state to "END". CommitTransactionCommand() will recognize this
1578 * and commit the transaction and return us to the default state
1580 s->blockState = TBLOCK_END;
1584 if (s->blockState == TBLOCK_ABORT)
1587 * here, we are in a transaction block which aborted and since the
1588 * AbortTransaction() was already done, we do whatever is needed
1589 * and change to the special "END ABORT" state. The upcoming
1590 * CommitTransactionCommand() will recognise this and then put us
1591 * back in the default state.
1593 s->blockState = TBLOCK_ENDABORT;
1598 * here, the user issued COMMIT when not inside a transaction. Issue a
1599 * WARNING and go to abort state. The upcoming call to
1600 * CommitTransactionCommand() will then put us back into the default
1604 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1605 errmsg("there is no transaction in progress")));
1607 s->blockState = TBLOCK_ENDABORT;
1611 * AbortTransactionBlock
1615 AbortTransactionBlock(void)
1617 TransactionState s = CurrentTransactionState;
1620 * check the current transaction state
1622 if (s->blockState == TBLOCK_INPROGRESS)
1625 * here we were inside a transaction block something screwed up
1626 * inside the system so we enter the abort state, do the abort
1627 * processing and then return. We remain in the abort state until
1628 * we see an END TRANSACTION command.
1630 s->blockState = TBLOCK_ABORT;
1636 * here, the user issued ABORT when not inside a transaction. Issue a
1637 * WARNING and go to abort state. The upcoming call to
1638 * CommitTransactionCommand() will then put us back into the default
1642 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1643 errmsg("there is no transaction in progress")));
1645 s->blockState = TBLOCK_ENDABORT;
1650 * UserAbortTransactionBlock
1653 UserAbortTransactionBlock(void)
1655 TransactionState s = CurrentTransactionState;
1658 * if the transaction has already been automatically aborted with an
1659 * error, and the user subsequently types 'abort', allow it. (the
1660 * behavior is the same as if they had typed 'end'.)
1662 if (s->blockState == TBLOCK_ABORT)
1664 s->blockState = TBLOCK_ENDABORT;
1668 if (s->blockState == TBLOCK_INPROGRESS)
1671 * here we were inside a transaction block and we got an abort
1672 * command from the user, so we move to the abort state, do the
1673 * abort processing and then change to the ENDABORT state so we
1674 * will end up in the default state after the upcoming
1675 * CommitTransactionCommand().
1677 s->blockState = TBLOCK_ABORT;
1679 s->blockState = TBLOCK_ENDABORT;
1684 * here, the user issued ABORT when not inside a transaction. Issue a
1685 * WARNING and go to abort state. The upcoming call to
1686 * CommitTransactionCommand() will then put us back into the default
1690 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
1691 errmsg("there is no transaction in progress")));
1693 s->blockState = TBLOCK_ENDABORT;
1697 * AbortOutOfAnyTransaction
1699 * This routine is provided for error recovery purposes. It aborts any
1700 * active transaction or transaction block, leaving the system in a known
1704 AbortOutOfAnyTransaction(void)
1706 TransactionState s = CurrentTransactionState;
1709 * Get out of any low-level transaction
1714 case TRANS_INPROGRESS:
1716 /* In a transaction, so clean up */
1718 CleanupTransaction();
1721 /* AbortTransaction already done, still need Cleanup */
1722 CleanupTransaction();
1725 /* Not in a transaction, do nothing */
1730 * Now reset the high-level state
1732 s->blockState = TBLOCK_DEFAULT;
1736 * IsTransactionBlock --- are we within a transaction block?
1739 IsTransactionBlock(void)
1741 TransactionState s = CurrentTransactionState;
1743 if (s->blockState == TBLOCK_DEFAULT)
1750 * IsTransactionOrTransactionBlock --- are we within either a transaction
1751 * or a transaction block? (The backend is only really "idle" when this
1754 * This should match up with IsTransactionBlock and IsTransactionState.
1757 IsTransactionOrTransactionBlock(void)
1759 TransactionState s = CurrentTransactionState;
1761 if (s->blockState == TBLOCK_DEFAULT && s->state == TRANS_DEFAULT)
1768 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
1771 TransactionBlockStatusCode(void)
1773 TransactionState s = CurrentTransactionState;
1775 switch (s->blockState)
1777 case TBLOCK_DEFAULT:
1778 return 'I'; /* idle --- not in transaction */
1780 case TBLOCK_INPROGRESS:
1782 return 'T'; /* in transaction */
1784 case TBLOCK_ENDABORT:
1785 return 'E'; /* in failed transaction */
1788 /* should never get here */
1789 elog(ERROR, "invalid transaction block state: %d",
1790 (int) s->blockState);
1791 return 0; /* keep compiler quiet */
1796 * XLOG support routines
1800 xact_redo(XLogRecPtr lsn, XLogRecord *record)
1802 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1804 if (info == XLOG_XACT_COMMIT)
1806 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
1810 TransactionIdCommit(record->xl_xid);
1811 /* Make sure files supposed to be dropped are dropped */
1812 nfiles = (record->xl_len - MinSizeOfXactCommit) / sizeof(RelFileNode);
1813 for (i = 0; i < nfiles; i++)
1815 XLogCloseRelation(xlrec->xnodes[i]);
1816 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
1819 else if (info == XLOG_XACT_ABORT)
1821 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
1825 TransactionIdAbort(record->xl_xid);
1826 /* Make sure files supposed to be dropped are dropped */
1827 nfiles = (record->xl_len - MinSizeOfXactAbort) / sizeof(RelFileNode);
1828 for (i = 0; i < nfiles; i++)
1830 XLogCloseRelation(xlrec->xnodes[i]);
1831 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
1835 elog(PANIC, "xact_redo: unknown op code %u", info);
1839 xact_undo(XLogRecPtr lsn, XLogRecord *record)
1841 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1843 if (info == XLOG_XACT_COMMIT) /* shouldn't be called by XLOG */
1844 elog(PANIC, "xact_undo: can't undo committed xaction");
1845 else if (info != XLOG_XACT_ABORT)
1846 elog(PANIC, "xact_redo: unknown op code %u", info);
1850 xact_desc(char *buf, uint8 xl_info, char *rec)
1852 uint8 info = xl_info & ~XLR_INFO_MASK;
1854 if (info == XLOG_XACT_COMMIT)
1856 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
1857 struct tm *tm = localtime(&xlrec->xtime);
1859 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
1860 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1861 tm->tm_hour, tm->tm_min, tm->tm_sec);
1862 /* XXX can't show RelFileNodes for lack of access to record length */
1864 else if (info == XLOG_XACT_ABORT)
1866 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
1867 struct tm *tm = localtime(&xlrec->xtime);
1869 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
1870 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1871 tm->tm_hour, tm->tm_min, tm->tm_sec);
1872 /* XXX can't show RelFileNodes for lack of access to record length */
1875 strcat(buf, "UNKNOWN");
1879 XactPushRollback(void (*func) (void *), void *data)
1882 if (_RollbackFunc != NULL)
1883 elog(PANIC, "XactPushRollback: already installed");
1886 _RollbackFunc = func;
1887 _RollbackData = data;
1891 XactPopRollback(void)
1893 _RollbackFunc = NULL;