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.138 2002/11/13 03:12:05 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 responce 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 of client queries */
203 TransactionState CurrentTransactionState = &CurrentTransactionStateData;
206 * User-tweakable parameters
208 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
211 bool autocommit = true;
213 int CommitDelay = 0; /* precommit delay in microseconds */
214 int CommitSiblings = 5; /* number of concurrent xacts needed to
218 static bool suppressChain = false;
220 static void (*_RollbackFunc) (void *) = NULL;
221 static void *_RollbackData = NULL;
224 /* ----------------------------------------------------------------
225 * transaction state accessors
226 * ----------------------------------------------------------------
231 /* --------------------------------
232 * TransactionFlushEnabled()
233 * SetTransactionFlushEnabled()
235 * These are used to test and set the "TransactionFlushState"
236 * varable. If this variable is true (the default), then
237 * the system will flush all dirty buffers to disk at the end
238 * of each transaction. If false then we are assuming the
239 * buffer pool resides in stable main memory, in which case we
240 * only do writes as necessary.
241 * --------------------------------
243 static int TransactionFlushState = 1;
246 TransactionFlushEnabled(void)
248 return TransactionFlushState;
252 SetTransactionFlushEnabled(bool state)
254 TransactionFlushState = (state == true);
259 /* --------------------------------
262 * This returns true if we are currently running a query
263 * within an executing transaction.
264 * --------------------------------
267 IsTransactionState(void)
269 TransactionState s = CurrentTransactionState;
277 case TRANS_INPROGRESS:
286 * Shouldn't get here, but lint is not happy with this...
291 /* --------------------------------
292 * IsAbortedTransactionBlockState
294 * This returns true if we are currently running a query
295 * within an aborted transaction block.
296 * --------------------------------
299 IsAbortedTransactionBlockState(void)
301 TransactionState s = CurrentTransactionState;
303 if (s->blockState == TBLOCK_ABORT)
310 /* --------------------------------
311 * GetCurrentTransactionId
312 * --------------------------------
315 GetCurrentTransactionId(void)
317 TransactionState s = CurrentTransactionState;
319 return s->transactionIdData;
323 /* --------------------------------
324 * GetCurrentCommandId
325 * --------------------------------
328 GetCurrentCommandId(void)
330 TransactionState s = CurrentTransactionState;
336 /* --------------------------------
337 * GetCurrentTransactionStartTime
338 * --------------------------------
341 GetCurrentTransactionStartTime(void)
343 TransactionState s = CurrentTransactionState;
349 /* --------------------------------
350 * GetCurrentTransactionStartTimeUsec
351 * --------------------------------
354 GetCurrentTransactionStartTimeUsec(int *msec)
356 TransactionState s = CurrentTransactionState;
358 *msec = s->startTimeUsec;
364 /* --------------------------------
365 * TransactionIdIsCurrentTransactionId
367 * During bootstrap, we cheat and say "it's not my transaction ID" even though
368 * it is. Along with transam.c's cheat to say that the bootstrap XID is
369 * already committed, this causes the tqual.c routines to see previously
370 * inserted tuples as committed, which is what we need during bootstrap.
371 * --------------------------------
374 TransactionIdIsCurrentTransactionId(TransactionId xid)
376 TransactionState s = CurrentTransactionState;
380 Assert(xid == BootstrapTransactionId);
384 return TransactionIdEquals(xid, s->transactionIdData);
388 /* --------------------------------
389 * CommandIdIsCurrentCommandId
390 * --------------------------------
393 CommandIdIsCurrentCommandId(CommandId cid)
395 TransactionState s = CurrentTransactionState;
397 return (cid == s->commandId) ? true : false;
401 /* --------------------------------
402 * CommandCounterIncrement
403 * --------------------------------
406 CommandCounterIncrement(void)
408 TransactionState s = CurrentTransactionState;
411 if (s->commandId == FirstCommandId) /* check for overflow */
412 elog(ERROR, "You may only have 2^32-1 commands per transaction");
414 /* Propagate new command ID into query snapshots, if set */
416 QuerySnapshot->curcid = s->commandId;
417 if (SerializableSnapshot)
418 SerializableSnapshot->curcid = s->commandId;
421 * make cache changes visible to me. AtCommit_LocalCache() instead of
422 * AtCommit_Cache() is called here.
424 AtCommit_LocalCache();
429 /* ----------------------------------------------------------------
430 * StartTransaction stuff
431 * ----------------------------------------------------------------
434 /* --------------------------------
436 * --------------------------------
441 AcceptInvalidationMessages();
444 /* --------------------------------
446 * --------------------------------
452 * at present, it is unknown to me what belongs here -cim 3/18/90
454 * There isn't anything to do at the start of a xact for locks. -mer
459 /* --------------------------------
461 * --------------------------------
467 * We shouldn't have any transaction contexts already.
469 Assert(TopTransactionContext == NULL);
470 Assert(TransactionCommandContext == NULL);
473 * Create a toplevel context for the transaction.
475 TopTransactionContext =
476 AllocSetContextCreate(TopMemoryContext,
477 "TopTransactionContext",
478 ALLOCSET_DEFAULT_MINSIZE,
479 ALLOCSET_DEFAULT_INITSIZE,
480 ALLOCSET_DEFAULT_MAXSIZE);
483 * Create a statement-level context and make it active.
485 TransactionCommandContext =
486 AllocSetContextCreate(TopTransactionContext,
487 "TransactionCommandContext",
488 ALLOCSET_DEFAULT_MINSIZE,
489 ALLOCSET_DEFAULT_INITSIZE,
490 ALLOCSET_DEFAULT_MAXSIZE);
491 MemoryContextSwitchTo(TransactionCommandContext);
495 /* ----------------------------------------------------------------
496 * CommitTransaction stuff
497 * ----------------------------------------------------------------
501 * RecordTransactionCommit
504 RecordTransactionCommit(void)
507 * If we made neither any XLOG entries nor any temp-rel updates, we
508 * can omit recording the transaction commit at all.
510 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)
512 TransactionId xid = GetCurrentTransactionId();
515 /* Tell bufmgr and smgr to prepare for commit */
518 START_CRIT_SECTION();
521 * We only need to log the commit in xlog if the transaction made
522 * any transaction-controlled XLOG entries. (Otherwise, its XID
523 * appears nowhere in permanent storage, so no one else will ever
524 * care if it committed.)
526 if (MyLastRecPtr.xrecoff != 0)
528 /* Need to emit a commit record */
530 xl_xact_commit xlrec;
532 xlrec.xtime = time(NULL);
533 rdata.buffer = InvalidBuffer;
534 rdata.data = (char *) (&xlrec);
535 rdata.len = SizeOfXactCommit;
539 * XXX SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
541 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, &rdata);
545 /* Just flush through last record written by me */
546 recptr = ProcLastRecEnd;
550 * We must flush our XLOG entries to disk if we made any XLOG
551 * entries, whether in or out of transaction control. For
552 * example, if we reported a nextval() result to the client, this
553 * ensures that any XLOG record generated by nextval will hit the
554 * disk before we report the transaction committed.
556 if (MyXactMadeXLogEntry)
559 * Sleep before flush! So we can flush more than one commit
560 * records per single fsync. (The idea is some other backend
561 * may do the XLogFlush while we're sleeping. This needs work
562 * still, because on most Unixen, the minimum select() delay
563 * is 10msec or more, which is way too long.)
565 * We do not sleep if enableFsync is not turned on, nor if there
566 * are fewer than CommitSiblings other backends with active
569 if (CommitDelay > 0 && enableFsync &&
570 CountActiveBackends() >= CommitSiblings)
572 struct timeval delay;
575 delay.tv_usec = CommitDelay;
576 (void) select(0, NULL, NULL, NULL, &delay);
583 * We must mark the transaction committed in clog if its XID
584 * appears either in permanent rels or in local temporary rels.
585 * We test this by seeing if we made transaction-controlled
586 * entries *OR* local-rel tuple updates. Note that if we made
587 * only the latter, we have not emitted an XLOG record for our
588 * commit, and so in the event of a crash the clog update might be
589 * lost. This is okay because no one else will ever care whether
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;
608 /* --------------------------------
610 * --------------------------------
616 * Clean up the relation cache.
618 AtEOXact_RelationCache(true);
621 * Make catalog changes visible to all backends.
623 AtEOXactInvalidationMessages(true);
626 /* --------------------------------
627 * AtCommit_LocalCache
628 * --------------------------------
631 AtCommit_LocalCache(void)
634 * Make catalog changes visible to me for the next command.
636 CommandEndInvalidationMessages(true);
639 /* --------------------------------
641 * --------------------------------
647 * XXX What if ProcReleaseLocks fails? (race condition?)
649 * Then you're up a creek! -mer 5/24/92
651 ProcReleaseLocks(true);
654 /* --------------------------------
656 * --------------------------------
659 AtCommit_Memory(void)
662 * Now that we're "out" of a transaction, have the system allocate
663 * things in the top memory context instead of per-transaction
666 MemoryContextSwitchTo(TopMemoryContext);
669 * Release all transaction-local memory.
671 Assert(TopTransactionContext != NULL);
672 MemoryContextDelete(TopTransactionContext);
673 TopTransactionContext = NULL;
674 TransactionCommandContext = NULL;
677 /* ----------------------------------------------------------------
678 * AbortTransaction stuff
679 * ----------------------------------------------------------------
683 * RecordTransactionAbort
686 RecordTransactionAbort(void)
689 * If we made neither any transaction-controlled XLOG entries nor any
690 * temp-rel updates, we can omit recording the transaction abort at
691 * all. No one will ever care that it aborted.
693 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
695 TransactionId xid = GetCurrentTransactionId();
698 * Catch the scenario where we aborted partway through
699 * RecordTransactionCommit ...
701 if (TransactionIdDidCommit(xid))
702 elog(PANIC, "RecordTransactionAbort: xact %u already committed",
705 START_CRIT_SECTION();
708 * We only need to log the abort in XLOG if the transaction made
709 * any transaction-controlled XLOG entries. (Otherwise, its XID
710 * appears nowhere in permanent storage, so no one else will ever
711 * care if it committed.) We do not flush XLOG to disk in any
712 * case, since the default assumption after a crash would be that
713 * we aborted, anyway.
715 if (MyLastRecPtr.xrecoff != 0)
721 xlrec.xtime = time(NULL);
722 rdata.buffer = InvalidBuffer;
723 rdata.data = (char *) (&xlrec);
724 rdata.len = SizeOfXactAbort;
728 * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
730 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
734 * Mark the transaction aborted in clog. This is not absolutely
735 * necessary but we may as well do it while we are here.
737 TransactionIdAbort(xid);
742 /* Break the chain of back-links in the XLOG records I output */
743 MyLastRecPtr.xrecoff = 0;
744 MyXactMadeXLogEntry = false;
745 MyXactMadeTempRelUpdate = false;
747 /* Show myself as out of the transaction in PGPROC array */
748 MyProc->logRec.xrecoff = 0;
751 /* --------------------------------
753 * --------------------------------
758 AtEOXact_RelationCache(false);
759 AtEOXactInvalidationMessages(false);
762 /* --------------------------------
764 * --------------------------------
770 * XXX What if ProcReleaseLocks() fails? (race condition?)
772 * Then you're up a creek without a paddle! -mer
774 ProcReleaseLocks(false);
778 /* --------------------------------
780 * --------------------------------
786 * Make sure we are in a valid context (not a child of
787 * TransactionCommandContext...). Note that it is possible for this
788 * code to be called when we aren't in a transaction at all; go
789 * directly to TopMemoryContext in that case.
791 if (TransactionCommandContext != NULL)
793 MemoryContextSwitchTo(TransactionCommandContext);
796 * We do not want to destroy transaction contexts yet, but it
797 * should be OK to delete any command-local memory.
799 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
802 MemoryContextSwitchTo(TopMemoryContext);
806 /* ----------------------------------------------------------------
807 * CleanupTransaction stuff
808 * ----------------------------------------------------------------
811 /* --------------------------------
813 * --------------------------------
816 AtCleanup_Memory(void)
819 * Now that we're "out" of a transaction, have the system allocate
820 * things in the top memory context instead of per-transaction
823 MemoryContextSwitchTo(TopMemoryContext);
826 * Release all transaction-local memory.
828 if (TopTransactionContext != NULL)
829 MemoryContextDelete(TopTransactionContext);
830 TopTransactionContext = NULL;
831 TransactionCommandContext = NULL;
835 /* ----------------------------------------------------------------
837 * ----------------------------------------------------------------
840 /* --------------------------------
842 * --------------------------------
845 StartTransaction(void)
847 TransactionState s = CurrentTransactionState;
850 XactIsoLevel = DefaultXactIsoLevel;
853 * Check the current transaction state. If the transaction system is
854 * switched off, or if we're already in a transaction, do nothing.
855 * We're already in a transaction when the monitor sends a null
856 * command to the backend to flush the comm channel. This is a hacky
857 * fix to a communications problem, and we keep having to deal with it
858 * here. We should fix the comm channel code. mao 080891
860 if (s->state == TRANS_INPROGRESS)
864 * set the current transaction state information appropriately during
867 s->state = TRANS_START;
869 SetReindexProcessing(false);
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 to we're starting a transaction
894 DeferredTriggerBeginXact();
897 * done with start processing, set current transaction state to "in
900 s->state = TRANS_INPROGRESS;
906 * Tell me if we are currently in progress
910 CurrentXactInProgress(void)
912 return CurrentTransactionState->state == TRANS_INPROGRESS;
916 /* --------------------------------
918 * --------------------------------
921 CommitTransaction(void)
923 TransactionState s = CurrentTransactionState;
926 * check the current transaction state
928 if (s->state != TRANS_INPROGRESS)
929 elog(WARNING, "CommitTransaction and not in in-progress state");
932 * Tell the trigger manager that this transaction is about to be
933 * committed. He'll invoke all trigger deferred until XACT before we
934 * really start on committing the transaction.
936 DeferredTriggerEndXact();
939 * Similarly, let ON COMMIT management do its thing before we start
942 PreCommit_on_commit_actions();
944 /* Prevent cancel/die interrupt while cleaning up */
948 * set the current transaction state information appropriately during
949 * the abort processing
951 s->state = TRANS_COMMIT;
954 * Do pre-commit processing (most of this stuff requires database
955 * access, and in fact could still cause an error...)
960 /* handle commit for large objects [ PA, 7/17/98 ] */
961 /* XXX probably this does not belong here */
964 /* NOTIFY commit must come before lower-level cleanup */
967 /* Update the flat password file if we changed pg_shadow or pg_group */
968 AtEOXact_UpdatePasswordFile(true);
971 * Here is where we really truly commit.
973 RecordTransactionCommit();
976 * Let others know about no transaction in progress by me. Note that
977 * this must be done _before_ releasing locks we hold and _after_
978 * RecordTransactionCommit.
980 * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
981 * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
982 * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
983 * as running as well or it will see two tuple versions - one deleted
984 * by xid 1 and one inserted by xid 0. See notes in GetSnapshotData.
986 if (MyProc != (PGPROC *) NULL)
988 /* Lock SInvalLock because that's what GetSnapshotData uses. */
989 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
990 MyProc->xid = InvalidTransactionId;
991 MyProc->xmin = InvalidTransactionId;
992 LWLockRelease(SInvalLock);
996 * This is all post-commit cleanup. Note that if an error is raised
997 * here, it's too late to abort the transaction. This should be just
998 * noncritical resource releasing.
1000 * The ordering of operations is not entirely random. The idea is:
1001 * release resources visible to other backends (eg, files, buffer pins);
1002 * then release locks; then release backend-local resources. We want
1003 * to release locks at the point where any backend waiting for us will
1004 * see our transaction as being fully cleaned up.
1007 smgrDoPendingDeletes(true);
1009 AtEOXact_Buffers(true);
1010 /* smgrcommit already done */
1020 AtEOXact_on_commit_actions(true);
1021 AtEOXact_Namespace(true);
1022 AtEOXact_CatCache(true);
1024 pgstat_count_xact_commit();
1028 * done with commit processing, set current transaction state back to
1031 s->state = TRANS_DEFAULT;
1033 RESUME_INTERRUPTS();
1036 /* --------------------------------
1038 * --------------------------------
1041 AbortTransaction(void)
1043 TransactionState s = CurrentTransactionState;
1045 /* Prevent cancel/die interrupt while cleaning up */
1049 * Release any LW locks we might be holding as quickly as possible.
1050 * (Regular locks, however, must be held till we finish aborting.)
1051 * Releasing LW locks is critical since we might try to grab them
1052 * again while cleaning up!
1056 /* Clean up buffer I/O and buffer context locks, too */
1061 * Also clean up any open wait for lock, since the lock manager will
1062 * choke if we try to wait for another lock before doing this.
1067 * check the current transaction state
1069 if (s->state != TRANS_INPROGRESS)
1070 elog(WARNING, "AbortTransaction and not in in-progress state");
1073 * set the current transaction state information appropriately during
1074 * the abort processing
1076 s->state = TRANS_ABORT;
1078 /* Make sure we are in a valid memory context */
1082 * Reset user id which might have been changed transiently
1084 SetUserId(GetSessionUserId());
1087 * do abort processing
1089 DeferredTriggerAbortXact();
1091 lo_commit(false); /* 'false' means it's abort */
1093 AtEOXact_UpdatePasswordFile(false);
1095 /* Advertise the fact that we aborted in pg_clog. */
1096 RecordTransactionAbort();
1099 * Let others know about no transaction in progress by me. Note that
1100 * this must be done _before_ releasing locks we hold and _after_
1101 * RecordTransactionAbort.
1103 if (MyProc != (PGPROC *) NULL)
1105 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1106 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1107 MyProc->xid = InvalidTransactionId;
1108 MyProc->xmin = InvalidTransactionId;
1109 LWLockRelease(SInvalLock);
1113 * Post-abort cleanup. See notes in CommitTransaction() concerning
1117 smgrDoPendingDeletes(false);
1119 AtEOXact_Buffers(false);
1124 AtEOXact_GUC(false);
1130 AtEOXact_on_commit_actions(false);
1131 AtEOXact_Namespace(false);
1132 AtEOXact_CatCache(false);
1134 pgstat_count_xact_rollback();
1137 * State remains TRANS_ABORT until CleanupTransaction().
1139 RESUME_INTERRUPTS();
1142 /* --------------------------------
1143 * CleanupTransaction
1144 * --------------------------------
1147 CleanupTransaction(void)
1149 TransactionState s = CurrentTransactionState;
1152 * State should still be TRANS_ABORT from AbortTransaction().
1154 if (s->state != TRANS_ABORT)
1155 elog(FATAL, "CleanupTransaction and not in abort state");
1158 * do abort cleanup processing
1163 * done with abort processing, set current transaction state back to
1166 s->state = TRANS_DEFAULT;
1169 /* --------------------------------
1170 * StartTransactionCommand
1172 * preventChain, if true, forces autocommit behavior at the next
1173 * CommitTransactionCommand call.
1174 * --------------------------------
1177 StartTransactionCommand(bool preventChain)
1179 TransactionState s = CurrentTransactionState;
1182 * Remember if caller wants to prevent autocommit-off chaining. This
1183 * is only allowed if not already in a transaction block.
1185 suppressChain = preventChain;
1186 if (preventChain && s->blockState != TBLOCK_DEFAULT)
1187 elog(ERROR, "StartTransactionCommand: can't prevent chain");
1189 switch (s->blockState)
1192 * if we aren't in a transaction block, we just do our usual
1193 * start transaction.
1195 case TBLOCK_DEFAULT:
1200 * We should never experience this -- if we do it means the
1201 * BEGIN state was not changed in the previous
1202 * CommitTransactionCommand(). If we get it, we print a
1203 * warning and change to the in-progress state.
1206 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_BEGIN");
1207 s->blockState = TBLOCK_INPROGRESS;
1211 * This is the case when are somewhere in a transaction block
1212 * and about to start a new command. For now we do nothing
1213 * but someday we may do command-local resource
1216 case TBLOCK_INPROGRESS:
1220 * As with BEGIN, we should never experience this if we do it
1221 * means the END state was not changed in the previous
1222 * CommitTransactionCommand(). If we get it, we print a
1223 * warning, commit the transaction, start a new transaction
1224 * and change to the default state.
1227 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_END");
1228 s->blockState = TBLOCK_DEFAULT;
1229 CommitTransaction();
1234 * Here we are in the middle of a transaction block but one of
1235 * the commands caused an abort so we do nothing but remain in
1236 * the abort state. Eventually we will get to the "END
1237 * TRANSACTION" which will set things straight.
1243 * This means we somehow aborted and the last call to
1244 * CommitTransactionCommand() didn't clear the state so we
1245 * remain in the ENDABORT state and maybe next time we get to
1246 * CommitTransactionCommand() the state will get reset to
1249 case TBLOCK_ENDABORT:
1250 elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");
1255 * We must switch to TransactionCommandContext before returning. This
1256 * is already done if we called StartTransaction, otherwise not.
1258 Assert(TransactionCommandContext != NULL);
1259 MemoryContextSwitchTo(TransactionCommandContext);
1262 /* --------------------------------
1263 * CommitTransactionCommand
1265 * forceCommit = true forces autocommit behavior even when autocommit is off.
1266 * --------------------------------
1269 CommitTransactionCommand(bool forceCommit)
1271 TransactionState s = CurrentTransactionState;
1273 switch (s->blockState)
1276 * If we aren't in a transaction block, and we are doing
1277 * autocommit, just do our usual transaction commit. But if
1278 * we aren't doing autocommit, start a transaction block
1279 * automatically by switching to INPROGRESS state. (We handle
1280 * this choice here, and not earlier, so that an explicit
1281 * BEGIN issued in autocommit-off mode won't issue strange
1284 * Autocommit mode is forced by either a true forceCommit
1285 * parameter to me, or a true preventChain parameter to the
1286 * preceding StartTransactionCommand call, or a
1287 * PreventTransactionChain call during the transaction.
1288 * (The parameters could be omitted, but it turns out most
1289 * callers of StartTransactionCommand/CommitTransactionCommand
1290 * want to force autocommit, so making them all call
1291 * PreventTransactionChain would just be extra notation.)
1293 case TBLOCK_DEFAULT:
1294 if (autocommit || forceCommit || suppressChain)
1295 CommitTransaction();
1298 BeginTransactionBlock();
1299 Assert(s->blockState == TBLOCK_INPROGRESS);
1300 /* This code must match the TBLOCK_INPROGRESS case below: */
1301 CommandCounterIncrement();
1302 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
1307 * This is the case right after we get a "BEGIN TRANSACTION"
1308 * command, but the user hasn't done anything else yet, so we
1309 * change to the "transaction block in progress" state and
1313 s->blockState = TBLOCK_INPROGRESS;
1317 * This is the case when we have finished executing a command
1318 * someplace within a transaction block. We increment the
1319 * command counter and return. Someday we may free resources
1320 * local to the command.
1322 * That someday is today, at least for memory allocated in
1323 * TransactionCommandContext. - vadim 03/25/97
1325 case TBLOCK_INPROGRESS:
1326 CommandCounterIncrement();
1327 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
1331 * This is the case when we just got the "END TRANSACTION"
1332 * statement, so we commit the transaction and go back to the
1336 CommitTransaction();
1337 s->blockState = TBLOCK_DEFAULT;
1341 * Here we are in the middle of a transaction block but one of
1342 * the commands caused an abort so we do nothing but remain in
1343 * the abort state. Eventually we will get to the "END
1344 * TRANSACTION" which will set things straight.
1350 * Here we were in an aborted transaction block which just
1351 * processed the "END TRANSACTION" command from the user, so
1352 * clean up and return to the default state.
1354 case TBLOCK_ENDABORT:
1355 CleanupTransaction();
1356 s->blockState = TBLOCK_DEFAULT;
1361 /* --------------------------------
1362 * AbortCurrentTransaction
1363 * --------------------------------
1366 AbortCurrentTransaction(void)
1368 TransactionState s = CurrentTransactionState;
1370 switch (s->blockState)
1373 * if we aren't in a transaction block, we just do the basic
1374 * abort & cleanup transaction.
1376 case TBLOCK_DEFAULT:
1378 CleanupTransaction();
1382 * If we are in the TBLOCK_BEGIN it means something screwed up
1383 * right after reading "BEGIN TRANSACTION" so we enter the
1384 * abort state. Eventually an "END TRANSACTION" will fix
1388 s->blockState = TBLOCK_ABORT;
1390 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1394 * This is the case when are somewhere in a transaction block
1395 * which aborted so we abort the transaction and set the ABORT
1396 * state. Eventually an "END TRANSACTION" will fix things and
1397 * restore us to a normal state.
1399 case TBLOCK_INPROGRESS:
1400 s->blockState = TBLOCK_ABORT;
1402 /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1406 * Here, the system was fouled up just after the user wanted
1407 * to end the transaction block so we abort the transaction
1408 * and put us back into the default state.
1411 s->blockState = TBLOCK_DEFAULT;
1413 CleanupTransaction();
1417 * Here, we are already in an aborted transaction state and
1418 * are waiting for an "END TRANSACTION" to come along and lo
1419 * and behold, we abort again! So we just remain in the abort
1426 * Here we were in an aborted transaction block which just
1427 * processed the "END TRANSACTION" command but somehow aborted
1428 * again.. since we must have done the abort processing, we
1429 * clean up and return to the default state.
1431 case TBLOCK_ENDABORT:
1432 CleanupTransaction();
1433 s->blockState = TBLOCK_DEFAULT;
1438 /* --------------------------------
1439 * PreventTransactionChain
1441 * This routine is to be called by statements that must not run inside
1442 * a transaction block, typically because they have non-rollback-able
1443 * side effects or do internal commits.
1445 * If we have already started a transaction block, issue an error; also issue
1446 * an error if we appear to be running inside a user-defined function (which
1447 * could issue more commands and possibly cause a failure after the statement
1448 * completes). In autocommit-off mode, we allow the statement if a block is
1449 * not already started, and force the statement to be autocommitted despite
1452 * stmtNode: pointer to parameter block for statement; this is used in
1453 * a very klugy way to determine whether we are inside a function.
1454 * stmtType: statement type name for error messages.
1455 * --------------------------------
1458 PreventTransactionChain(void *stmtNode, const char *stmtType)
1461 * xact block already started?
1463 if (IsTransactionBlock())
1465 /* translator: %s represents an SQL statement name */
1466 elog(ERROR, "%s cannot run inside a transaction block", stmtType);
1469 * Are we inside a function call? If the statement's parameter block
1470 * was allocated in QueryContext, assume it is an interactive command.
1471 * Otherwise assume it is coming from a function.
1473 if (!MemoryContextContains(QueryContext, stmtNode))
1475 /* translator: %s represents an SQL statement name */
1476 elog(ERROR, "%s cannot be executed from a function", stmtType);
1478 /* If we got past IsTransactionBlock test, should be in default state */
1479 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT)
1480 elog(ERROR, "PreventTransactionChain: can't prevent chain");
1481 /* okay to set the flag */
1482 suppressChain = true;
1483 /* If we're in autocommit-off node, generate a notice */
1486 /* translator: %s represents an SQL statement name */
1487 elog(NOTICE, "%s will be committed automatically", stmtType);
1492 /* ----------------------------------------------------------------
1493 * transaction block support
1494 * ----------------------------------------------------------------
1496 /* --------------------------------
1497 * BeginTransactionBlock
1498 * --------------------------------
1501 BeginTransactionBlock(void)
1503 TransactionState s = CurrentTransactionState;
1506 * check the current transaction state
1508 if (s->blockState != TBLOCK_DEFAULT)
1509 elog(WARNING, "BEGIN: already a transaction in progress");
1512 * set the current transaction block state information appropriately
1513 * during begin processing
1515 s->blockState = TBLOCK_BEGIN;
1518 * do begin processing. NOTE: if you put anything here, check that it
1519 * behaves properly in both autocommit-on and autocommit-off modes. In
1520 * the latter case we will already have done some work in the new
1525 * done with begin processing, set block state to inprogress
1527 s->blockState = TBLOCK_INPROGRESS;
1530 /* --------------------------------
1531 * EndTransactionBlock
1532 * --------------------------------
1535 EndTransactionBlock(void)
1537 TransactionState s = CurrentTransactionState;
1540 * check the current transaction state
1542 if (s->blockState == TBLOCK_INPROGRESS)
1545 * here we are in a transaction block which should commit when we
1546 * get to the upcoming CommitTransactionCommand() so we set the
1547 * state to "END". CommitTransactionCommand() will recognize this
1548 * and commit the transaction and return us to the default state
1550 s->blockState = TBLOCK_END;
1554 if (s->blockState == TBLOCK_ABORT)
1557 * here, we are in a transaction block which aborted and since the
1558 * AbortTransaction() was already done, we do whatever is needed
1559 * and change to the special "END ABORT" state. The upcoming
1560 * CommitTransactionCommand() will recognise this and then put us
1561 * back in the default state.
1563 s->blockState = TBLOCK_ENDABORT;
1568 * here, the user issued COMMIT when not inside a transaction. Issue a
1569 * WARNING and go to abort state. The upcoming call to
1570 * CommitTransactionCommand() will then put us back into the default
1573 elog(WARNING, "COMMIT: no transaction in progress");
1575 s->blockState = TBLOCK_ENDABORT;
1578 /* --------------------------------
1579 * AbortTransactionBlock
1580 * --------------------------------
1584 AbortTransactionBlock(void)
1586 TransactionState s = CurrentTransactionState;
1589 * check the current transaction state
1591 if (s->blockState == TBLOCK_INPROGRESS)
1594 * here we were inside a transaction block something screwed up
1595 * inside the system so we enter the abort state, do the abort
1596 * processing and then return. We remain in the abort state until
1597 * we see an END TRANSACTION command.
1599 s->blockState = TBLOCK_ABORT;
1605 * here, the user issued ABORT when not inside a transaction. Issue a
1606 * WARNING and go to abort state. The upcoming call to
1607 * CommitTransactionCommand() will then put us back into the default
1610 elog(WARNING, "ROLLBACK: no transaction in progress");
1612 s->blockState = TBLOCK_ENDABORT;
1616 /* --------------------------------
1617 * UserAbortTransactionBlock
1618 * --------------------------------
1621 UserAbortTransactionBlock(void)
1623 TransactionState s = CurrentTransactionState;
1626 * if the transaction has already been automatically aborted with an
1627 * error, and the user subsequently types 'abort', allow it. (the
1628 * behavior is the same as if they had typed 'end'.)
1630 if (s->blockState == TBLOCK_ABORT)
1632 s->blockState = TBLOCK_ENDABORT;
1636 if (s->blockState == TBLOCK_INPROGRESS)
1639 * here we were inside a transaction block and we got an abort
1640 * command from the user, so we move to the abort state, do the
1641 * abort processing and then change to the ENDABORT state so we
1642 * will end up in the default state after the upcoming
1643 * CommitTransactionCommand().
1645 s->blockState = TBLOCK_ABORT;
1647 s->blockState = TBLOCK_ENDABORT;
1652 * here, the user issued ABORT when not inside a transaction. Issue a
1653 * WARNING and go to abort state. The upcoming call to
1654 * CommitTransactionCommand() will then put us back into the default
1657 elog(WARNING, "ROLLBACK: no transaction in progress");
1659 s->blockState = TBLOCK_ENDABORT;
1662 /* --------------------------------
1663 * AbortOutOfAnyTransaction
1665 * This routine is provided for error recovery purposes. It aborts any
1666 * active transaction or transaction block, leaving the system in a known
1668 * --------------------------------
1671 AbortOutOfAnyTransaction(void)
1673 TransactionState s = CurrentTransactionState;
1676 * Get out of any low-level transaction
1681 case TRANS_INPROGRESS:
1683 /* In a transaction, so clean up */
1685 CleanupTransaction();
1688 /* AbortTransaction already done, still need Cleanup */
1689 CleanupTransaction();
1692 /* Not in a transaction, do nothing */
1697 * Now reset the high-level state
1699 s->blockState = TBLOCK_DEFAULT;
1703 IsTransactionBlock(void)
1705 TransactionState s = CurrentTransactionState;
1707 if (s->blockState == TBLOCK_INPROGRESS
1708 || s->blockState == TBLOCK_ABORT
1709 || s->blockState == TBLOCK_ENDABORT)
1717 * XLOG support routines
1721 xact_redo(XLogRecPtr lsn, XLogRecord *record)
1723 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1725 if (info == XLOG_XACT_COMMIT)
1727 TransactionIdCommit(record->xl_xid);
1728 /* SHOULD REMOVE FILES OF ALL DROPPED RELATIONS */
1730 else if (info == XLOG_XACT_ABORT)
1732 TransactionIdAbort(record->xl_xid);
1733 /* SHOULD REMOVE FILES OF ALL FAILED-TO-BE-CREATED RELATIONS */
1736 elog(PANIC, "xact_redo: unknown op code %u", info);
1740 xact_undo(XLogRecPtr lsn, XLogRecord *record)
1742 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1744 if (info == XLOG_XACT_COMMIT) /* shouldn't be called by XLOG */
1745 elog(PANIC, "xact_undo: can't undo committed xaction");
1746 else if (info != XLOG_XACT_ABORT)
1747 elog(PANIC, "xact_redo: unknown op code %u", info);
1751 xact_desc(char *buf, uint8 xl_info, char *rec)
1753 uint8 info = xl_info & ~XLR_INFO_MASK;
1755 if (info == XLOG_XACT_COMMIT)
1757 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
1758 struct tm *tm = localtime(&xlrec->xtime);
1760 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
1761 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1762 tm->tm_hour, tm->tm_min, tm->tm_sec);
1764 else if (info == XLOG_XACT_ABORT)
1766 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
1767 struct tm *tm = localtime(&xlrec->xtime);
1769 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
1770 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1771 tm->tm_hour, tm->tm_min, tm->tm_sec);
1774 strcat(buf, "UNKNOWN");
1778 XactPushRollback(void (*func) (void *), void *data)
1781 if (_RollbackFunc != NULL)
1782 elog(PANIC, "XactPushRollback: already installed");
1785 _RollbackFunc = func;
1786 _RollbackData = data;
1790 XactPopRollback(void)
1792 _RollbackFunc = NULL;