1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.143 2003/03/14 22:40:31 momjian 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 * TransactionCommandContext 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 * StartTransactionBlock
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 * \ StartTransactionBlock();
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 StartTransactionBlock() 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"
145 #include <sys/time.h>
147 #include "access/gistscan.h"
148 #include "access/hash.h"
149 #include "access/nbtree.h"
150 #include "access/rtree.h"
151 #include "access/xact.h"
152 #include "catalog/heap.h"
153 #include "catalog/index.h"
154 #include "catalog/namespace.h"
155 #include "commands/async.h"
156 #include "commands/tablecmds.h"
157 #include "commands/trigger.h"
158 #include "commands/user.h"
159 #include "executor/spi.h"
160 #include "libpq/be-fsstubs.h"
161 #include "miscadmin.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 CleanupTransaction(void);
187 static void CommitTransaction(void);
188 static void RecordTransactionAbort(void);
189 static void StartTransaction(void);
192 * global variables holding the current transaction state.
194 static TransactionStateData CurrentTransactionStateData = {
195 0, /* transaction id */
196 FirstCommandId, /* command id */
197 0, /* scan command id */
198 0x0, /* start time */
199 TRANS_DEFAULT, /* transaction state */
200 TBLOCK_DEFAULT /* transaction block state from
201 the client perspective */
204 TransactionState CurrentTransactionState = &CurrentTransactionStateData;
207 * User-tweakable parameters
209 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
212 bool DefaultXactReadOnly = false;
215 bool autocommit = true;
217 int CommitDelay = 0; /* precommit delay in microseconds */
218 int CommitSiblings = 5; /* number of concurrent xacts needed to
222 static bool suppressChain = false;
224 static void (*_RollbackFunc) (void *) = NULL;
225 static void *_RollbackData = NULL;
228 /* ----------------------------------------------------------------
229 * transaction state accessors
230 * ----------------------------------------------------------------
235 /* --------------------------------
236 * TransactionFlushEnabled()
237 * SetTransactionFlushEnabled()
239 * These are used to test and set the "TransactionFlushState"
240 * variable. If this variable is true (the default), then
241 * the system will flush all dirty buffers to disk at the end
242 * of each transaction. If false then we are assuming the
243 * buffer pool resides in stable main memory, in which case we
244 * only do writes as necessary.
245 * --------------------------------
247 static int TransactionFlushState = 1;
250 TransactionFlushEnabled(void)
252 return TransactionFlushState;
256 SetTransactionFlushEnabled(bool state)
258 TransactionFlushState = (state == true);
266 * This returns true if we are currently running a query
267 * within an executing transaction.
270 IsTransactionState(void)
272 TransactionState s = CurrentTransactionState;
280 case TRANS_INPROGRESS:
289 * Shouldn't get here, but lint is not happy with this...
295 * IsAbortedTransactionBlockState
297 * This returns true if we are currently running a query
298 * within an aborted transaction block.
301 IsAbortedTransactionBlockState(void)
303 TransactionState s = CurrentTransactionState;
305 if (s->blockState == TBLOCK_ABORT)
313 * GetCurrentTransactionId
316 GetCurrentTransactionId(void)
318 TransactionState s = CurrentTransactionState;
320 return s->transactionIdData;
325 * GetCurrentCommandId
328 GetCurrentCommandId(void)
330 TransactionState s = CurrentTransactionState;
337 * GetCurrentTransactionStartTime
340 GetCurrentTransactionStartTime(void)
342 TransactionState s = CurrentTransactionState;
349 * GetCurrentTransactionStartTimeUsec
352 GetCurrentTransactionStartTimeUsec(int *msec)
354 TransactionState s = CurrentTransactionState;
356 *msec = s->startTimeUsec;
363 * TransactionIdIsCurrentTransactionId
365 * During bootstrap, we cheat and say "it's not my transaction ID" even though
366 * it is. Along with transam.c's cheat to say that the bootstrap XID is
367 * already committed, this causes the tqual.c routines to see previously
368 * inserted tuples as committed, which is what we need during bootstrap.
371 TransactionIdIsCurrentTransactionId(TransactionId xid)
373 TransactionState s = CurrentTransactionState;
377 Assert(xid == BootstrapTransactionId);
381 return TransactionIdEquals(xid, s->transactionIdData);
386 * CommandIdIsCurrentCommandId
389 CommandIdIsCurrentCommandId(CommandId cid)
391 TransactionState s = CurrentTransactionState;
393 return (cid == s->commandId) ? true : false;
398 * CommandCounterIncrement
401 CommandCounterIncrement(void)
403 TransactionState s = CurrentTransactionState;
406 if (s->commandId == FirstCommandId) /* check for overflow */
407 elog(ERROR, "You may only have 2^32-1 commands per transaction");
409 /* Propagate new command ID into query snapshots, if set */
411 QuerySnapshot->curcid = s->commandId;
412 if (SerializableSnapshot)
413 SerializableSnapshot->curcid = s->commandId;
416 * make cache changes visible to me. AtCommit_LocalCache() instead of
417 * AtCommit_Cache() is called here.
419 AtCommit_LocalCache();
424 /* ----------------------------------------------------------------
425 * StartTransaction stuff
426 * ----------------------------------------------------------------
435 AcceptInvalidationMessages();
445 * at present, it is unknown to me what belongs here -cim 3/18/90
447 * There isn't anything to do at the start of a xact for locks. -mer
459 * We shouldn't have any transaction contexts already.
461 Assert(TopTransactionContext == NULL);
462 Assert(TransactionCommandContext == NULL);
465 * Create a toplevel context for the transaction.
467 TopTransactionContext =
468 AllocSetContextCreate(TopMemoryContext,
469 "TopTransactionContext",
470 ALLOCSET_DEFAULT_MINSIZE,
471 ALLOCSET_DEFAULT_INITSIZE,
472 ALLOCSET_DEFAULT_MAXSIZE);
475 * Create a statement-level context and make it active.
477 TransactionCommandContext =
478 AllocSetContextCreate(TopTransactionContext,
479 "TransactionCommandContext",
480 ALLOCSET_DEFAULT_MINSIZE,
481 ALLOCSET_DEFAULT_INITSIZE,
482 ALLOCSET_DEFAULT_MAXSIZE);
483 MemoryContextSwitchTo(TransactionCommandContext);
487 /* ----------------------------------------------------------------
488 * CommitTransaction stuff
489 * ----------------------------------------------------------------
493 * RecordTransactionCommit
496 RecordTransactionCommit(void)
499 * If we made neither any XLOG entries nor any temp-rel updates, we
500 * can omit recording the transaction commit at all.
502 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)
504 TransactionId xid = GetCurrentTransactionId();
507 /* Tell bufmgr and smgr to prepare for commit */
510 START_CRIT_SECTION();
513 * We only need to log the commit in xlog if the transaction made
514 * any transaction-controlled XLOG entries. (Otherwise, its XID
515 * appears nowhere in permanent storage, so no one else will ever
516 * care if it committed.)
518 if (MyLastRecPtr.xrecoff != 0)
520 /* Need to emit a commit record */
522 xl_xact_commit xlrec;
524 xlrec.xtime = time(NULL);
525 rdata.buffer = InvalidBuffer;
526 rdata.data = (char *) (&xlrec);
527 rdata.len = SizeOfXactCommit;
531 * XXX SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
533 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
537 /* Just flush through last record written by me */
538 recptr = ProcLastRecEnd;
542 * We must flush our XLOG entries to disk if we made any XLOG
543 * entries, whether in or out of transaction control. For
544 * example, if we reported a nextval() result to the client, this
545 * ensures that any XLOG record generated by nextval will hit the
546 * disk before we report the transaction committed.
548 if (MyXactMadeXLogEntry)
551 * Sleep before flush! So we can flush more than one commit
552 * records per single fsync. (The idea is some other backend
553 * may do the XLogFlush while we're sleeping. This needs work
554 * still, because on most Unixen, the minimum select() delay
555 * is 10msec or more, which is way too long.)
557 * We do not sleep if enableFsync is not turned on, nor if there
558 * are fewer than CommitSiblings other backends with active
561 if (CommitDelay > 0 && enableFsync &&
562 CountActiveBackends() >= CommitSiblings)
564 struct timeval delay;
567 delay.tv_usec = CommitDelay;
568 (void) select(0, NULL, NULL, NULL, &delay);
575 * We must mark the transaction committed in clog if its XID
576 * appears either in permanent rels or in local temporary rels.
577 * We test this by seeing if we made transaction-controlled
578 * entries *OR* local-rel tuple updates. Note that if we made
579 * only the latter, we have not emitted an XLOG record for our
580 * commit, and so in the event of a crash the clog update might be
581 * lost. This is okay because no one else will ever care whether
584 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
585 TransactionIdCommit(xid);
590 /* Break the chain of back-links in the XLOG records I output */
591 MyLastRecPtr.xrecoff = 0;
592 MyXactMadeXLogEntry = false;
593 MyXactMadeTempRelUpdate = false;
595 /* Show myself as out of the transaction in PGPROC array */
596 MyProc->logRec.xrecoff = 0;
607 * Clean up the relation cache.
609 AtEOXact_RelationCache(true);
612 * Make catalog changes visible to all backends.
614 AtEOXactInvalidationMessages(true);
618 * AtCommit_LocalCache
621 AtCommit_LocalCache(void)
624 * Make catalog changes visible to me for the next command.
626 CommandEndInvalidationMessages(true);
636 * XXX What if ProcReleaseLocks fails? (race condition?)
638 * Then you're up a creek! -mer 5/24/92
640 ProcReleaseLocks(true);
647 AtCommit_Memory(void)
650 * Now that we're "out" of a transaction, have the system allocate
651 * things in the top memory context instead of per-transaction
654 MemoryContextSwitchTo(TopMemoryContext);
657 * Release all transaction-local memory.
659 Assert(TopTransactionContext != NULL);
660 MemoryContextDelete(TopTransactionContext);
661 TopTransactionContext = NULL;
662 TransactionCommandContext = NULL;
665 /* ----------------------------------------------------------------
666 * AbortTransaction stuff
667 * ----------------------------------------------------------------
671 * RecordTransactionAbort
674 RecordTransactionAbort(void)
677 * If we made neither any transaction-controlled XLOG entries nor any
678 * temp-rel updates, we can omit recording the transaction abort at
679 * all. No one will ever care that it aborted.
681 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
683 TransactionId xid = GetCurrentTransactionId();
686 * Catch the scenario where we aborted partway through
687 * RecordTransactionCommit ...
689 if (TransactionIdDidCommit(xid))
690 elog(PANIC, "RecordTransactionAbort: xact %u already committed",
693 START_CRIT_SECTION();
696 * We only need to log the abort in XLOG if the transaction made
697 * any transaction-controlled XLOG entries. (Otherwise, its XID
698 * appears nowhere in permanent storage, so no one else will ever
699 * care if it committed.) We do not flush XLOG to disk in any
700 * case, since the default assumption after a crash would be that
701 * we aborted, anyway.
703 if (MyLastRecPtr.xrecoff != 0)
709 xlrec.xtime = time(NULL);
710 rdata.buffer = InvalidBuffer;
711 rdata.data = (char *) (&xlrec);
712 rdata.len = SizeOfXactAbort;
716 * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
718 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
722 * Mark the transaction aborted in clog. This is not absolutely
723 * necessary but we may as well do it while we are here.
725 TransactionIdAbort(xid);
730 /* Break the chain of back-links in the XLOG records I output */
731 MyLastRecPtr.xrecoff = 0;
732 MyXactMadeXLogEntry = false;
733 MyXactMadeTempRelUpdate = false;
735 /* Show myself as out of the transaction in PGPROC array */
736 MyProc->logRec.xrecoff = 0;
745 AtEOXact_RelationCache(false);
746 AtEOXactInvalidationMessages(false);
756 * XXX What if ProcReleaseLocks() fails? (race condition?)
758 * Then you're up a creek without a paddle! -mer
760 ProcReleaseLocks(false);
771 * Make sure we are in a valid context (not a child of
772 * TransactionCommandContext...). Note that it is possible for this
773 * code to be called when we aren't in a transaction at all; go
774 * directly to TopMemoryContext in that case.
776 if (TransactionCommandContext != NULL)
778 MemoryContextSwitchTo(TransactionCommandContext);
781 * We do not want to destroy transaction contexts yet, but it
782 * should be OK to delete any command-local memory.
784 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
787 MemoryContextSwitchTo(TopMemoryContext);
791 /* ----------------------------------------------------------------
792 * CleanupTransaction stuff
793 * ----------------------------------------------------------------
800 AtCleanup_Memory(void)
803 * Now that we're "out" of a transaction, have the system allocate
804 * things in the top memory context instead of per-transaction
807 MemoryContextSwitchTo(TopMemoryContext);
810 * Release all transaction-local memory.
812 if (TopTransactionContext != NULL)
813 MemoryContextDelete(TopTransactionContext);
814 TopTransactionContext = NULL;
815 TransactionCommandContext = NULL;
819 /* ----------------------------------------------------------------
821 * ----------------------------------------------------------------
828 StartTransaction(void)
830 TransactionState s = CurrentTransactionState;
833 XactIsoLevel = DefaultXactIsoLevel;
834 XactReadOnly = DefaultXactReadOnly;
837 * Check the current transaction state. If the transaction system is
838 * switched off, or if we're already in a transaction, do nothing.
839 * We're already in a transaction when the monitor sends a null
840 * command to the backend to flush the comm channel. This is a hacky
841 * fix to a communications problem, and we keep having to deal with it
842 * here. We should fix the comm channel code. mao 080891
844 if (s->state == TRANS_INPROGRESS)
848 * set the current transaction state information appropriately during
851 s->state = TRANS_START;
853 SetReindexProcessing(false);
856 * generate a new transaction id
858 s->transactionIdData = GetNewTransactionId();
860 XactLockTableInsert(s->transactionIdData);
863 * initialize current transaction state fields
865 s->commandId = FirstCommandId;
866 s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
869 * initialize the various transaction subsystems
876 * Tell the trigger manager to we're starting a transaction
878 DeferredTriggerBeginXact();
881 * done with start processing, set current transaction state to "in
884 s->state = TRANS_INPROGRESS;
892 CommitTransaction(void)
894 TransactionState s = CurrentTransactionState;
897 * check the current transaction state
899 if (s->state != TRANS_INPROGRESS)
900 elog(WARNING, "CommitTransaction and not in in-progress state");
903 * Tell the trigger manager that this transaction is about to be
904 * committed. He'll invoke all trigger deferred until XACT before we
905 * really start on committing the transaction.
907 DeferredTriggerEndXact();
910 * Similarly, let ON COMMIT management do its thing before we start
913 PreCommit_on_commit_actions();
915 /* Prevent cancel/die interrupt while cleaning up */
919 * set the current transaction state information appropriately during
920 * the abort processing
922 s->state = TRANS_COMMIT;
925 * Do pre-commit processing (most of this stuff requires database
926 * access, and in fact could still cause an error...)
931 /* handle commit for large objects [ PA, 7/17/98 ] */
932 /* XXX probably this does not belong here */
935 /* NOTIFY commit must come before lower-level cleanup */
938 /* Update the flat password file if we changed pg_shadow or pg_group */
939 AtEOXact_UpdatePasswordFile(true);
942 * Here is where we really truly commit.
944 RecordTransactionCommit();
947 * Let others know about no transaction in progress by me. Note that
948 * this must be done _before_ releasing locks we hold and _after_
949 * RecordTransactionCommit.
951 * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
952 * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
953 * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
954 * as running as well or it will see two tuple versions - one deleted
955 * by xid 1 and one inserted by xid 0. See notes in GetSnapshotData.
957 if (MyProc != (PGPROC *) NULL)
959 /* Lock SInvalLock because that's what GetSnapshotData uses. */
960 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
961 MyProc->xid = InvalidTransactionId;
962 MyProc->xmin = InvalidTransactionId;
963 LWLockRelease(SInvalLock);
967 * This is all post-commit cleanup. Note that if an error is raised
968 * here, it's too late to abort the transaction. This should be just
969 * noncritical resource releasing.
971 * The ordering of operations is not entirely random. The idea is:
972 * release resources visible to other backends (eg, files, buffer pins);
973 * then release locks; then release backend-local resources. We want
974 * to release locks at the point where any backend waiting for us will
975 * see our transaction as being fully cleaned up.
978 smgrDoPendingDeletes(true);
980 AtEOXact_Buffers(true);
981 /* smgrcommit already done */
991 AtEOXact_on_commit_actions(true);
992 AtEOXact_Namespace(true);
993 AtEOXact_CatCache(true);
995 pgstat_count_xact_commit();
999 * done with commit processing, set current transaction state back to
1002 s->state = TRANS_DEFAULT;
1004 RESUME_INTERRUPTS();
1011 AbortTransaction(void)
1013 TransactionState s = CurrentTransactionState;
1015 /* Prevent cancel/die interrupt while cleaning up */
1019 * Release any LW locks we might be holding as quickly as possible.
1020 * (Regular locks, however, must be held till we finish aborting.)
1021 * Releasing LW locks is critical since we might try to grab them
1022 * again while cleaning up!
1026 /* Clean up buffer I/O and buffer context locks, too */
1031 * Also clean up any open wait for lock, since the lock manager will
1032 * choke if we try to wait for another lock before doing this.
1037 * check the current transaction state
1039 if (s->state != TRANS_INPROGRESS)
1040 elog(WARNING, "AbortTransaction and not in in-progress state");
1043 * set the current transaction state information appropriately during
1044 * the abort processing
1046 s->state = TRANS_ABORT;
1048 /* Make sure we are in a valid memory context */
1052 * Reset user id which might have been changed transiently
1054 SetUserId(GetSessionUserId());
1057 * do abort processing
1059 DeferredTriggerAbortXact();
1061 lo_commit(false); /* 'false' means it's abort */
1063 AtEOXact_UpdatePasswordFile(false);
1065 /* Advertise the fact that we aborted in pg_clog. */
1066 RecordTransactionAbort();
1069 * Let others know about no transaction in progress by me. Note that
1070 * this must be done _before_ releasing locks we hold and _after_
1071 * RecordTransactionAbort.
1073 if (MyProc != (PGPROC *) NULL)
1075 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1076 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1077 MyProc->xid = InvalidTransactionId;
1078 MyProc->xmin = InvalidTransactionId;
1079 LWLockRelease(SInvalLock);
1083 * Post-abort cleanup. See notes in CommitTransaction() concerning
1087 smgrDoPendingDeletes(false);
1089 AtEOXact_Buffers(false);
1094 AtEOXact_GUC(false);
1100 AtEOXact_on_commit_actions(false);
1101 AtEOXact_Namespace(false);
1102 AtEOXact_CatCache(false);
1104 pgstat_count_xact_rollback();
1107 * State remains TRANS_ABORT until CleanupTransaction().
1109 RESUME_INTERRUPTS();
1113 * CleanupTransaction
1116 CleanupTransaction(void)
1118 TransactionState s = CurrentTransactionState;
1121 * State should still be TRANS_ABORT from AbortTransaction().
1123 if (s->state != TRANS_ABORT)
1124 elog(FATAL, "CleanupTransaction and not in abort state");
1127 * do abort cleanup processing
1132 * done with abort processing, set current transaction state back to
1135 s->state = TRANS_DEFAULT;
1139 * StartTransactionCommand
1141 * preventChain, if true, forces autocommit behavior at the next
1142 * CommitTransactionCommand call.
1145 StartTransactionCommand(bool preventChain)
1147 TransactionState s = CurrentTransactionState;
1150 * Remember if caller wants to prevent autocommit-off chaining. This
1151 * is only allowed if not already in a transaction block.
1153 suppressChain = preventChain;
1154 if (preventChain && s->blockState != TBLOCK_DEFAULT)
1155 elog(ERROR, "StartTransactionCommand: can't prevent chain");
1157 switch (s->blockState)
1160 * if we aren't in a transaction block, we just do our usual
1161 * start transaction.
1163 case TBLOCK_DEFAULT:
1168 * We should never experience this -- if we do it means the
1169 * BEGIN state was not changed in the previous
1170 * CommitTransactionCommand(). If we get it, we print a
1171 * warning and change to the in-progress state.
1174 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_BEGIN");
1175 s->blockState = TBLOCK_INPROGRESS;
1179 * This is the case when are somewhere in a transaction block
1180 * and about to start a new command. For now we do nothing
1181 * but someday we may do command-local resource
1184 case TBLOCK_INPROGRESS:
1188 * As with BEGIN, we should never experience this if we do it
1189 * means the END state was not changed in the previous
1190 * CommitTransactionCommand(). If we get it, we print a
1191 * warning, commit the transaction, start a new transaction
1192 * and change to the default state.
1195 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_END");
1196 s->blockState = TBLOCK_DEFAULT;
1197 CommitTransaction();
1202 * Here we are in the middle of a transaction block but one of
1203 * the commands caused an abort so we do nothing but remain in
1204 * the abort state. Eventually we will get to the "END
1205 * TRANSACTION" which will set things straight.
1211 * This means we somehow aborted and the last call to
1212 * CommitTransactionCommand() didn't clear the state so we
1213 * remain in the ENDABORT state and maybe next time we get to
1214 * CommitTransactionCommand() the state will get reset to
1217 case TBLOCK_ENDABORT:
1218 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");
1223 * We must switch to TransactionCommandContext before returning. This
1224 * is already done if we called StartTransaction, otherwise not.
1226 Assert(TransactionCommandContext != NULL);
1227 MemoryContextSwitchTo(TransactionCommandContext);
1231 * CommitTransactionCommand
1233 * forceCommit = true forces autocommit behavior even when autocommit is off.
1236 CommitTransactionCommand(bool forceCommit)
1238 TransactionState s = CurrentTransactionState;
1240 switch (s->blockState)
1243 * If we aren't in a transaction block, and we are doing
1244 * autocommit, just do our usual transaction commit. But if
1245 * we aren't doing autocommit, start a transaction block
1246 * automatically by switching to INPROGRESS state. (We handle
1247 * this choice here, and not earlier, so that an explicit
1248 * BEGIN issued in autocommit-off mode won't issue strange
1251 * Autocommit mode is forced by either a true forceCommit
1252 * parameter to me, or a true preventChain parameter to the
1253 * preceding StartTransactionCommand call, or a
1254 * PreventTransactionChain call during the transaction.
1255 * (The parameters could be omitted, but it turns out most
1256 * callers of StartTransactionCommand/CommitTransactionCommand
1257 * want to force autocommit, so making them all call
1258 * PreventTransactionChain would just be extra notation.)
1260 case TBLOCK_DEFAULT:
1261 if (autocommit || forceCommit || suppressChain)
1262 CommitTransaction();
1265 BeginTransactionBlock();
1266 Assert(s->blockState == TBLOCK_INPROGRESS);
1267 /* This code must match the TBLOCK_INPROGRESS case below: */
1268 CommandCounterIncrement();
1269 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
1274 * This is the case right after we get a "BEGIN TRANSACTION"
1275 * command, but the user hasn't done anything else yet, so we
1276 * change to the "transaction block in progress" state and
1280 s->blockState = TBLOCK_INPROGRESS;
1284 * This is the case when we have finished executing a command
1285 * someplace within a transaction block. We increment the
1286 * command counter and return. Someday we may free resources
1287 * local to the command.
1289 * That someday is today, at least for memory allocated in
1290 * TransactionCommandContext. - vadim 03/25/97
1292 case TBLOCK_INPROGRESS:
1293 CommandCounterIncrement();
1294 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
1298 * This is the case when we just got the "END TRANSACTION"
1299 * statement, so we commit the transaction and go back to the
1303 CommitTransaction();
1304 s->blockState = TBLOCK_DEFAULT;
1308 * Here we are in the middle of a transaction block but one of
1309 * the commands caused an abort so we do nothing but remain in
1310 * the abort state. Eventually we will get to the "END
1311 * TRANSACTION" which will set things straight.
1317 * Here we were in an aborted transaction block which just
1318 * processed the "END TRANSACTION" command from the user, so
1319 * clean up and return to the default state.
1321 case TBLOCK_ENDABORT:
1322 CleanupTransaction();
1323 s->blockState = TBLOCK_DEFAULT;
1329 * AbortCurrentTransaction
1332 AbortCurrentTransaction(void)
1334 TransactionState s = CurrentTransactionState;
1336 switch (s->blockState)
1339 * if we aren't in a transaction block, we just do the basic
1340 * abort & cleanup transaction.
1342 case TBLOCK_DEFAULT:
1344 CleanupTransaction();
1348 * If we are in the TBLOCK_BEGIN it means something screwed up
1349 * right after reading "BEGIN TRANSACTION" so we enter the
1350 * abort state. Eventually an "END TRANSACTION" will fix
1354 s->blockState = TBLOCK_ABORT;
1356 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1360 * This is the case when are somewhere in a transaction block
1361 * which aborted so we abort the transaction and set the ABORT
1362 * state. Eventually an "END TRANSACTION" will fix things and
1363 * restore us to a normal state.
1365 case TBLOCK_INPROGRESS:
1366 s->blockState = TBLOCK_ABORT;
1368 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1372 * Here, the system was fouled up just after the user wanted
1373 * to end the transaction block so we abort the transaction
1374 * and put us back into the default state.
1377 s->blockState = TBLOCK_DEFAULT;
1379 CleanupTransaction();
1383 * Here, we are already in an aborted transaction state and
1384 * are waiting for an "END TRANSACTION" to come along and lo
1385 * and behold, we abort again! So we just remain in the abort
1392 * Here we were in an aborted transaction block which just
1393 * processed the "END TRANSACTION" command but somehow aborted
1394 * again.. since we must have done the abort processing, we
1395 * clean up and return to the default state.
1397 case TBLOCK_ENDABORT:
1398 CleanupTransaction();
1399 s->blockState = TBLOCK_DEFAULT;
1405 * PreventTransactionChain
1407 * This routine is to be called by statements that must not run inside
1408 * a transaction block, typically because they have non-rollback-able
1409 * side effects or do internal commits.
1411 * If we have already started a transaction block, issue an error; also issue
1412 * an error if we appear to be running inside a user-defined function (which
1413 * could issue more commands and possibly cause a failure after the statement
1414 * completes). In autocommit-off mode, we allow the statement if a block is
1415 * not already started, and force the statement to be autocommitted despite
1418 * stmtNode: pointer to parameter block for statement; this is used in
1419 * a very klugy way to determine whether we are inside a function.
1420 * stmtType: statement type name for error messages.
1423 PreventTransactionChain(void *stmtNode, const char *stmtType)
1426 * xact block already started?
1428 if (IsTransactionBlock())
1430 /* translator: %s represents an SQL statement name */
1431 elog(ERROR, "%s cannot run inside a transaction block", stmtType);
1434 * Are we inside a function call? If the statement's parameter block
1435 * was allocated in QueryContext, assume it is an interactive command.
1436 * Otherwise assume it is coming from a function.
1438 if (!MemoryContextContains(QueryContext, stmtNode))
1440 /* translator: %s represents an SQL statement name */
1441 elog(ERROR, "%s cannot be executed from a function", stmtType);
1443 /* If we got past IsTransactionBlock test, should be in default state */
1444 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)
1445 elog(ERROR, "PreventTransactionChain: can't prevent chain");
1446 /* okay to set the flag */
1447 suppressChain = true;
1448 /* If we're in autocommit-off node, generate a notice */
1451 /* translator: %s represents an SQL statement name */
1452 elog(NOTICE, "%s will be committed automatically", stmtType);
1457 * RequireTransactionChain
1459 * This routine is to be called by statements that must run inside
1460 * a transaction block, because they have no effects that persist past
1461 * transaction end (and so calling them outside a transaction block
1462 * is presumably an error). DECLARE CURSOR is an example.
1464 * If we appear to be running inside a user-defined function, we do not
1465 * issue an error, since the function could issue more commands that make
1466 * use of the current statement's results. Thus this is an inverse for
1467 * PreventTransactionChain.
1469 * stmtNode: pointer to parameter block for statement; this is used in
1470 * a very klugy way to determine whether we are inside a function.
1471 * stmtType: statement type name for error messages.
1474 RequireTransactionChain(void *stmtNode, const char *stmtType)
1477 * xact block already started?
1479 if (IsTransactionBlock())
1482 * Are we inside a function call? If the statement's parameter block
1483 * was allocated in QueryContext, assume it is an interactive command.
1484 * Otherwise assume it is coming from a function.
1486 if (!MemoryContextContains(QueryContext, stmtNode))
1489 * If we are in autocommit-off mode then it's okay, because this
1490 * statement will itself start a transaction block.
1492 if (!autocommit && !suppressChain)
1494 /* translator: %s represents an SQL statement name */
1495 elog(ERROR, "%s may only be used in begin/end transaction blocks",
1500 /* ----------------------------------------------------------------
1501 * transaction block support
1502 * ----------------------------------------------------------------
1505 * BeginTransactionBlock
1508 BeginTransactionBlock(void)
1510 TransactionState s = CurrentTransactionState;
1513 * check the current transaction state
1515 if (s->blockState != TBLOCK_DEFAULT)
1516 elog(WARNING, "BEGIN: already a transaction in progress");
1519 * set the current transaction block state information appropriately
1520 * during begin processing
1522 s->blockState = TBLOCK_BEGIN;
1525 * do begin processing. NOTE: if you put anything here, check that it
1526 * behaves properly in both autocommit-on and autocommit-off modes. In
1527 * the latter case we will already have done some work in the new
1532 * done with begin processing, set block state to inprogress
1534 s->blockState = TBLOCK_INPROGRESS;
1538 * EndTransactionBlock
1541 EndTransactionBlock(void)
1543 TransactionState s = CurrentTransactionState;
1546 * check the current transaction state
1548 if (s->blockState == TBLOCK_INPROGRESS)
1551 * here we are in a transaction block which should commit when we
1552 * get to the upcoming CommitTransactionCommand() so we set the
1553 * state to "END". CommitTransactionCommand() will recognize this
1554 * and commit the transaction and return us to the default state
1556 s->blockState = TBLOCK_END;
1560 if (s->blockState == TBLOCK_ABORT)
1563 * here, we are in a transaction block which aborted and since the
1564 * AbortTransaction() was already done, we do whatever is needed
1565 * and change to the special "END ABORT" state. The upcoming
1566 * CommitTransactionCommand() will recognise this and then put us
1567 * back in the default state.
1569 s->blockState = TBLOCK_ENDABORT;
1574 * here, the user issued COMMIT when not inside a transaction. Issue a
1575 * WARNING and go to abort state. The upcoming call to
1576 * CommitTransactionCommand() will then put us back into the default
1579 elog(WARNING, "COMMIT: no transaction in progress");
1581 s->blockState = TBLOCK_ENDABORT;
1585 * AbortTransactionBlock
1589 AbortTransactionBlock(void)
1591 TransactionState s = CurrentTransactionState;
1594 * check the current transaction state
1596 if (s->blockState == TBLOCK_INPROGRESS)
1599 * here we were inside a transaction block something screwed up
1600 * inside the system so we enter the abort state, do the abort
1601 * processing and then return. We remain in the abort state until
1602 * we see an END TRANSACTION command.
1604 s->blockState = TBLOCK_ABORT;
1610 * here, the user issued ABORT when not inside a transaction. Issue a
1611 * WARNING and go to abort state. The upcoming call to
1612 * CommitTransactionCommand() will then put us back into the default
1615 elog(WARNING, "ROLLBACK: no transaction in progress");
1617 s->blockState = TBLOCK_ENDABORT;
1622 * UserAbortTransactionBlock
1625 UserAbortTransactionBlock(void)
1627 TransactionState s = CurrentTransactionState;
1630 * if the transaction has already been automatically aborted with an
1631 * error, and the user subsequently types 'abort', allow it. (the
1632 * behavior is the same as if they had typed 'end'.)
1634 if (s->blockState == TBLOCK_ABORT)
1636 s->blockState = TBLOCK_ENDABORT;
1640 if (s->blockState == TBLOCK_INPROGRESS)
1643 * here we were inside a transaction block and we got an abort
1644 * command from the user, so we move to the abort state, do the
1645 * abort processing and then change to the ENDABORT state so we
1646 * will end up in the default state after the upcoming
1647 * CommitTransactionCommand().
1649 s->blockState = TBLOCK_ABORT;
1651 s->blockState = TBLOCK_ENDABORT;
1656 * here, the user issued ABORT when not inside a transaction. Issue a
1657 * WARNING and go to abort state. The upcoming call to
1658 * CommitTransactionCommand() will then put us back into the default
1661 elog(WARNING, "ROLLBACK: no transaction in progress");
1663 s->blockState = TBLOCK_ENDABORT;
1667 * AbortOutOfAnyTransaction
1669 * This routine is provided for error recovery purposes. It aborts any
1670 * active transaction or transaction block, leaving the system in a known
1674 AbortOutOfAnyTransaction(void)
1676 TransactionState s = CurrentTransactionState;
1679 * Get out of any low-level transaction
1684 case TRANS_INPROGRESS:
1686 /* In a transaction, so clean up */
1688 CleanupTransaction();
1691 /* AbortTransaction already done, still need Cleanup */
1692 CleanupTransaction();
1695 /* Not in a transaction, do nothing */
1700 * Now reset the high-level state
1702 s->blockState = TBLOCK_DEFAULT;
1706 IsTransactionBlock(void)
1708 TransactionState s = CurrentTransactionState;
1710 if (s->blockState == TBLOCK_INPROGRESS
1711 || s->blockState == TBLOCK_ABORT
1712 || s->blockState == TBLOCK_ENDABORT)
1720 * XLOG support routines
1724 xact_redo(XLogRecPtr lsn, XLogRecord *record)
1726 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1728 if (info == XLOG_XACT_COMMIT)
1730 TransactionIdCommit(record->xl_xid);
1731 /* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */
1733 else if (info == XLOG_XACT_ABORT)
1735 TransactionIdAbort(record->xl_xid);
1736 /* SHOULD REMOVE FILES OF ALL FAILED-TO-BE-CREATED RELATIONS */
1739 elog(PANIC, "xact_redo: unknown op code %u", info);
1743 xact_undo(XLogRecPtr lsn, XLogRecord *record)
1745 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1747 if (info == XLOG_XACT_COMMIT) /* shouldn't be called by XLOG */
1748 elog(PANIC, "xact_undo: can't undo committed xaction");
1749 else if (info != XLOG_XACT_ABORT)
1750 elog(PANIC, "xact_redo: unknown op code %u", info);
1754 xact_desc(char *buf, uint8 xl_info, char *rec)
1756 uint8 info = xl_info & ~XLR_INFO_MASK;
1758 if (info == XLOG_XACT_COMMIT)
1760 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
1761 struct tm *tm = localtime(&xlrec->xtime);
1763 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
1764 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1765 tm->tm_hour, tm->tm_min, tm->tm_sec);
1767 else if (info == XLOG_XACT_ABORT)
1769 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
1770 struct tm *tm = localtime(&xlrec->xtime);
1772 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
1773 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1774 tm->tm_hour, tm->tm_min, tm->tm_sec);
1777 strcat(buf, "UNKNOWN");
1781 XactPushRollback(void (*func) (void *), void *data)
1784 if (_RollbackFunc != NULL)
1785 elog(PANIC, "XactPushRollback: already installed");
1788 _RollbackFunc = func;
1789 _RollbackData = data;
1793 XactPopRollback(void)
1795 _RollbackFunc = NULL;