1
/*-------------------------------------------------------------------------
4
* top level transaction system support routines
6
* See src/backend/access/transam/README for more information.
8
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
9
* Portions Copyright (c) 1994, Regents of the University of California
15
*-------------------------------------------------------------------------
23
#include "access/multixact.h"
24
#include "access/subtrans.h"
25
#include "access/transam.h"
26
#include "access/twophase.h"
27
#include "access/xact.h"
28
#include "access/xlogutils.h"
29
#include "catalog/catalog.h"
30
#include "catalog/namespace.h"
31
#include "catalog/storage.h"
32
#include "commands/async.h"
33
#include "commands/tablecmds.h"
34
#include "commands/trigger.h"
35
#include "executor/spi.h"
36
#include "libpq/be-fsstubs.h"
37
#include "miscadmin.h"
39
#include "storage/bufmgr.h"
40
#include "storage/fd.h"
41
#include "storage/lmgr.h"
42
#include "storage/procarray.h"
43
#include "storage/sinvaladt.h"
44
#include "storage/smgr.h"
45
#include "utils/combocid.h"
46
#include "utils/flatfiles.h"
47
#include "utils/guc.h"
48
#include "utils/inval.h"
49
#include "utils/memutils.h"
50
#include "utils/relcache.h"
51
#include "utils/snapmgr.h"
52
#include "utils/xml.h"
57
* User-tweakable parameters
59
int DefaultXactIsoLevel = XACT_READ_COMMITTED;
62
bool DefaultXactReadOnly = false;
65
bool XactSyncCommit = true;
67
int CommitDelay = 0; /* precommit delay in microseconds */
68
int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
71
* MyXactAccessedTempRel is set when a temporary relation is accessed.
72
* We don't allow PREPARE TRANSACTION in that case. (This is global
73
* so that it can be set from heapam.c.)
75
bool MyXactAccessedTempRel = false;
79
* transaction states - transaction state from server perspective
81
typedef enum TransState
83
TRANS_DEFAULT, /* idle */
84
TRANS_START, /* transaction starting */
85
TRANS_INPROGRESS, /* inside a valid transaction */
86
TRANS_COMMIT, /* commit in progress */
87
TRANS_ABORT, /* abort in progress */
88
TRANS_PREPARE /* prepare in progress */
92
* transaction block states - transaction state of client queries
94
* Note: the subtransaction states are used only for non-topmost
95
* transactions; the others appear only in the topmost transaction.
97
typedef enum TBlockState
99
/* not-in-transaction-block states */
100
TBLOCK_DEFAULT, /* idle */
101
TBLOCK_STARTED, /* running single-query transaction */
103
/* transaction block states */
104
TBLOCK_BEGIN, /* starting transaction block */
105
TBLOCK_INPROGRESS, /* live transaction */
106
TBLOCK_END, /* COMMIT received */
107
TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
108
TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
109
TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
110
TBLOCK_PREPARE, /* live xact, PREPARE received */
112
/* subtransaction states */
113
TBLOCK_SUBBEGIN, /* starting a subtransaction */
114
TBLOCK_SUBINPROGRESS, /* live subtransaction */
115
TBLOCK_SUBEND, /* RELEASE received */
116
TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
117
TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
118
TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
119
TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
120
TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
124
* transaction state structure
126
typedef struct TransactionStateData
128
TransactionId transactionId; /* my XID, or Invalid if none */
129
SubTransactionId subTransactionId; /* my subxact ID */
130
char *name; /* savepoint name, if any */
131
int savepointLevel; /* savepoint level */
132
TransState state; /* low-level state */
133
TBlockState blockState; /* high-level state */
134
int nestingLevel; /* transaction nesting depth */
135
int gucNestLevel; /* GUC context nesting depth */
136
MemoryContext curTransactionContext; /* my xact-lifetime context */
137
ResourceOwner curTransactionOwner; /* my query resources */
138
TransactionId *childXids; /* subcommitted child XIDs, in XID order */
139
int nChildXids; /* # of subcommitted child XIDs */
140
int maxChildXids; /* allocated size of childXids[] */
141
Oid prevUser; /* previous CurrentUserId setting */
142
bool prevSecDefCxt; /* previous SecurityDefinerContext setting */
143
bool prevXactReadOnly; /* entry-time xact r/o state */
144
struct TransactionStateData *parent; /* back link to parent */
145
} TransactionStateData;
147
typedef TransactionStateData *TransactionState;
150
* CurrentTransactionState always points to the current transaction state
151
* block. It will point to TopTransactionStateData when not in a
152
* transaction at all, or when in a top-level transaction.
154
static TransactionStateData TopTransactionStateData = {
155
0, /* transaction id */
156
0, /* subtransaction id */
157
NULL, /* savepoint name */
158
0, /* savepoint level */
159
TRANS_DEFAULT, /* transaction state */
160
TBLOCK_DEFAULT, /* transaction block state from the client
162
0, /* transaction nesting depth */
163
0, /* GUC context nesting depth */
164
NULL, /* cur transaction context */
165
NULL, /* cur transaction resource owner */
166
NULL, /* subcommitted child Xids */
167
0, /* # of subcommitted child Xids */
168
0, /* allocated size of childXids[] */
169
InvalidOid, /* previous CurrentUserId setting */
170
false, /* previous SecurityDefinerContext setting */
171
false, /* entry-time xact r/o state */
172
NULL /* link to parent state block */
175
static TransactionState CurrentTransactionState = &TopTransactionStateData;
178
* The subtransaction ID and command ID assignment counters are global
179
* to a whole transaction, so we do not keep them in the state stack.
181
static SubTransactionId currentSubTransactionId;
182
static CommandId currentCommandId;
183
static bool currentCommandIdUsed;
186
* xactStartTimestamp is the value of transaction_timestamp().
187
* stmtStartTimestamp is the value of statement_timestamp().
188
* xactStopTimestamp is the time at which we log a commit or abort WAL record.
189
* These do not change as we enter and exit subtransactions, so we don't
190
* keep them inside the TransactionState stack.
192
static TimestampTz xactStartTimestamp;
193
static TimestampTz stmtStartTimestamp;
194
static TimestampTz xactStopTimestamp;
197
* GID to be used for preparing the current transaction. This is also
198
* global to a whole transaction, so we don't keep it in the state stack.
200
static char *prepareGID;
203
* Some commands want to force synchronous commit.
205
static bool forceSyncCommit = false;
208
* Private context for transaction-abort work --- we reserve space for this
209
* at startup to ensure that AbortTransaction and AbortSubTransaction can work
210
* when we've run out of memory.
212
static MemoryContext TransactionAbortContext = NULL;
215
* List of add-on start- and end-of-xact callbacks
217
typedef struct XactCallbackItem
219
struct XactCallbackItem *next;
220
XactCallback callback;
224
static XactCallbackItem *Xact_callbacks = NULL;
227
* List of add-on start- and end-of-subxact callbacks
229
typedef struct SubXactCallbackItem
231
struct SubXactCallbackItem *next;
232
SubXactCallback callback;
234
} SubXactCallbackItem;
236
static SubXactCallbackItem *SubXact_callbacks = NULL;
239
/* local function prototypes */
240
static void AssignTransactionId(TransactionState s);
241
static void AbortTransaction(void);
242
static void AtAbort_Memory(void);
243
static void AtCleanup_Memory(void);
244
static void AtAbort_ResourceOwner(void);
245
static void AtCommit_LocalCache(void);
246
static void AtCommit_Memory(void);
247
static void AtStart_Cache(void);
248
static void AtStart_Memory(void);
249
static void AtStart_ResourceOwner(void);
250
static void CallXactCallbacks(XactEvent event);
251
static void CallSubXactCallbacks(SubXactEvent event,
252
SubTransactionId mySubid,
253
SubTransactionId parentSubid);
254
static void CleanupTransaction(void);
255
static void CommitTransaction(void);
256
static TransactionId RecordTransactionAbort(bool isSubXact);
257
static void StartTransaction(void);
259
static void StartSubTransaction(void);
260
static void CommitSubTransaction(void);
261
static void AbortSubTransaction(void);
262
static void CleanupSubTransaction(void);
263
static void PushTransaction(void);
264
static void PopTransaction(void);
266
static void AtSubAbort_Memory(void);
267
static void AtSubCleanup_Memory(void);
268
static void AtSubAbort_ResourceOwner(void);
269
static void AtSubCommit_Memory(void);
270
static void AtSubStart_Memory(void);
271
static void AtSubStart_ResourceOwner(void);
273
static void ShowTransactionState(const char *str);
274
static void ShowTransactionStateRec(TransactionState state);
275
static const char *BlockStateAsString(TBlockState blockState);
276
static const char *TransStateAsString(TransState state);
279
/* ----------------------------------------------------------------
280
* transaction state accessors
281
* ----------------------------------------------------------------
287
* This returns true if we are inside a valid transaction; that is,
288
* it is safe to initiate database access, take heavyweight locks, etc.
291
IsTransactionState(void)
293
TransactionState s = CurrentTransactionState;
296
* TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we
297
* also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
298
* TRANS_PREPARE since it might be too soon or too late within those
299
* transition states to do anything interesting. Hence, the only "valid"
300
* state is TRANS_INPROGRESS.
302
return (s->state == TRANS_INPROGRESS);
306
* IsAbortedTransactionBlockState
308
* This returns true if we are currently running a query
309
* within an aborted transaction block.
312
IsAbortedTransactionBlockState(void)
314
TransactionState s = CurrentTransactionState;
316
if (s->blockState == TBLOCK_ABORT ||
317
s->blockState == TBLOCK_SUBABORT)
325
* GetTopTransactionId
327
* This will return the XID of the main transaction, assigning one if
328
* it's not yet set. Be careful to call this only inside a valid xact.
331
GetTopTransactionId(void)
333
if (!TransactionIdIsValid(TopTransactionStateData.transactionId))
334
AssignTransactionId(&TopTransactionStateData);
335
return TopTransactionStateData.transactionId;
339
* GetTopTransactionIdIfAny
341
* This will return the XID of the main transaction, if one is assigned.
342
* It will return InvalidTransactionId if we are not currently inside a
343
* transaction, or inside a transaction that hasn't yet been assigned an XID.
346
GetTopTransactionIdIfAny(void)
348
return TopTransactionStateData.transactionId;
352
* GetCurrentTransactionId
354
* This will return the XID of the current transaction (main or sub
355
* transaction), assigning one if it's not yet set. Be careful to call this
356
* only inside a valid xact.
359
GetCurrentTransactionId(void)
361
TransactionState s = CurrentTransactionState;
363
if (!TransactionIdIsValid(s->transactionId))
364
AssignTransactionId(s);
365
return s->transactionId;
369
* GetCurrentTransactionIdIfAny
371
* This will return the XID of the current sub xact, if one is assigned.
372
* It will return InvalidTransactionId if we are not currently inside a
373
* transaction, or inside a transaction that hasn't been assigned an XID yet.
376
GetCurrentTransactionIdIfAny(void)
378
return CurrentTransactionState->transactionId;
383
* AssignTransactionId
385
* Assigns a new permanent XID to the given TransactionState.
386
* We do not assign XIDs to transactions until/unless this is called.
387
* Also, any parent TransactionStates that don't yet have XIDs are assigned
388
* one; this maintains the invariant that a child transaction has an XID
389
* following its parent's.
392
AssignTransactionId(TransactionState s)
394
bool isSubXact = (s->parent != NULL);
395
ResourceOwner currentOwner;
397
/* Assert that caller didn't screw up */
398
Assert(!TransactionIdIsValid(s->transactionId));
399
Assert(s->state == TRANS_INPROGRESS);
402
* Ensure parent(s) have XIDs, so that a child always has an XID later
405
if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
406
AssignTransactionId(s->parent);
409
* Generate a new Xid and record it in PG_PROC and pg_subtrans.
411
* NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
412
* shared storage other than PG_PROC; because if there's no room for it in
413
* PG_PROC, the subtrans entry is needed to ensure that other backends see
414
* the Xid as "running". See GetNewTransactionId.
416
s->transactionId = GetNewTransactionId(isSubXact);
419
SubTransSetParent(s->transactionId, s->parent->transactionId);
422
* Acquire lock on the transaction XID. (We assume this cannot block.) We
423
* have to ensure that the lock is assigned to the transaction's own
426
currentOwner = CurrentResourceOwner;
429
CurrentResourceOwner = s->curTransactionOwner;
430
XactLockTableInsert(s->transactionId);
434
/* Ensure CurrentResourceOwner is restored on error */
435
CurrentResourceOwner = currentOwner;
439
CurrentResourceOwner = currentOwner;
444
* GetCurrentSubTransactionId
447
GetCurrentSubTransactionId(void)
449
TransactionState s = CurrentTransactionState;
451
return s->subTransactionId;
456
* GetCurrentCommandId
458
* "used" must be TRUE if the caller intends to use the command ID to mark
459
* inserted/updated/deleted tuples. FALSE means the ID is being fetched
460
* for read-only purposes (ie, as a snapshot validity cutoff). See
461
* CommandCounterIncrement() for discussion.
464
GetCurrentCommandId(bool used)
466
/* this is global to a transaction, not subtransaction-local */
468
currentCommandIdUsed = true;
469
return currentCommandId;
473
* GetCurrentTransactionStartTimestamp
476
GetCurrentTransactionStartTimestamp(void)
478
return xactStartTimestamp;
482
* GetCurrentStatementStartTimestamp
485
GetCurrentStatementStartTimestamp(void)
487
return stmtStartTimestamp;
491
* GetCurrentTransactionStopTimestamp
493
* We return current time if the transaction stop time hasn't been set
494
* (which can happen if we decide we don't need to log an XLOG record).
497
GetCurrentTransactionStopTimestamp(void)
499
if (xactStopTimestamp != 0)
500
return xactStopTimestamp;
501
return GetCurrentTimestamp();
505
* SetCurrentStatementStartTimestamp
508
SetCurrentStatementStartTimestamp(void)
510
stmtStartTimestamp = GetCurrentTimestamp();
514
* SetCurrentTransactionStopTimestamp
517
SetCurrentTransactionStopTimestamp(void)
519
xactStopTimestamp = GetCurrentTimestamp();
523
* GetCurrentTransactionNestLevel
525
* Note: this will return zero when not inside any transaction, one when
526
* inside a top-level transaction, etc.
529
GetCurrentTransactionNestLevel(void)
531
TransactionState s = CurrentTransactionState;
533
return s->nestingLevel;
538
* TransactionIdIsCurrentTransactionId
541
TransactionIdIsCurrentTransactionId(TransactionId xid)
546
* We always say that BootstrapTransactionId is "not my transaction ID"
547
* even when it is (ie, during bootstrap). Along with the fact that
548
* transam.c always treats BootstrapTransactionId as already committed,
549
* this causes the tqual.c routines to see all tuples as committed, which
550
* is what we need during bootstrap. (Bootstrap mode only inserts tuples,
551
* it never updates or deletes them, so all tuples can be presumed good
554
* Likewise, InvalidTransactionId and FrozenTransactionId are certainly
555
* not my transaction ID, so we can just return "false" immediately for
556
* any non-normal XID.
558
if (!TransactionIdIsNormal(xid))
562
* We will return true for the Xid of the current subtransaction, any of
563
* its subcommitted children, any of its parents, or any of their
564
* previously subcommitted children. However, a transaction being aborted
565
* is no longer "current", even though it may still have an entry on the
568
for (s = CurrentTransactionState; s != NULL; s = s->parent)
572
if (s->state == TRANS_ABORT)
574
if (!TransactionIdIsValid(s->transactionId))
575
continue; /* it can't have any child XIDs either */
576
if (TransactionIdEquals(xid, s->transactionId))
578
/* As the childXids array is ordered, we can use binary search */
580
high = s->nChildXids - 1;
586
middle = low + (high - low) / 2;
587
probe = s->childXids[middle];
588
if (TransactionIdEquals(probe, xid))
590
else if (TransactionIdPrecedes(probe, xid))
602
* CommandCounterIncrement
605
CommandCounterIncrement(void)
608
* If the current value of the command counter hasn't been "used" to
609
* mark tuples, we need not increment it, since there's no need to
610
* distinguish a read-only command from others. This helps postpone
611
* command counter overflow, and keeps no-op CommandCounterIncrement
614
if (currentCommandIdUsed)
616
currentCommandId += 1;
617
if (currentCommandId == FirstCommandId) /* check for overflow */
619
currentCommandId -= 1;
621
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
622
errmsg("cannot have more than 2^32-1 commands in a transaction")));
624
currentCommandIdUsed = false;
626
/* Propagate new command ID into static snapshots */
627
SnapshotSetCommandId(currentCommandId);
630
* Make any catalog changes done by the just-completed command
631
* visible in the local syscache. We obviously don't need to do
632
* this after a read-only command. (But see hacks in inval.c
633
* to make real sure we don't think a command that queued inval
634
* messages was read-only.)
636
AtCommit_LocalCache();
640
* Make any other backends' catalog changes visible to me.
642
* XXX this is probably in the wrong place: CommandCounterIncrement
643
* should be purely a local operation, most likely. However fooling
644
* with this will affect asynchronous cross-backend interactions,
645
* which doesn't seem like a wise thing to do in late beta, so save
646
* improving this for another day - tgl 2007-11-30
654
* Interface routine to allow commands to force a synchronous commit of the
655
* current top-level transaction
658
ForceSyncCommit(void)
660
forceSyncCommit = true;
664
/* ----------------------------------------------------------------
665
* StartTransaction stuff
666
* ----------------------------------------------------------------
675
AcceptInvalidationMessages();
684
TransactionState s = CurrentTransactionState;
687
* If this is the first time through, create a private context for
688
* AbortTransaction to work in. By reserving some space now, we can
689
* insulate AbortTransaction from out-of-memory scenarios. Like
690
* ErrorContext, we set it up with slow growth rate and a nonzero minimum
691
* size, so that space will be reserved immediately.
693
if (TransactionAbortContext == NULL)
694
TransactionAbortContext =
695
AllocSetContextCreate(TopMemoryContext,
696
"TransactionAbortContext",
702
* We shouldn't have a transaction context already.
704
Assert(TopTransactionContext == NULL);
707
* Create a toplevel context for the transaction.
709
TopTransactionContext =
710
AllocSetContextCreate(TopMemoryContext,
711
"TopTransactionContext",
712
ALLOCSET_DEFAULT_MINSIZE,
713
ALLOCSET_DEFAULT_INITSIZE,
714
ALLOCSET_DEFAULT_MAXSIZE);
717
* In a top-level transaction, CurTransactionContext is the same as
718
* TopTransactionContext.
720
CurTransactionContext = TopTransactionContext;
721
s->curTransactionContext = CurTransactionContext;
723
/* Make the CurTransactionContext active. */
724
MemoryContextSwitchTo(CurTransactionContext);
728
* AtStart_ResourceOwner
731
AtStart_ResourceOwner(void)
733
TransactionState s = CurrentTransactionState;
736
* We shouldn't have a transaction resource owner already.
738
Assert(TopTransactionResourceOwner == NULL);
741
* Create a toplevel resource owner for the transaction.
743
s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
745
TopTransactionResourceOwner = s->curTransactionOwner;
746
CurTransactionResourceOwner = s->curTransactionOwner;
747
CurrentResourceOwner = s->curTransactionOwner;
750
/* ----------------------------------------------------------------
751
* StartSubTransaction stuff
752
* ----------------------------------------------------------------
759
AtSubStart_Memory(void)
761
TransactionState s = CurrentTransactionState;
763
Assert(CurTransactionContext != NULL);
766
* Create a CurTransactionContext, which will be used to hold data that
767
* survives subtransaction commit but disappears on subtransaction abort.
768
* We make it a child of the immediate parent's CurTransactionContext.
770
CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
771
"CurTransactionContext",
772
ALLOCSET_DEFAULT_MINSIZE,
773
ALLOCSET_DEFAULT_INITSIZE,
774
ALLOCSET_DEFAULT_MAXSIZE);
775
s->curTransactionContext = CurTransactionContext;
777
/* Make the CurTransactionContext active. */
778
MemoryContextSwitchTo(CurTransactionContext);
782
* AtSubStart_ResourceOwner
785
AtSubStart_ResourceOwner(void)
787
TransactionState s = CurrentTransactionState;
789
Assert(s->parent != NULL);
792
* Create a resource owner for the subtransaction. We make it a child of
793
* the immediate parent's resource owner.
795
s->curTransactionOwner =
796
ResourceOwnerCreate(s->parent->curTransactionOwner,
799
CurTransactionResourceOwner = s->curTransactionOwner;
800
CurrentResourceOwner = s->curTransactionOwner;
803
/* ----------------------------------------------------------------
804
* CommitTransaction stuff
805
* ----------------------------------------------------------------
809
* RecordTransactionCommit
811
* Returns latest XID among xact and its children, or InvalidTransactionId
812
* if the xact has no XID. (We compute that here just because it's easier.)
814
* This is exported only to support an ugly hack in VACUUM FULL.
817
RecordTransactionCommit(void)
819
TransactionId xid = GetTopTransactionIdIfAny();
820
bool markXidCommitted = TransactionIdIsValid(xid);
821
TransactionId latestXid = InvalidTransactionId;
826
TransactionId *children;
828
/* Get data needed for commit record */
829
nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
830
nchildren = xactGetCommittedChildren(&children);
833
* If we haven't been assigned an XID yet, we neither can, nor do we want
834
* to write a COMMIT record.
836
if (!markXidCommitted)
839
* We expect that every smgrscheduleunlink is followed by a catalog
840
* update, and hence XID assignment, so we shouldn't get here with any
841
* pending deletes. Use a real test not just an Assert to check this,
842
* since it's a bit fragile.
845
elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
847
/* Can't have child XIDs either; AssignTransactionId enforces this */
848
Assert(nchildren == 0);
851
* If we didn't create XLOG entries, we're done here; otherwise we
852
* should flush those entries the same as a commit record. (An
853
* example of a possible record that wouldn't cause an XID to be
854
* assigned is a sequence advance record due to nextval() --- we want
855
* to flush that to disk before reporting commit.)
857
if (XactLastRecEnd.xrecoff == 0)
863
* Begin commit critical section and insert the commit XLOG record.
865
XLogRecData rdata[3];
867
xl_xact_commit xlrec;
869
/* Tell bufmgr and smgr to prepare for commit */
873
* Mark ourselves as within our "commit critical section". This
874
* forces any concurrent checkpoint to wait until we've updated
875
* pg_clog. Without this, it is possible for the checkpoint to set
876
* REDO after the XLOG record but fail to flush the pg_clog update to
877
* disk, leading to loss of the transaction commit if the system
878
* crashes a little later.
880
* Note: we could, but don't bother to, set this flag in
881
* RecordTransactionAbort. That's because loss of a transaction abort
882
* is noncritical; the presumption would be that it aborted, anyway.
884
* It's safe to change the inCommit flag of our own backend without
885
* holding the ProcArrayLock, since we're the only one modifying it.
886
* This makes checkpoint's determination of which xacts are inCommit a
887
* bit fuzzy, but it doesn't matter.
889
START_CRIT_SECTION();
890
MyProc->inCommit = true;
892
SetCurrentTransactionStopTimestamp();
893
xlrec.xact_time = xactStopTimestamp;
895
xlrec.nsubxacts = nchildren;
896
rdata[0].data = (char *) (&xlrec);
897
rdata[0].len = MinSizeOfXactCommit;
898
rdata[0].buffer = InvalidBuffer;
899
/* dump rels to delete */
902
rdata[0].next = &(rdata[1]);
903
rdata[1].data = (char *) rels;
904
rdata[1].len = nrels * sizeof(RelFileNode);
905
rdata[1].buffer = InvalidBuffer;
908
/* dump committed child Xids */
911
rdata[lastrdata].next = &(rdata[2]);
912
rdata[2].data = (char *) children;
913
rdata[2].len = nchildren * sizeof(TransactionId);
914
rdata[2].buffer = InvalidBuffer;
917
rdata[lastrdata].next = NULL;
919
(void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
923
* Check if we want to commit asynchronously. If the user has set
924
* synchronous_commit = off, and we're not doing cleanup of any non-temp
925
* rels nor committing any command that wanted to force sync commit, then
926
* we can defer flushing XLOG. (We must not allow asynchronous commit if
927
* there are any non-temp tables to be deleted, because we might delete
928
* the files before the COMMIT record is flushed to disk. We do allow
929
* asynchronous commit if all to-be-deleted tables are temporary though,
930
* since they are lost anyway if we crash.)
932
if (XactSyncCommit || forceSyncCommit || haveNonTemp)
935
* Synchronous commit case.
937
* Sleep before flush! So we can flush more than one commit records
938
* per single fsync. (The idea is some other backend may do the
939
* XLogFlush while we're sleeping. This needs work still, because on
940
* most Unixen, the minimum select() delay is 10msec or more, which is
943
* We do not sleep if enableFsync is not turned on, nor if there are
944
* fewer than CommitSiblings other backends with active transactions.
946
if (CommitDelay > 0 && enableFsync &&
947
CountActiveBackends() >= CommitSiblings)
948
pg_usleep(CommitDelay);
950
XLogFlush(XactLastRecEnd);
953
* Now we may update the CLOG, if we wrote a COMMIT record above
955
if (markXidCommitted)
956
TransactionIdCommitTree(xid, nchildren, children);
961
* Asynchronous commit case.
963
* Report the latest async commit LSN, so that the WAL writer knows to
966
XLogSetAsyncCommitLSN(XactLastRecEnd);
969
* We must not immediately update the CLOG, since we didn't flush the
970
* XLOG. Instead, we store the LSN up to which the XLOG must be
971
* flushed before the CLOG may be updated.
973
if (markXidCommitted)
974
TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
978
* If we entered a commit critical section, leave it now, and let
979
* checkpoints proceed.
981
if (markXidCommitted)
983
MyProc->inCommit = false;
987
/* Compute latestXid while we have the child XIDs handy */
988
latestXid = TransactionIdLatest(xid, nchildren, children);
990
/* Reset XactLastRecEnd until the next transaction writes something */
991
XactLastRecEnd.xrecoff = 0;
994
/* Clean up local data */
1003
* AtCommit_LocalCache
1006
AtCommit_LocalCache(void)
1009
* Make catalog changes visible to me for the next command.
1011
CommandEndInvalidationMessages();
1018
AtCommit_Memory(void)
1021
* Now that we're "out" of a transaction, have the system allocate things
1022
* in the top memory context instead of per-transaction contexts.
1024
MemoryContextSwitchTo(TopMemoryContext);
1027
* Release all transaction-local memory.
1029
Assert(TopTransactionContext != NULL);
1030
MemoryContextDelete(TopTransactionContext);
1031
TopTransactionContext = NULL;
1032
CurTransactionContext = NULL;
1033
CurrentTransactionState->curTransactionContext = NULL;
1036
/* ----------------------------------------------------------------
1037
* CommitSubTransaction stuff
1038
* ----------------------------------------------------------------
1042
* AtSubCommit_Memory
1045
AtSubCommit_Memory(void)
1047
TransactionState s = CurrentTransactionState;
1049
Assert(s->parent != NULL);
1051
/* Return to parent transaction level's memory context. */
1052
CurTransactionContext = s->parent->curTransactionContext;
1053
MemoryContextSwitchTo(CurTransactionContext);
1056
* Ordinarily we cannot throw away the child's CurTransactionContext,
1057
* since the data it contains will be needed at upper commit. However, if
1058
* there isn't actually anything in it, we can throw it away. This avoids
1059
* a small memory leak in the common case of "trivial" subxacts.
1061
if (MemoryContextIsEmpty(s->curTransactionContext))
1063
MemoryContextDelete(s->curTransactionContext);
1064
s->curTransactionContext = NULL;
1069
* AtSubCommit_childXids
1071
* Pass my own XID and my child XIDs up to my parent as committed children.
1074
AtSubCommit_childXids(void)
1076
TransactionState s = CurrentTransactionState;
1079
Assert(s->parent != NULL);
1082
* The parent childXids array will need to hold my XID and all my
1083
* childXids, in addition to the XIDs already there.
1085
new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
1087
/* Allocate or enlarge the parent array if necessary */
1088
if (s->parent->maxChildXids < new_nChildXids)
1090
int new_maxChildXids;
1091
TransactionId *new_childXids;
1094
* Make it 2x what's needed right now, to avoid having to enlarge it
1095
* repeatedly. But we can't go above MaxAllocSize. (The latter
1096
* limit is what ensures that we don't need to worry about integer
1097
* overflow here or in the calculation of new_nChildXids.)
1099
new_maxChildXids = Min(new_nChildXids * 2,
1100
(int) (MaxAllocSize / sizeof(TransactionId)));
1102
if (new_maxChildXids < new_nChildXids)
1104
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1105
errmsg("maximum number of committed subtransactions (%d) exceeded",
1106
(int) (MaxAllocSize / sizeof(TransactionId)))));
1109
* We keep the child-XID arrays in TopTransactionContext; this avoids
1110
* setting up child-transaction contexts for what might be just a few
1111
* bytes of grandchild XIDs.
1113
if (s->parent->childXids == NULL)
1115
MemoryContextAlloc(TopTransactionContext,
1116
new_maxChildXids * sizeof(TransactionId));
1118
new_childXids = repalloc(s->parent->childXids,
1119
new_maxChildXids * sizeof(TransactionId));
1121
s->parent->childXids = new_childXids;
1122
s->parent->maxChildXids = new_maxChildXids;
1126
* Copy all my XIDs to parent's array.
1128
* Note: We rely on the fact that the XID of a child always follows that
1129
* of its parent. By copying the XID of this subtransaction before the
1130
* XIDs of its children, we ensure that the array stays ordered. Likewise,
1131
* all XIDs already in the array belong to subtransactions started and
1132
* subcommitted before us, so their XIDs must precede ours.
1134
s->parent->childXids[s->parent->nChildXids] = s->transactionId;
1136
if (s->nChildXids > 0)
1137
memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
1139
s->nChildXids * sizeof(TransactionId));
1141
s->parent->nChildXids = new_nChildXids;
1143
/* Release child's array to avoid leakage */
1144
if (s->childXids != NULL)
1145
pfree(s->childXids);
1146
/* We must reset these to avoid double-free if fail later in commit */
1147
s->childXids = NULL;
1149
s->maxChildXids = 0;
1152
/* ----------------------------------------------------------------
1153
* AbortTransaction stuff
1154
* ----------------------------------------------------------------
1158
* RecordTransactionAbort
1160
* Returns latest XID among xact and its children, or InvalidTransactionId
1161
* if the xact has no XID. (We compute that here just because it's easier.)
1163
static TransactionId
1164
RecordTransactionAbort(bool isSubXact)
1166
TransactionId xid = GetCurrentTransactionIdIfAny();
1167
TransactionId latestXid;
1171
TransactionId *children;
1172
XLogRecData rdata[3];
1174
xl_xact_abort xlrec;
1177
* If we haven't been assigned an XID, nobody will care whether we aborted
1178
* or not. Hence, we're done in that case. It does not matter if we have
1179
* rels to delete (note that this routine is not responsible for actually
1180
* deleting 'em). We cannot have any child XIDs, either.
1182
if (!TransactionIdIsValid(xid))
1184
/* Reset XactLastRecEnd until the next transaction writes something */
1186
XactLastRecEnd.xrecoff = 0;
1187
return InvalidTransactionId;
1191
* We have a valid XID, so we should write an ABORT record for it.
1193
* We do not flush XLOG to disk here, since the default assumption after a
1194
* crash would be that we aborted, anyway. For the same reason, we don't
1195
* need to worry about interlocking against checkpoint start.
1199
* Check that we haven't aborted halfway through RecordTransactionCommit.
1201
if (TransactionIdDidCommit(xid))
1202
elog(PANIC, "cannot abort transaction %u, it was already committed",
1205
/* Fetch the data we need for the abort record */
1206
nrels = smgrGetPendingDeletes(false, &rels, NULL);
1207
nchildren = xactGetCommittedChildren(&children);
1209
/* XXX do we really need a critical section here? */
1210
START_CRIT_SECTION();
1212
/* Write the ABORT record */
1214
xlrec.xact_time = GetCurrentTimestamp();
1217
SetCurrentTransactionStopTimestamp();
1218
xlrec.xact_time = xactStopTimestamp;
1220
xlrec.nrels = nrels;
1221
xlrec.nsubxacts = nchildren;
1222
rdata[0].data = (char *) (&xlrec);
1223
rdata[0].len = MinSizeOfXactAbort;
1224
rdata[0].buffer = InvalidBuffer;
1225
/* dump rels to delete */
1228
rdata[0].next = &(rdata[1]);
1229
rdata[1].data = (char *) rels;
1230
rdata[1].len = nrels * sizeof(RelFileNode);
1231
rdata[1].buffer = InvalidBuffer;
1234
/* dump committed child Xids */
1237
rdata[lastrdata].next = &(rdata[2]);
1238
rdata[2].data = (char *) children;
1239
rdata[2].len = nchildren * sizeof(TransactionId);
1240
rdata[2].buffer = InvalidBuffer;
1243
rdata[lastrdata].next = NULL;
1245
(void) XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1248
* Mark the transaction aborted in clog. This is not absolutely necessary
1249
* but we may as well do it while we are here; also, in the subxact case
1250
* it is helpful because XactLockTableWait makes use of it to avoid
1251
* waiting for already-aborted subtransactions. It is OK to do it without
1252
* having flushed the ABORT record to disk, because in event of a crash
1253
* we'd be assumed to have aborted anyway.
1255
TransactionIdAbortTree(xid, nchildren, children);
1259
/* Compute latestXid while we have the child XIDs handy */
1260
latestXid = TransactionIdLatest(xid, nchildren, children);
1263
* If we're aborting a subtransaction, we can immediately remove failed
1264
* XIDs from PGPROC's cache of running child XIDs. We do that here for
1265
* subxacts, because we already have the child XID array at hand. For
1266
* main xacts, the equivalent happens just after this function returns.
1269
XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1271
/* Reset XactLastRecEnd until the next transaction writes something */
1273
XactLastRecEnd.xrecoff = 0;
1275
/* And clean up local data */
1286
AtAbort_Memory(void)
1289
* Switch into TransactionAbortContext, which should have some free space
1290
* even if nothing else does. We'll work in this context until we've
1291
* finished cleaning up.
1293
* It is barely possible to get here when we've not been able to create
1294
* TransactionAbortContext yet; if so use TopMemoryContext.
1296
if (TransactionAbortContext != NULL)
1297
MemoryContextSwitchTo(TransactionAbortContext);
1299
MemoryContextSwitchTo(TopMemoryContext);
1306
AtSubAbort_Memory(void)
1308
Assert(TransactionAbortContext != NULL);
1310
MemoryContextSwitchTo(TransactionAbortContext);
1315
* AtAbort_ResourceOwner
1318
AtAbort_ResourceOwner(void)
1321
* Make sure we have a valid ResourceOwner, if possible (else it will be
1322
* NULL, which is OK)
1324
CurrentResourceOwner = TopTransactionResourceOwner;
1328
* AtSubAbort_ResourceOwner
1331
AtSubAbort_ResourceOwner(void)
1333
TransactionState s = CurrentTransactionState;
1335
/* Make sure we have a valid ResourceOwner */
1336
CurrentResourceOwner = s->curTransactionOwner;
1341
* AtSubAbort_childXids
1344
AtSubAbort_childXids(void)
1346
TransactionState s = CurrentTransactionState;
1349
* We keep the child-XID arrays in TopTransactionContext (see
1350
* AtSubCommit_childXids). This means we'd better free the array
1351
* explicitly at abort to avoid leakage.
1353
if (s->childXids != NULL)
1354
pfree(s->childXids);
1355
s->childXids = NULL;
1357
s->maxChildXids = 0;
1360
/* ----------------------------------------------------------------
1361
* CleanupTransaction stuff
1362
* ----------------------------------------------------------------
1369
AtCleanup_Memory(void)
1371
Assert(CurrentTransactionState->parent == NULL);
1374
* Now that we're "out" of a transaction, have the system allocate things
1375
* in the top memory context instead of per-transaction contexts.
1377
MemoryContextSwitchTo(TopMemoryContext);
1380
* Clear the special abort context for next time.
1382
if (TransactionAbortContext != NULL)
1383
MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1386
* Release all transaction-local memory.
1388
if (TopTransactionContext != NULL)
1389
MemoryContextDelete(TopTransactionContext);
1390
TopTransactionContext = NULL;
1391
CurTransactionContext = NULL;
1392
CurrentTransactionState->curTransactionContext = NULL;
1396
/* ----------------------------------------------------------------
1397
* CleanupSubTransaction stuff
1398
* ----------------------------------------------------------------
1402
* AtSubCleanup_Memory
1405
AtSubCleanup_Memory(void)
1407
TransactionState s = CurrentTransactionState;
1409
Assert(s->parent != NULL);
1411
/* Make sure we're not in an about-to-be-deleted context */
1412
MemoryContextSwitchTo(s->parent->curTransactionContext);
1413
CurTransactionContext = s->parent->curTransactionContext;
1416
* Clear the special abort context for next time.
1418
if (TransactionAbortContext != NULL)
1419
MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1422
* Delete the subxact local memory contexts. Its CurTransactionContext can
1423
* go too (note this also kills CurTransactionContexts from any children
1426
if (s->curTransactionContext)
1427
MemoryContextDelete(s->curTransactionContext);
1428
s->curTransactionContext = NULL;
1431
/* ----------------------------------------------------------------
1432
* interface routines
1433
* ----------------------------------------------------------------
1440
StartTransaction(void)
1443
VirtualTransactionId vxid;
1446
* Let's just make sure the state stack is empty
1448
s = &TopTransactionStateData;
1449
CurrentTransactionState = s;
1452
* check the current transaction state
1454
if (s->state != TRANS_DEFAULT)
1455
elog(WARNING, "StartTransaction while in %s state",
1456
TransStateAsString(s->state));
1459
* set the current transaction state information appropriately during
1462
s->state = TRANS_START;
1463
s->transactionId = InvalidTransactionId; /* until assigned */
1466
* Make sure we've reset xact state variables
1468
XactIsoLevel = DefaultXactIsoLevel;
1469
XactReadOnly = DefaultXactReadOnly;
1470
forceSyncCommit = false;
1471
MyXactAccessedTempRel = false;
1474
* reinitialize within-transaction counters
1476
s->subTransactionId = TopSubTransactionId;
1477
currentSubTransactionId = TopSubTransactionId;
1478
currentCommandId = FirstCommandId;
1479
currentCommandIdUsed = false;
1482
* must initialize resource-management stuff first
1485
AtStart_ResourceOwner();
1488
* Assign a new LocalTransactionId, and combine it with the backendId to
1489
* form a virtual transaction id.
1491
vxid.backendId = MyBackendId;
1492
vxid.localTransactionId = GetNextLocalTransactionId();
1495
* Lock the virtual transaction id before we announce it in the proc array
1497
VirtualXactLockTableInsert(vxid);
1500
* Advertise it in the proc array. We assume assignment of
1501
* LocalTransactionID is atomic, and the backendId should be set already.
1503
Assert(MyProc->backendId == vxid.backendId);
1504
MyProc->lxid = vxid.localTransactionId;
1506
TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
1509
* set transaction_timestamp() (a/k/a now()). We want this to be the same
1510
* as the first command's statement_timestamp(), so don't do a fresh
1511
* GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1512
* xactStopTimestamp as unset.
1514
xactStartTimestamp = stmtStartTimestamp;
1515
xactStopTimestamp = 0;
1516
pgstat_report_xact_timestamp(xactStartTimestamp);
1519
* initialize current transaction state fields
1521
* note: prevXactReadOnly is not used at the outermost level
1523
s->nestingLevel = 1;
1524
s->gucNestLevel = 1;
1525
s->childXids = NULL;
1527
s->maxChildXids = 0;
1528
GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
1529
/* SecurityDefinerContext should never be set outside a transaction */
1530
Assert(!s->prevSecDefCxt);
1533
* initialize other subsystems for new transaction
1538
AfterTriggerBeginXact();
1541
* done with start processing, set current transaction state to "in
1544
s->state = TRANS_INPROGRESS;
1546
ShowTransactionState("StartTransaction");
1553
* NB: if you change this routine, better look at PrepareTransaction too!
1556
CommitTransaction(void)
1558
TransactionState s = CurrentTransactionState;
1559
TransactionId latestXid;
1561
ShowTransactionState("CommitTransaction");
1564
* check the current transaction state
1566
if (s->state != TRANS_INPROGRESS)
1567
elog(WARNING, "CommitTransaction while in %s state",
1568
TransStateAsString(s->state));
1569
Assert(s->parent == NULL);
1572
* Do pre-commit processing (most of this stuff requires database access,
1573
* and in fact could still cause an error...)
1575
* It is possible for CommitHoldablePortals to invoke functions that queue
1576
* deferred triggers, and it's also possible that triggers create holdable
1577
* cursors. So we have to loop until there's nothing left to do.
1582
* Fire all currently pending deferred triggers.
1584
AfterTriggerFireDeferred();
1587
* Convert any open holdable cursors into static portals. If there
1588
* weren't any, we are done ... otherwise loop back to check if they
1589
* queued deferred triggers. Lather, rinse, repeat.
1591
if (!CommitHoldablePortals())
1595
/* Now we can shut down the deferred-trigger manager */
1596
AfterTriggerEndXact(true);
1598
/* Close any open regular cursors */
1602
* Let ON COMMIT management do its thing (must happen after closing
1603
* cursors, to avoid dangling-reference problems)
1605
PreCommit_on_commit_actions();
1607
/* close large objects before lower-level cleanup */
1608
AtEOXact_LargeObject(true);
1610
/* NOTIFY commit must come before lower-level cleanup */
1614
* Update flat files if we changed pg_database, pg_authid or
1615
* pg_auth_members. This should be the last step before commit.
1617
AtEOXact_UpdateFlatFiles(true);
1619
/* Prevent cancel/die interrupt while cleaning up */
1623
* set the current transaction state information appropriately during
1626
s->state = TRANS_COMMIT;
1629
* Here is where we really truly commit.
1631
latestXid = RecordTransactionCommit();
1633
TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
1636
* Let others know about no transaction in progress by me. Note that this
1637
* must be done _before_ releasing locks we hold and _after_
1638
* RecordTransactionCommit.
1640
ProcArrayEndTransaction(MyProc, latestXid);
1643
* This is all post-commit cleanup. Note that if an error is raised here,
1644
* it's too late to abort the transaction. This should be just
1645
* noncritical resource releasing.
1647
* The ordering of operations is not entirely random. The idea is:
1648
* release resources visible to other backends (eg, files, buffer pins);
1649
* then release locks; then release backend-local resources. We want to
1650
* release locks at the point where any backend waiting for us will see
1651
* our transaction as being fully cleaned up.
1653
* Resources that can be associated with individual queries are handled by
1654
* the ResourceOwner mechanism. The other calls here are for backend-wide
1658
CallXactCallbacks(XACT_EVENT_COMMIT);
1660
ResourceOwnerRelease(TopTransactionResourceOwner,
1661
RESOURCE_RELEASE_BEFORE_LOCKS,
1664
/* Check we've released all buffer pins */
1665
AtEOXact_Buffers(true);
1667
/* Clean up the relation cache */
1668
AtEOXact_RelationCache(true);
1670
/* Clean up the snapshot manager */
1671
AtEarlyCommit_Snapshot();
1674
* Make catalog changes visible to all backends. This has to happen after
1675
* relcache references are dropped (see comments for
1676
* AtEOXact_RelationCache), but before locks are released (if anyone is
1677
* waiting for lock on a relation we've modified, we want them to know
1678
* about the catalog change before they start using the relation).
1680
AtEOXact_Inval(true);
1683
* Likewise, dropping of files deleted during the transaction is best done
1684
* after releasing relcache and buffer pins. (This is not strictly
1685
* necessary during commit, since such pins should have been released
1686
* already, but this ordering is definitely critical during abort.)
1688
smgrDoPendingDeletes(true);
1690
AtEOXact_MultiXact();
1692
ResourceOwnerRelease(TopTransactionResourceOwner,
1693
RESOURCE_RELEASE_LOCKS,
1695
ResourceOwnerRelease(TopTransactionResourceOwner,
1696
RESOURCE_RELEASE_AFTER_LOCKS,
1699
/* Check we've released all catcache entries */
1700
AtEOXact_CatCache(true);
1702
AtEOXact_GUC(true, 1);
1705
AtEOXact_on_commit_actions(true);
1706
AtEOXact_Namespace(true);
1707
/* smgrcommit already done */
1709
AtEOXact_ComboCid();
1710
AtEOXact_HashTables(true);
1711
AtEOXact_PgStat(true);
1712
AtEOXact_Snapshot(true);
1713
pgstat_report_xact_timestamp(0);
1715
CurrentResourceOwner = NULL;
1716
ResourceOwnerDelete(TopTransactionResourceOwner);
1717
s->curTransactionOwner = NULL;
1718
CurTransactionResourceOwner = NULL;
1719
TopTransactionResourceOwner = NULL;
1723
s->transactionId = InvalidTransactionId;
1724
s->subTransactionId = InvalidSubTransactionId;
1725
s->nestingLevel = 0;
1726
s->gucNestLevel = 0;
1727
s->childXids = NULL;
1729
s->maxChildXids = 0;
1732
* done with commit processing, set current transaction state back to
1735
s->state = TRANS_DEFAULT;
1737
RESUME_INTERRUPTS();
1742
* PrepareTransaction
1744
* NB: if you change this routine, better look at CommitTransaction too!
1747
PrepareTransaction(void)
1749
TransactionState s = CurrentTransactionState;
1750
TransactionId xid = GetCurrentTransactionId();
1751
GlobalTransaction gxact;
1752
TimestampTz prepared_at;
1754
ShowTransactionState("PrepareTransaction");
1757
* check the current transaction state
1759
if (s->state != TRANS_INPROGRESS)
1760
elog(WARNING, "PrepareTransaction while in %s state",
1761
TransStateAsString(s->state));
1762
Assert(s->parent == NULL);
1765
* Do pre-commit processing (most of this stuff requires database access,
1766
* and in fact could still cause an error...)
1768
* It is possible for PrepareHoldablePortals to invoke functions that
1769
* queue deferred triggers, and it's also possible that triggers create
1770
* holdable cursors. So we have to loop until there's nothing left to do.
1775
* Fire all currently pending deferred triggers.
1777
AfterTriggerFireDeferred();
1780
* Convert any open holdable cursors into static portals. If there
1781
* weren't any, we are done ... otherwise loop back to check if they
1782
* queued deferred triggers. Lather, rinse, repeat.
1784
if (!PrepareHoldablePortals())
1788
/* Now we can shut down the deferred-trigger manager */
1789
AfterTriggerEndXact(true);
1791
/* Close any open regular cursors */
1795
* Let ON COMMIT management do its thing (must happen after closing
1796
* cursors, to avoid dangling-reference problems)
1798
PreCommit_on_commit_actions();
1800
/* close large objects before lower-level cleanup */
1801
AtEOXact_LargeObject(true);
1803
/* NOTIFY and flatfiles will be handled below */
1806
* Don't allow PREPARE TRANSACTION if we've accessed a temporary table
1807
* in this transaction. Having the prepared xact hold locks on another
1808
* backend's temp table seems a bad idea --- for instance it would prevent
1809
* the backend from exiting. There are other problems too, such as how
1810
* to clean up the source backend's local buffers and ON COMMIT state
1811
* if the prepared xact includes a DROP of a temp table.
1813
* We must check this after executing any ON COMMIT actions, because
1814
* they might still access a temp relation.
1816
* XXX In principle this could be relaxed to allow some useful special
1817
* cases, such as a temp table created and dropped all within the
1818
* transaction. That seems to require much more bookkeeping though.
1820
if (MyXactAccessedTempRel)
1822
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1823
errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1825
/* Prevent cancel/die interrupt while cleaning up */
1829
* set the current transaction state information appropriately during
1830
* prepare processing
1832
s->state = TRANS_PREPARE;
1834
prepared_at = GetCurrentTimestamp();
1836
/* Tell bufmgr and smgr to prepare for commit */
1840
* Reserve the GID for this transaction. This could fail if the requested
1841
* GID is invalid or already in use.
1843
gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1844
GetUserId(), MyDatabaseId);
1848
* Collect data for the 2PC state file. Note that in general, no actual
1849
* state change should happen in the called modules during this step,
1850
* since it's still possible to fail before commit, and in that case we
1851
* want transaction abort to be able to clean up. (In particular, the
1852
* AtPrepare routines may error out if they find cases they cannot
1853
* handle.) State cleanup should happen in the PostPrepare routines
1854
* below. However, some modules can go ahead and clear state here because
1855
* they wouldn't do anything with it during abort anyway.
1857
* Note: because the 2PC state file records will be replayed in the same
1858
* order they are made, the order of these calls has to match the order in
1859
* which we want things to happen during COMMIT PREPARED or ROLLBACK
1860
* PREPARED; in particular, pay attention to whether things should happen
1861
* before or after releasing the transaction's locks.
1863
StartPrepare(gxact);
1866
AtPrepare_UpdateFlatFiles();
1872
* Here is where we really truly prepare.
1874
* We have to record transaction prepares even if we didn't make any
1875
* updates, because the transaction manager might get confused if we lose
1876
* a global transaction.
1881
* Now we clean up backend-internal state and release internal resources.
1884
/* Reset XactLastRecEnd until the next transaction writes something */
1885
XactLastRecEnd.xrecoff = 0;
1888
* Let others know about no transaction in progress by me. This has to be
1889
* done *after* the prepared transaction has been marked valid, else
1890
* someone may think it is unlocked and recyclable.
1892
ProcArrayClearTransaction(MyProc);
1895
* This is all post-transaction cleanup. Note that if an error is raised
1896
* here, it's too late to abort the transaction. This should be just
1897
* noncritical resource releasing. See notes in CommitTransaction.
1900
CallXactCallbacks(XACT_EVENT_PREPARE);
1902
ResourceOwnerRelease(TopTransactionResourceOwner,
1903
RESOURCE_RELEASE_BEFORE_LOCKS,
1906
/* Check we've released all buffer pins */
1907
AtEOXact_Buffers(true);
1909
/* Clean up the relation cache */
1910
AtEOXact_RelationCache(true);
1912
/* Clean up the snapshot manager */
1913
AtEarlyCommit_Snapshot();
1915
/* notify and flatfiles don't need a postprepare call */
1917
PostPrepare_PgStat();
1919
PostPrepare_Inval();
1923
AtEOXact_MultiXact();
1925
PostPrepare_Locks(xid);
1927
ResourceOwnerRelease(TopTransactionResourceOwner,
1928
RESOURCE_RELEASE_LOCKS,
1930
ResourceOwnerRelease(TopTransactionResourceOwner,
1931
RESOURCE_RELEASE_AFTER_LOCKS,
1934
/* Check we've released all catcache entries */
1935
AtEOXact_CatCache(true);
1937
/* PREPARE acts the same as COMMIT as far as GUC is concerned */
1938
AtEOXact_GUC(true, 1);
1941
AtEOXact_on_commit_actions(true);
1942
AtEOXact_Namespace(true);
1943
/* smgrcommit already done */
1945
AtEOXact_ComboCid();
1946
AtEOXact_HashTables(true);
1947
/* don't call AtEOXact_PgStat here */
1948
AtEOXact_Snapshot(true);
1950
CurrentResourceOwner = NULL;
1951
ResourceOwnerDelete(TopTransactionResourceOwner);
1952
s->curTransactionOwner = NULL;
1953
CurTransactionResourceOwner = NULL;
1954
TopTransactionResourceOwner = NULL;
1958
s->transactionId = InvalidTransactionId;
1959
s->subTransactionId = InvalidSubTransactionId;
1960
s->nestingLevel = 0;
1961
s->gucNestLevel = 0;
1962
s->childXids = NULL;
1964
s->maxChildXids = 0;
1967
* done with 1st phase commit processing, set current transaction state
1970
s->state = TRANS_DEFAULT;
1972
RESUME_INTERRUPTS();
1980
AbortTransaction(void)
1982
TransactionState s = CurrentTransactionState;
1983
TransactionId latestXid;
1985
/* Prevent cancel/die interrupt while cleaning up */
1988
/* Make sure we have a valid memory context and resource owner */
1990
AtAbort_ResourceOwner();
1993
* Release any LW locks we might be holding as quickly as possible.
1994
* (Regular locks, however, must be held till we finish aborting.)
1995
* Releasing LW locks is critical since we might try to grab them again
1996
* while cleaning up!
2000
/* Clean up buffer I/O and buffer context locks, too */
2005
* Also clean up any open wait for lock, since the lock manager will choke
2006
* if we try to wait for another lock before doing this.
2011
* check the current transaction state
2013
if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
2014
elog(WARNING, "AbortTransaction while in %s state",
2015
TransStateAsString(s->state));
2016
Assert(s->parent == NULL);
2019
* set the current transaction state information appropriately during the
2022
s->state = TRANS_ABORT;
2025
* Reset user ID which might have been changed transiently. We need this
2026
* to clean up in case control escaped out of a SECURITY DEFINER function
2027
* or other local change of CurrentUserId; therefore, the prior value
2028
* of SecurityDefinerContext also needs to be restored.
2030
* (Note: it is not necessary to restore session authorization or role
2031
* settings here because those can only be changed via GUC, and GUC will
2032
* take care of rolling them back if need be.)
2034
SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
2037
* do abort processing
2039
AfterTriggerEndXact(false);
2041
AtEOXact_LargeObject(false); /* 'false' means it's abort */
2043
AtEOXact_UpdateFlatFiles(false);
2046
* Advertise the fact that we aborted in pg_clog (assuming that we got as
2047
* far as assigning an XID to advertise).
2049
latestXid = RecordTransactionAbort(false);
2051
TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid);
2054
* Let others know about no transaction in progress by me. Note that this
2055
* must be done _before_ releasing locks we hold and _after_
2056
* RecordTransactionAbort.
2058
ProcArrayEndTransaction(MyProc, latestXid);
2061
* Post-abort cleanup. See notes in CommitTransaction() concerning
2065
CallXactCallbacks(XACT_EVENT_ABORT);
2067
ResourceOwnerRelease(TopTransactionResourceOwner,
2068
RESOURCE_RELEASE_BEFORE_LOCKS,
2070
AtEOXact_Buffers(false);
2071
AtEOXact_RelationCache(false);
2072
AtEOXact_Inval(false);
2073
smgrDoPendingDeletes(false);
2074
AtEOXact_MultiXact();
2075
ResourceOwnerRelease(TopTransactionResourceOwner,
2076
RESOURCE_RELEASE_LOCKS,
2078
ResourceOwnerRelease(TopTransactionResourceOwner,
2079
RESOURCE_RELEASE_AFTER_LOCKS,
2081
AtEOXact_CatCache(false);
2083
AtEOXact_GUC(false, 1);
2084
AtEOXact_SPI(false);
2086
AtEOXact_on_commit_actions(false);
2087
AtEOXact_Namespace(false);
2089
AtEOXact_ComboCid();
2090
AtEOXact_HashTables(false);
2091
AtEOXact_PgStat(false);
2092
AtEOXact_Snapshot(false);
2093
pgstat_report_xact_timestamp(0);
2096
* State remains TRANS_ABORT until CleanupTransaction().
2098
RESUME_INTERRUPTS();
2102
* CleanupTransaction
2105
CleanupTransaction(void)
2107
TransactionState s = CurrentTransactionState;
2110
* State should still be TRANS_ABORT from AbortTransaction().
2112
if (s->state != TRANS_ABORT)
2113
elog(FATAL, "CleanupTransaction: unexpected state %s",
2114
TransStateAsString(s->state));
2117
* do abort cleanup processing
2119
AtCleanup_Portals(); /* now safe to release portal memory */
2121
CurrentResourceOwner = NULL; /* and resource owner */
2122
if (TopTransactionResourceOwner)
2123
ResourceOwnerDelete(TopTransactionResourceOwner);
2124
s->curTransactionOwner = NULL;
2125
CurTransactionResourceOwner = NULL;
2126
TopTransactionResourceOwner = NULL;
2128
AtCleanup_Memory(); /* and transaction memory */
2130
s->transactionId = InvalidTransactionId;
2131
s->subTransactionId = InvalidSubTransactionId;
2132
s->nestingLevel = 0;
2133
s->gucNestLevel = 0;
2134
s->childXids = NULL;
2136
s->maxChildXids = 0;
2139
* done with abort processing, set current transaction state back to
2142
s->state = TRANS_DEFAULT;
2146
* StartTransactionCommand
2149
StartTransactionCommand(void)
2151
TransactionState s = CurrentTransactionState;
2153
switch (s->blockState)
2156
* if we aren't in a transaction block, we just do our usual start
2159
case TBLOCK_DEFAULT:
2161
s->blockState = TBLOCK_STARTED;
2165
* We are somewhere in a transaction block or subtransaction and
2166
* about to start a new command. For now we do nothing, but
2167
* someday we may do command-local resource initialization. (Note
2168
* that any needed CommandCounterIncrement was done by the
2169
* previous CommitTransactionCommand.)
2171
case TBLOCK_INPROGRESS:
2172
case TBLOCK_SUBINPROGRESS:
2176
* Here we are in a failed transaction block (one of the commands
2177
* caused an abort) so we do nothing but remain in the abort
2178
* state. Eventually we will get a ROLLBACK command which will
2179
* get us out of this state. (It is up to other code to ensure
2180
* that no commands other than ROLLBACK will be processed in these
2184
case TBLOCK_SUBABORT:
2187
/* These cases are invalid. */
2188
case TBLOCK_STARTED:
2190
case TBLOCK_SUBBEGIN:
2193
case TBLOCK_ABORT_END:
2194
case TBLOCK_SUBABORT_END:
2195
case TBLOCK_ABORT_PENDING:
2196
case TBLOCK_SUBABORT_PENDING:
2197
case TBLOCK_SUBRESTART:
2198
case TBLOCK_SUBABORT_RESTART:
2199
case TBLOCK_PREPARE:
2200
elog(ERROR, "StartTransactionCommand: unexpected state %s",
2201
BlockStateAsString(s->blockState));
2206
* We must switch to CurTransactionContext before returning. This is
2207
* already done if we called StartTransaction, otherwise not.
2209
Assert(CurTransactionContext != NULL);
2210
MemoryContextSwitchTo(CurTransactionContext);
2214
* CommitTransactionCommand
2217
CommitTransactionCommand(void)
2219
TransactionState s = CurrentTransactionState;
2221
switch (s->blockState)
2224
* This shouldn't happen, because it means the previous
2225
* StartTransactionCommand didn't set the STARTED state
2228
case TBLOCK_DEFAULT:
2229
elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2230
BlockStateAsString(s->blockState));
2234
* If we aren't in a transaction block, just do our usual
2235
* transaction commit, and return to the idle state.
2237
case TBLOCK_STARTED:
2238
CommitTransaction();
2239
s->blockState = TBLOCK_DEFAULT;
2243
* We are completing a "BEGIN TRANSACTION" command, so we change
2244
* to the "transaction block in progress" state and return. (We
2245
* assume the BEGIN did nothing to the database, so we need no
2246
* CommandCounterIncrement.)
2249
s->blockState = TBLOCK_INPROGRESS;
2253
* This is the case when we have finished executing a command
2254
* someplace within a transaction block. We increment the command
2255
* counter and return.
2257
case TBLOCK_INPROGRESS:
2258
case TBLOCK_SUBINPROGRESS:
2259
CommandCounterIncrement();
2263
* We are completing a "COMMIT" command. Do it and return to the
2267
CommitTransaction();
2268
s->blockState = TBLOCK_DEFAULT;
2272
* Here we are in the middle of a transaction block but one of the
2273
* commands caused an abort so we do nothing but remain in the
2274
* abort state. Eventually we will get a ROLLBACK comand.
2277
case TBLOCK_SUBABORT:
2281
* Here we were in an aborted transaction block and we just got
2282
* the ROLLBACK command from the user, so clean up the
2283
* already-aborted transaction and return to the idle state.
2285
case TBLOCK_ABORT_END:
2286
CleanupTransaction();
2287
s->blockState = TBLOCK_DEFAULT;
2291
* Here we were in a perfectly good transaction block but the user
2292
* told us to ROLLBACK anyway. We have to abort the transaction
2293
* and then clean up.
2295
case TBLOCK_ABORT_PENDING:
2297
CleanupTransaction();
2298
s->blockState = TBLOCK_DEFAULT;
2302
* We are completing a "PREPARE TRANSACTION" command. Do it and
2303
* return to the idle state.
2305
case TBLOCK_PREPARE:
2306
PrepareTransaction();
2307
s->blockState = TBLOCK_DEFAULT;
2311
* We were just issued a SAVEPOINT inside a transaction block.
2312
* Start a subtransaction. (DefineSavepoint already did
2313
* PushTransaction, so as to have someplace to put the SUBBEGIN
2316
case TBLOCK_SUBBEGIN:
2317
StartSubTransaction();
2318
s->blockState = TBLOCK_SUBINPROGRESS;
2322
* We were issued a COMMIT or RELEASE command, so we end the
2323
* current subtransaction and return to the parent transaction.
2324
* The parent might be ended too, so repeat till we are all the
2325
* way out or find an INPROGRESS transaction.
2330
CommitSubTransaction();
2331
s = CurrentTransactionState; /* changed by pop */
2332
} while (s->blockState == TBLOCK_SUBEND);
2333
/* If we had a COMMIT command, finish off the main xact too */
2334
if (s->blockState == TBLOCK_END)
2336
Assert(s->parent == NULL);
2337
CommitTransaction();
2338
s->blockState = TBLOCK_DEFAULT;
2340
else if (s->blockState == TBLOCK_PREPARE)
2342
Assert(s->parent == NULL);
2343
PrepareTransaction();
2344
s->blockState = TBLOCK_DEFAULT;
2348
Assert(s->blockState == TBLOCK_INPROGRESS ||
2349
s->blockState == TBLOCK_SUBINPROGRESS);
2354
* The current already-failed subtransaction is ending due to a
2355
* ROLLBACK or ROLLBACK TO command, so pop it and recursively
2356
* examine the parent (which could be in any of several states).
2358
case TBLOCK_SUBABORT_END:
2359
CleanupSubTransaction();
2360
CommitTransactionCommand();
2364
* As above, but it's not dead yet, so abort first.
2366
case TBLOCK_SUBABORT_PENDING:
2367
AbortSubTransaction();
2368
CleanupSubTransaction();
2369
CommitTransactionCommand();
2373
* The current subtransaction is the target of a ROLLBACK TO
2374
* command. Abort and pop it, then start a new subtransaction
2375
* with the same name.
2377
case TBLOCK_SUBRESTART:
2382
/* save name and keep Cleanup from freeing it */
2385
savepointLevel = s->savepointLevel;
2387
AbortSubTransaction();
2388
CleanupSubTransaction();
2390
DefineSavepoint(NULL);
2391
s = CurrentTransactionState; /* changed by push */
2393
s->savepointLevel = savepointLevel;
2395
/* This is the same as TBLOCK_SUBBEGIN case */
2396
AssertState(s->blockState == TBLOCK_SUBBEGIN);
2397
StartSubTransaction();
2398
s->blockState = TBLOCK_SUBINPROGRESS;
2403
* Same as above, but the subtransaction had already failed, so we
2404
* don't need AbortSubTransaction.
2406
case TBLOCK_SUBABORT_RESTART:
2411
/* save name and keep Cleanup from freeing it */
2414
savepointLevel = s->savepointLevel;
2416
CleanupSubTransaction();
2418
DefineSavepoint(NULL);
2419
s = CurrentTransactionState; /* changed by push */
2421
s->savepointLevel = savepointLevel;
2423
/* This is the same as TBLOCK_SUBBEGIN case */
2424
AssertState(s->blockState == TBLOCK_SUBBEGIN);
2425
StartSubTransaction();
2426
s->blockState = TBLOCK_SUBINPROGRESS;
2433
* AbortCurrentTransaction
2436
AbortCurrentTransaction(void)
2438
TransactionState s = CurrentTransactionState;
2440
switch (s->blockState)
2442
case TBLOCK_DEFAULT:
2443
if (s->state == TRANS_DEFAULT)
2445
/* we are idle, so nothing to do */
2450
* We can get here after an error during transaction start
2451
* (state will be TRANS_START). Need to clean up the
2452
* incompletely started transaction. First, adjust the
2453
* low-level state to suppress warning message from
2456
if (s->state == TRANS_START)
2457
s->state = TRANS_INPROGRESS;
2459
CleanupTransaction();
2464
* if we aren't in a transaction block, we just do the basic abort
2465
* & cleanup transaction.
2467
case TBLOCK_STARTED:
2469
CleanupTransaction();
2470
s->blockState = TBLOCK_DEFAULT;
2474
* If we are in TBLOCK_BEGIN it means something screwed up right
2475
* after reading "BEGIN TRANSACTION". We assume that the user
2476
* will interpret the error as meaning the BEGIN failed to get him
2477
* into a transaction block, so we should abort and return to idle
2482
CleanupTransaction();
2483
s->blockState = TBLOCK_DEFAULT;
2487
* We are somewhere in a transaction block and we've gotten a
2488
* failure, so we abort the transaction and set up the persistent
2489
* ABORT state. We will stay in ABORT until we get a ROLLBACK.
2491
case TBLOCK_INPROGRESS:
2493
s->blockState = TBLOCK_ABORT;
2494
/* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2498
* Here, we failed while trying to COMMIT. Clean up the
2499
* transaction and return to idle state (we do not want to stay in
2504
CleanupTransaction();
2505
s->blockState = TBLOCK_DEFAULT;
2509
* Here, we are already in an aborted transaction state and are
2510
* waiting for a ROLLBACK, but for some reason we failed again! So
2511
* we just remain in the abort state.
2514
case TBLOCK_SUBABORT:
2518
* We are in a failed transaction and we got the ROLLBACK command.
2519
* We have already aborted, we just need to cleanup and go to idle
2522
case TBLOCK_ABORT_END:
2523
CleanupTransaction();
2524
s->blockState = TBLOCK_DEFAULT;
2528
* We are in a live transaction and we got a ROLLBACK command.
2529
* Abort, cleanup, go to idle state.
2531
case TBLOCK_ABORT_PENDING:
2533
CleanupTransaction();
2534
s->blockState = TBLOCK_DEFAULT;
2538
* Here, we failed while trying to PREPARE. Clean up the
2539
* transaction and return to idle state (we do not want to stay in
2542
case TBLOCK_PREPARE:
2544
CleanupTransaction();
2545
s->blockState = TBLOCK_DEFAULT;
2549
* We got an error inside a subtransaction. Abort just the
2550
* subtransaction, and go to the persistent SUBABORT state until
2553
case TBLOCK_SUBINPROGRESS:
2554
AbortSubTransaction();
2555
s->blockState = TBLOCK_SUBABORT;
2559
* If we failed while trying to create a subtransaction, clean up
2560
* the broken subtransaction and abort the parent. The same
2561
* applies if we get a failure while ending a subtransaction.
2563
case TBLOCK_SUBBEGIN:
2565
case TBLOCK_SUBABORT_PENDING:
2566
case TBLOCK_SUBRESTART:
2567
AbortSubTransaction();
2568
CleanupSubTransaction();
2569
AbortCurrentTransaction();
2573
* Same as above, except the Abort() was already done.
2575
case TBLOCK_SUBABORT_END:
2576
case TBLOCK_SUBABORT_RESTART:
2577
CleanupSubTransaction();
2578
AbortCurrentTransaction();
2584
* PreventTransactionChain
2586
* This routine is to be called by statements that must not run inside
2587
* a transaction block, typically because they have non-rollback-able
2588
* side effects or do internal commits.
2590
* If we have already started a transaction block, issue an error; also issue
2591
* an error if we appear to be running inside a user-defined function (which
2592
* could issue more commands and possibly cause a failure after the statement
2593
* completes). Subtransactions are verboten too.
2595
* isTopLevel: passed down from ProcessUtility to determine whether we are
2596
* inside a function or multi-query querystring. (We will always fail if
2597
* this is false, but it's convenient to centralize the check here instead of
2598
* making callers do it.)
2599
* stmtType: statement type name, for error messages.
2602
PreventTransactionChain(bool isTopLevel, const char *stmtType)
2605
* xact block already started?
2607
if (IsTransactionBlock())
2609
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2610
/* translator: %s represents an SQL statement name */
2611
errmsg("%s cannot run inside a transaction block",
2617
if (IsSubTransaction())
2619
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2620
/* translator: %s represents an SQL statement name */
2621
errmsg("%s cannot run inside a subtransaction",
2625
* inside a function call?
2629
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2630
/* translator: %s represents an SQL statement name */
2631
errmsg("%s cannot be executed from a function or multi-command string",
2634
/* If we got past IsTransactionBlock test, should be in default state */
2635
if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2636
CurrentTransactionState->blockState != TBLOCK_STARTED)
2637
elog(FATAL, "cannot prevent transaction chain");
2642
* RequireTransactionChain
2644
* This routine is to be called by statements that must run inside
2645
* a transaction block, because they have no effects that persist past
2646
* transaction end (and so calling them outside a transaction block
2647
* is presumably an error). DECLARE CURSOR is an example.
2649
* If we appear to be running inside a user-defined function, we do not
2650
* issue an error, since the function could issue more commands that make
2651
* use of the current statement's results. Likewise subtransactions.
2652
* Thus this is an inverse for PreventTransactionChain.
2654
* isTopLevel: passed down from ProcessUtility to determine whether we are
2655
* inside a function.
2656
* stmtType: statement type name, for error messages.
2659
RequireTransactionChain(bool isTopLevel, const char *stmtType)
2662
* xact block already started?
2664
if (IsTransactionBlock())
2670
if (IsSubTransaction())
2674
* inside a function call?
2680
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2681
/* translator: %s represents an SQL statement name */
2682
errmsg("%s can only be used in transaction blocks",
2687
* IsInTransactionChain
2689
* This routine is for statements that need to behave differently inside
2690
* a transaction block than when running as single commands. ANALYZE is
2691
* currently the only example.
2693
* isTopLevel: passed down from ProcessUtility to determine whether we are
2694
* inside a function.
2697
IsInTransactionChain(bool isTopLevel)
2700
* Return true on same conditions that would make PreventTransactionChain
2703
if (IsTransactionBlock())
2706
if (IsSubTransaction())
2712
if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2713
CurrentTransactionState->blockState != TBLOCK_STARTED)
2721
* Register or deregister callback functions for start- and end-of-xact
2724
* These functions are intended for use by dynamically loaded modules.
2725
* For built-in modules we generally just hardwire the appropriate calls
2726
* (mainly because it's easier to control the order that way, where needed).
2728
* At transaction end, the callback occurs post-commit or post-abort, so the
2729
* callback functions can only do noncritical cleanup.
2732
RegisterXactCallback(XactCallback callback, void *arg)
2734
XactCallbackItem *item;
2736
item = (XactCallbackItem *)
2737
MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2738
item->callback = callback;
2740
item->next = Xact_callbacks;
2741
Xact_callbacks = item;
2745
UnregisterXactCallback(XactCallback callback, void *arg)
2747
XactCallbackItem *item;
2748
XactCallbackItem *prev;
2751
for (item = Xact_callbacks; item; prev = item, item = item->next)
2753
if (item->callback == callback && item->arg == arg)
2756
prev->next = item->next;
2758
Xact_callbacks = item->next;
2766
CallXactCallbacks(XactEvent event)
2768
XactCallbackItem *item;
2770
for (item = Xact_callbacks; item; item = item->next)
2771
(*item->callback) (event, item->arg);
2776
* Register or deregister callback functions for start- and end-of-subxact
2779
* Pretty much same as above, but for subtransaction events.
2781
* At subtransaction end, the callback occurs post-subcommit or post-subabort,
2782
* so the callback functions can only do noncritical cleanup. At
2783
* subtransaction start, the callback is called when the subtransaction has
2784
* finished initializing.
2787
RegisterSubXactCallback(SubXactCallback callback, void *arg)
2789
SubXactCallbackItem *item;
2791
item = (SubXactCallbackItem *)
2792
MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2793
item->callback = callback;
2795
item->next = SubXact_callbacks;
2796
SubXact_callbacks = item;
2800
UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2802
SubXactCallbackItem *item;
2803
SubXactCallbackItem *prev;
2806
for (item = SubXact_callbacks; item; prev = item, item = item->next)
2808
if (item->callback == callback && item->arg == arg)
2811
prev->next = item->next;
2813
SubXact_callbacks = item->next;
2821
CallSubXactCallbacks(SubXactEvent event,
2822
SubTransactionId mySubid,
2823
SubTransactionId parentSubid)
2825
SubXactCallbackItem *item;
2827
for (item = SubXact_callbacks; item; item = item->next)
2828
(*item->callback) (event, mySubid, parentSubid, item->arg);
2832
/* ----------------------------------------------------------------
2833
* transaction block support
2834
* ----------------------------------------------------------------
2838
* BeginTransactionBlock
2839
* This executes a BEGIN command.
2842
BeginTransactionBlock(void)
2844
TransactionState s = CurrentTransactionState;
2846
switch (s->blockState)
2849
* We are not inside a transaction block, so allow one to begin.
2851
case TBLOCK_STARTED:
2852
s->blockState = TBLOCK_BEGIN;
2856
* Already a transaction block in progress.
2858
case TBLOCK_INPROGRESS:
2859
case TBLOCK_SUBINPROGRESS:
2861
case TBLOCK_SUBABORT:
2863
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2864
errmsg("there is already a transaction in progress")));
2867
/* These cases are invalid. */
2868
case TBLOCK_DEFAULT:
2870
case TBLOCK_SUBBEGIN:
2873
case TBLOCK_ABORT_END:
2874
case TBLOCK_SUBABORT_END:
2875
case TBLOCK_ABORT_PENDING:
2876
case TBLOCK_SUBABORT_PENDING:
2877
case TBLOCK_SUBRESTART:
2878
case TBLOCK_SUBABORT_RESTART:
2879
case TBLOCK_PREPARE:
2880
elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2881
BlockStateAsString(s->blockState));
2887
* PrepareTransactionBlock
2888
* This executes a PREPARE command.
2890
* Since PREPARE may actually do a ROLLBACK, the result indicates what
2891
* happened: TRUE for PREPARE, FALSE for ROLLBACK.
2893
* Note that we don't actually do anything here except change blockState.
2894
* The real work will be done in the upcoming PrepareTransaction().
2895
* We do it this way because it's not convenient to change memory context,
2896
* resource owner, etc while executing inside a Portal.
2899
PrepareTransactionBlock(char *gid)
2904
/* Set up to commit the current transaction */
2905
result = EndTransactionBlock();
2907
/* If successful, change outer tblock state to PREPARE */
2910
s = CurrentTransactionState;
2912
while (s->parent != NULL)
2915
if (s->blockState == TBLOCK_END)
2917
/* Save GID where PrepareTransaction can find it again */
2918
prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2920
s->blockState = TBLOCK_PREPARE;
2925
* ignore case where we are not in a transaction;
2926
* EndTransactionBlock already issued a warning.
2928
Assert(s->blockState == TBLOCK_STARTED);
2929
/* Don't send back a PREPARE result tag... */
2938
* EndTransactionBlock
2939
* This executes a COMMIT command.
2941
* Since COMMIT may actually do a ROLLBACK, the result indicates what
2942
* happened: TRUE for COMMIT, FALSE for ROLLBACK.
2944
* Note that we don't actually do anything here except change blockState.
2945
* The real work will be done in the upcoming CommitTransactionCommand().
2946
* We do it this way because it's not convenient to change memory context,
2947
* resource owner, etc while executing inside a Portal.
2950
EndTransactionBlock(void)
2952
TransactionState s = CurrentTransactionState;
2953
bool result = false;
2955
switch (s->blockState)
2958
* We are in a transaction block, so tell CommitTransactionCommand
2961
case TBLOCK_INPROGRESS:
2962
s->blockState = TBLOCK_END;
2967
* We are in a failed transaction block. Tell
2968
* CommitTransactionCommand it's time to exit the block.
2971
s->blockState = TBLOCK_ABORT_END;
2975
* We are in a live subtransaction block. Set up to subcommit all
2976
* open subtransactions and then commit the main transaction.
2978
case TBLOCK_SUBINPROGRESS:
2979
while (s->parent != NULL)
2981
if (s->blockState == TBLOCK_SUBINPROGRESS)
2982
s->blockState = TBLOCK_SUBEND;
2984
elog(FATAL, "EndTransactionBlock: unexpected state %s",
2985
BlockStateAsString(s->blockState));
2988
if (s->blockState == TBLOCK_INPROGRESS)
2989
s->blockState = TBLOCK_END;
2991
elog(FATAL, "EndTransactionBlock: unexpected state %s",
2992
BlockStateAsString(s->blockState));
2997
* Here we are inside an aborted subtransaction. Treat the COMMIT
2998
* as ROLLBACK: set up to abort everything and exit the main
3001
case TBLOCK_SUBABORT:
3002
while (s->parent != NULL)
3004
if (s->blockState == TBLOCK_SUBINPROGRESS)
3005
s->blockState = TBLOCK_SUBABORT_PENDING;
3006
else if (s->blockState == TBLOCK_SUBABORT)
3007
s->blockState = TBLOCK_SUBABORT_END;
3009
elog(FATAL, "EndTransactionBlock: unexpected state %s",
3010
BlockStateAsString(s->blockState));
3013
if (s->blockState == TBLOCK_INPROGRESS)
3014
s->blockState = TBLOCK_ABORT_PENDING;
3015
else if (s->blockState == TBLOCK_ABORT)
3016
s->blockState = TBLOCK_ABORT_END;
3018
elog(FATAL, "EndTransactionBlock: unexpected state %s",
3019
BlockStateAsString(s->blockState));
3023
* The user issued COMMIT when not inside a transaction. Issue a
3024
* WARNING, staying in TBLOCK_STARTED state. The upcoming call to
3025
* CommitTransactionCommand() will then close the transaction and
3026
* put us back into the default state.
3028
case TBLOCK_STARTED:
3030
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3031
errmsg("there is no transaction in progress")));
3035
/* These cases are invalid. */
3036
case TBLOCK_DEFAULT:
3038
case TBLOCK_SUBBEGIN:
3041
case TBLOCK_ABORT_END:
3042
case TBLOCK_SUBABORT_END:
3043
case TBLOCK_ABORT_PENDING:
3044
case TBLOCK_SUBABORT_PENDING:
3045
case TBLOCK_SUBRESTART:
3046
case TBLOCK_SUBABORT_RESTART:
3047
case TBLOCK_PREPARE:
3048
elog(FATAL, "EndTransactionBlock: unexpected state %s",
3049
BlockStateAsString(s->blockState));
3057
* UserAbortTransactionBlock
3058
* This executes a ROLLBACK command.
3060
* As above, we don't actually do anything here except change blockState.
3063
UserAbortTransactionBlock(void)
3065
TransactionState s = CurrentTransactionState;
3067
switch (s->blockState)
3070
* We are inside a transaction block and we got a ROLLBACK command
3071
* from the user, so tell CommitTransactionCommand to abort and
3072
* exit the transaction block.
3074
case TBLOCK_INPROGRESS:
3075
s->blockState = TBLOCK_ABORT_PENDING;
3079
* We are inside a failed transaction block and we got a ROLLBACK
3080
* command from the user. Abort processing is already done, so
3081
* CommitTransactionCommand just has to cleanup and go back to
3085
s->blockState = TBLOCK_ABORT_END;
3089
* We are inside a subtransaction. Mark everything up to top
3090
* level as exitable.
3092
case TBLOCK_SUBINPROGRESS:
3093
case TBLOCK_SUBABORT:
3094
while (s->parent != NULL)
3096
if (s->blockState == TBLOCK_SUBINPROGRESS)
3097
s->blockState = TBLOCK_SUBABORT_PENDING;
3098
else if (s->blockState == TBLOCK_SUBABORT)
3099
s->blockState = TBLOCK_SUBABORT_END;
3101
elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3102
BlockStateAsString(s->blockState));
3105
if (s->blockState == TBLOCK_INPROGRESS)
3106
s->blockState = TBLOCK_ABORT_PENDING;
3107
else if (s->blockState == TBLOCK_ABORT)
3108
s->blockState = TBLOCK_ABORT_END;
3110
elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3111
BlockStateAsString(s->blockState));
3115
* The user issued ABORT when not inside a transaction. Issue a
3116
* WARNING and go to abort state. The upcoming call to
3117
* CommitTransactionCommand() will then put us back into the
3120
case TBLOCK_STARTED:
3122
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3123
errmsg("there is no transaction in progress")));
3124
s->blockState = TBLOCK_ABORT_PENDING;
3127
/* These cases are invalid. */
3128
case TBLOCK_DEFAULT:
3130
case TBLOCK_SUBBEGIN:
3133
case TBLOCK_ABORT_END:
3134
case TBLOCK_SUBABORT_END:
3135
case TBLOCK_ABORT_PENDING:
3136
case TBLOCK_SUBABORT_PENDING:
3137
case TBLOCK_SUBRESTART:
3138
case TBLOCK_SUBABORT_RESTART:
3139
case TBLOCK_PREPARE:
3140
elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3141
BlockStateAsString(s->blockState));
3148
* This executes a SAVEPOINT command.
3151
DefineSavepoint(char *name)
3153
TransactionState s = CurrentTransactionState;
3155
switch (s->blockState)
3157
case TBLOCK_INPROGRESS:
3158
case TBLOCK_SUBINPROGRESS:
3159
/* Normal subtransaction start */
3161
s = CurrentTransactionState; /* changed by push */
3164
* Savepoint names, like the TransactionState block itself, live
3165
* in TopTransactionContext.
3168
s->name = MemoryContextStrdup(TopTransactionContext, name);
3171
/* These cases are invalid. */
3172
case TBLOCK_DEFAULT:
3173
case TBLOCK_STARTED:
3175
case TBLOCK_SUBBEGIN:
3179
case TBLOCK_SUBABORT:
3180
case TBLOCK_ABORT_END:
3181
case TBLOCK_SUBABORT_END:
3182
case TBLOCK_ABORT_PENDING:
3183
case TBLOCK_SUBABORT_PENDING:
3184
case TBLOCK_SUBRESTART:
3185
case TBLOCK_SUBABORT_RESTART:
3186
case TBLOCK_PREPARE:
3187
elog(FATAL, "DefineSavepoint: unexpected state %s",
3188
BlockStateAsString(s->blockState));
3195
* This executes a RELEASE command.
3197
* As above, we don't actually do anything here except change blockState.
3200
ReleaseSavepoint(List *options)
3202
TransactionState s = CurrentTransactionState;
3203
TransactionState target,
3208
switch (s->blockState)
3211
* We can't rollback to a savepoint if there is no savepoint
3214
case TBLOCK_INPROGRESS:
3216
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3217
errmsg("no such savepoint")));
3221
* We are in a non-aborted subtransaction. This is the only valid
3224
case TBLOCK_SUBINPROGRESS:
3227
/* These cases are invalid. */
3228
case TBLOCK_DEFAULT:
3229
case TBLOCK_STARTED:
3231
case TBLOCK_SUBBEGIN:
3235
case TBLOCK_SUBABORT:
3236
case TBLOCK_ABORT_END:
3237
case TBLOCK_SUBABORT_END:
3238
case TBLOCK_ABORT_PENDING:
3239
case TBLOCK_SUBABORT_PENDING:
3240
case TBLOCK_SUBRESTART:
3241
case TBLOCK_SUBABORT_RESTART:
3242
case TBLOCK_PREPARE:
3243
elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3244
BlockStateAsString(s->blockState));
3248
foreach(cell, options)
3250
DefElem *elem = lfirst(cell);
3252
if (strcmp(elem->defname, "savepoint_name") == 0)
3253
name = strVal(elem->arg);
3256
Assert(PointerIsValid(name));
3258
for (target = s; PointerIsValid(target); target = target->parent)
3260
if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3264
if (!PointerIsValid(target))
3266
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3267
errmsg("no such savepoint")));
3269
/* disallow crossing savepoint level boundaries */
3270
if (target->savepointLevel != s->savepointLevel)
3272
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3273
errmsg("no such savepoint")));
3276
* Mark "commit pending" all subtransactions up to the target
3277
* subtransaction. The actual commits will happen when control gets to
3278
* CommitTransactionCommand.
3280
xact = CurrentTransactionState;
3283
Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3284
xact->blockState = TBLOCK_SUBEND;
3287
xact = xact->parent;
3288
Assert(PointerIsValid(xact));
3293
* RollbackToSavepoint
3294
* This executes a ROLLBACK TO <savepoint> command.
3296
* As above, we don't actually do anything here except change blockState.
3299
RollbackToSavepoint(List *options)
3301
TransactionState s = CurrentTransactionState;
3302
TransactionState target,
3307
switch (s->blockState)
3310
* We can't rollback to a savepoint if there is no savepoint
3313
case TBLOCK_INPROGRESS:
3316
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3317
errmsg("no such savepoint")));
3321
* There is at least one savepoint, so proceed.
3323
case TBLOCK_SUBINPROGRESS:
3324
case TBLOCK_SUBABORT:
3327
/* These cases are invalid. */
3328
case TBLOCK_DEFAULT:
3329
case TBLOCK_STARTED:
3331
case TBLOCK_SUBBEGIN:
3334
case TBLOCK_ABORT_END:
3335
case TBLOCK_SUBABORT_END:
3336
case TBLOCK_ABORT_PENDING:
3337
case TBLOCK_SUBABORT_PENDING:
3338
case TBLOCK_SUBRESTART:
3339
case TBLOCK_SUBABORT_RESTART:
3340
case TBLOCK_PREPARE:
3341
elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3342
BlockStateAsString(s->blockState));
3346
foreach(cell, options)
3348
DefElem *elem = lfirst(cell);
3350
if (strcmp(elem->defname, "savepoint_name") == 0)
3351
name = strVal(elem->arg);
3354
Assert(PointerIsValid(name));
3356
for (target = s; PointerIsValid(target); target = target->parent)
3358
if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3362
if (!PointerIsValid(target))
3364
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3365
errmsg("no such savepoint")));
3367
/* disallow crossing savepoint level boundaries */
3368
if (target->savepointLevel != s->savepointLevel)
3370
(errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3371
errmsg("no such savepoint")));
3374
* Mark "abort pending" all subtransactions up to the target
3375
* subtransaction. The actual aborts will happen when control gets to
3376
* CommitTransactionCommand.
3378
xact = CurrentTransactionState;
3383
if (xact->blockState == TBLOCK_SUBINPROGRESS)
3384
xact->blockState = TBLOCK_SUBABORT_PENDING;
3385
else if (xact->blockState == TBLOCK_SUBABORT)
3386
xact->blockState = TBLOCK_SUBABORT_END;
3388
elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3389
BlockStateAsString(xact->blockState));
3390
xact = xact->parent;
3391
Assert(PointerIsValid(xact));
3394
/* And mark the target as "restart pending" */
3395
if (xact->blockState == TBLOCK_SUBINPROGRESS)
3396
xact->blockState = TBLOCK_SUBRESTART;
3397
else if (xact->blockState == TBLOCK_SUBABORT)
3398
xact->blockState = TBLOCK_SUBABORT_RESTART;
3400
elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3401
BlockStateAsString(xact->blockState));
3405
* BeginInternalSubTransaction
3406
* This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3407
* TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3408
* used in functions that might be called when not inside a BEGIN block
3409
* or when running deferred triggers at COMMIT/PREPARE time. Also, it
3410
* automatically does CommitTransactionCommand/StartTransactionCommand
3411
* instead of expecting the caller to do it.
3414
BeginInternalSubTransaction(char *name)
3416
TransactionState s = CurrentTransactionState;
3418
switch (s->blockState)
3420
case TBLOCK_STARTED:
3421
case TBLOCK_INPROGRESS:
3423
case TBLOCK_PREPARE:
3424
case TBLOCK_SUBINPROGRESS:
3425
/* Normal subtransaction start */
3427
s = CurrentTransactionState; /* changed by push */
3430
* Savepoint names, like the TransactionState block itself, live
3431
* in TopTransactionContext.
3434
s->name = MemoryContextStrdup(TopTransactionContext, name);
3437
/* These cases are invalid. */
3438
case TBLOCK_DEFAULT:
3440
case TBLOCK_SUBBEGIN:
3443
case TBLOCK_SUBABORT:
3444
case TBLOCK_ABORT_END:
3445
case TBLOCK_SUBABORT_END:
3446
case TBLOCK_ABORT_PENDING:
3447
case TBLOCK_SUBABORT_PENDING:
3448
case TBLOCK_SUBRESTART:
3449
case TBLOCK_SUBABORT_RESTART:
3450
elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3451
BlockStateAsString(s->blockState));
3455
CommitTransactionCommand();
3456
StartTransactionCommand();
3460
* ReleaseCurrentSubTransaction
3462
* RELEASE (ie, commit) the innermost subtransaction, regardless of its
3463
* savepoint name (if any).
3464
* NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3467
ReleaseCurrentSubTransaction(void)
3469
TransactionState s = CurrentTransactionState;
3471
if (s->blockState != TBLOCK_SUBINPROGRESS)
3472
elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3473
BlockStateAsString(s->blockState));
3474
Assert(s->state == TRANS_INPROGRESS);
3475
MemoryContextSwitchTo(CurTransactionContext);
3476
CommitSubTransaction();
3477
s = CurrentTransactionState; /* changed by pop */
3478
Assert(s->state == TRANS_INPROGRESS);
3482
* RollbackAndReleaseCurrentSubTransaction
3484
* ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3485
* of its savepoint name (if any).
3486
* NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3489
RollbackAndReleaseCurrentSubTransaction(void)
3491
TransactionState s = CurrentTransactionState;
3493
switch (s->blockState)
3495
/* Must be in a subtransaction */
3496
case TBLOCK_SUBINPROGRESS:
3497
case TBLOCK_SUBABORT:
3500
/* These cases are invalid. */
3501
case TBLOCK_DEFAULT:
3502
case TBLOCK_STARTED:
3504
case TBLOCK_SUBBEGIN:
3505
case TBLOCK_INPROGRESS:
3509
case TBLOCK_ABORT_END:
3510
case TBLOCK_SUBABORT_END:
3511
case TBLOCK_ABORT_PENDING:
3512
case TBLOCK_SUBABORT_PENDING:
3513
case TBLOCK_SUBRESTART:
3514
case TBLOCK_SUBABORT_RESTART:
3515
case TBLOCK_PREPARE:
3516
elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3517
BlockStateAsString(s->blockState));
3522
* Abort the current subtransaction, if needed.
3524
if (s->blockState == TBLOCK_SUBINPROGRESS)
3525
AbortSubTransaction();
3527
/* And clean it up, too */
3528
CleanupSubTransaction();
3530
s = CurrentTransactionState; /* changed by pop */
3531
AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3532
s->blockState == TBLOCK_INPROGRESS ||
3533
s->blockState == TBLOCK_STARTED);
3537
* AbortOutOfAnyTransaction
3539
* This routine is provided for error recovery purposes. It aborts any
3540
* active transaction or transaction block, leaving the system in a known
3544
AbortOutOfAnyTransaction(void)
3546
TransactionState s = CurrentTransactionState;
3549
* Get out of any transaction or nested transaction
3553
switch (s->blockState)
3555
case TBLOCK_DEFAULT:
3556
/* Not in a transaction, do nothing */
3558
case TBLOCK_STARTED:
3560
case TBLOCK_INPROGRESS:
3562
case TBLOCK_ABORT_PENDING:
3563
case TBLOCK_PREPARE:
3564
/* In a transaction, so clean up */
3566
CleanupTransaction();
3567
s->blockState = TBLOCK_DEFAULT;
3570
case TBLOCK_ABORT_END:
3571
/* AbortTransaction already done, still need Cleanup */
3572
CleanupTransaction();
3573
s->blockState = TBLOCK_DEFAULT;
3577
* In a subtransaction, so clean it up and abort parent too
3579
case TBLOCK_SUBBEGIN:
3580
case TBLOCK_SUBINPROGRESS:
3582
case TBLOCK_SUBABORT_PENDING:
3583
case TBLOCK_SUBRESTART:
3584
AbortSubTransaction();
3585
CleanupSubTransaction();
3586
s = CurrentTransactionState; /* changed by pop */
3589
case TBLOCK_SUBABORT:
3590
case TBLOCK_SUBABORT_END:
3591
case TBLOCK_SUBABORT_RESTART:
3592
/* As above, but AbortSubTransaction already done */
3593
CleanupSubTransaction();
3594
s = CurrentTransactionState; /* changed by pop */
3597
} while (s->blockState != TBLOCK_DEFAULT);
3599
/* Should be out of all subxacts now */
3600
Assert(s->parent == NULL);
3604
* IsTransactionBlock --- are we within a transaction block?
3607
IsTransactionBlock(void)
3609
TransactionState s = CurrentTransactionState;
3611
if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3618
* IsTransactionOrTransactionBlock --- are we within either a transaction
3619
* or a transaction block? (The backend is only really "idle" when this
3622
* This should match up with IsTransactionBlock and IsTransactionState.
3625
IsTransactionOrTransactionBlock(void)
3627
TransactionState s = CurrentTransactionState;
3629
if (s->blockState == TBLOCK_DEFAULT)
3636
* TransactionBlockStatusCode - return status code to send in ReadyForQuery
3639
TransactionBlockStatusCode(void)
3641
TransactionState s = CurrentTransactionState;
3643
switch (s->blockState)
3645
case TBLOCK_DEFAULT:
3646
case TBLOCK_STARTED:
3647
return 'I'; /* idle --- not in transaction */
3649
case TBLOCK_SUBBEGIN:
3650
case TBLOCK_INPROGRESS:
3651
case TBLOCK_SUBINPROGRESS:
3654
case TBLOCK_PREPARE:
3655
return 'T'; /* in transaction */
3657
case TBLOCK_SUBABORT:
3658
case TBLOCK_ABORT_END:
3659
case TBLOCK_SUBABORT_END:
3660
case TBLOCK_ABORT_PENDING:
3661
case TBLOCK_SUBABORT_PENDING:
3662
case TBLOCK_SUBRESTART:
3663
case TBLOCK_SUBABORT_RESTART:
3664
return 'E'; /* in failed transaction */
3667
/* should never get here */
3668
elog(FATAL, "invalid transaction block state: %s",
3669
BlockStateAsString(s->blockState));
3670
return 0; /* keep compiler quiet */
3677
IsSubTransaction(void)
3679
TransactionState s = CurrentTransactionState;
3681
if (s->nestingLevel >= 2)
3688
* StartSubTransaction
3690
* If you're wondering why this is separate from PushTransaction: it's because
3691
* we can't conveniently do this stuff right inside DefineSavepoint. The
3692
* SAVEPOINT utility command will be executed inside a Portal, and if we
3693
* muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3694
* the Portal will undo those settings. So we make DefineSavepoint just
3695
* push a dummy transaction block, and when control returns to the main
3696
* idle loop, CommitTransactionCommand will be called, and we'll come here
3697
* to finish starting the subtransaction.
3700
StartSubTransaction(void)
3702
TransactionState s = CurrentTransactionState;
3704
if (s->state != TRANS_DEFAULT)
3705
elog(WARNING, "StartSubTransaction while in %s state",
3706
TransStateAsString(s->state));
3708
s->state = TRANS_START;
3711
* Initialize subsystems for new subtransaction
3713
* must initialize resource-management stuff first
3715
AtSubStart_Memory();
3716
AtSubStart_ResourceOwner();
3718
AtSubStart_Notify();
3719
AfterTriggerBeginSubXact();
3721
s->state = TRANS_INPROGRESS;
3724
* Call start-of-subxact callbacks
3726
CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3727
s->parent->subTransactionId);
3729
ShowTransactionState("StartSubTransaction");
3733
* CommitSubTransaction
3735
* The caller has to make sure to always reassign CurrentTransactionState
3736
* if it has a local pointer to it after calling this function.
3739
CommitSubTransaction(void)
3741
TransactionState s = CurrentTransactionState;
3743
ShowTransactionState("CommitSubTransaction");
3745
if (s->state != TRANS_INPROGRESS)
3746
elog(WARNING, "CommitSubTransaction while in %s state",
3747
TransStateAsString(s->state));
3749
/* Pre-commit processing goes here -- nothing to do at the moment */
3751
s->state = TRANS_COMMIT;
3753
/* Must CCI to ensure commands of subtransaction are seen as done */
3754
CommandCounterIncrement();
3757
* Prior to 8.4 we marked subcommit in clog at this point. We now only
3758
* perform that step, if required, as part of the atomic update of the
3759
* whole transaction tree at top level commit or abort.
3762
/* Post-commit cleanup */
3763
if (TransactionIdIsValid(s->transactionId))
3764
AtSubCommit_childXids();
3765
AfterTriggerEndSubXact(true);
3766
AtSubCommit_Portals(s->subTransactionId,
3767
s->parent->subTransactionId,
3768
s->parent->curTransactionOwner);
3769
AtEOSubXact_LargeObject(true, s->subTransactionId,
3770
s->parent->subTransactionId);
3771
AtSubCommit_Notify();
3772
AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3773
s->parent->subTransactionId);
3775
CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3776
s->parent->subTransactionId);
3778
ResourceOwnerRelease(s->curTransactionOwner,
3779
RESOURCE_RELEASE_BEFORE_LOCKS,
3781
AtEOSubXact_RelationCache(true, s->subTransactionId,
3782
s->parent->subTransactionId);
3783
AtEOSubXact_Inval(true);
3787
* The only lock we actually release here is the subtransaction XID lock.
3788
* The rest just get transferred to the parent resource owner.
3790
CurrentResourceOwner = s->curTransactionOwner;
3791
if (TransactionIdIsValid(s->transactionId))
3792
XactLockTableDelete(s->transactionId);
3794
ResourceOwnerRelease(s->curTransactionOwner,
3795
RESOURCE_RELEASE_LOCKS,
3797
ResourceOwnerRelease(s->curTransactionOwner,
3798
RESOURCE_RELEASE_AFTER_LOCKS,
3801
AtEOXact_GUC(true, s->gucNestLevel);
3802
AtEOSubXact_SPI(true, s->subTransactionId);
3803
AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3804
s->parent->subTransactionId);
3805
AtEOSubXact_Namespace(true, s->subTransactionId,
3806
s->parent->subTransactionId);
3807
AtEOSubXact_Files(true, s->subTransactionId,
3808
s->parent->subTransactionId);
3809
AtEOSubXact_HashTables(true, s->nestingLevel);
3810
AtEOSubXact_PgStat(true, s->nestingLevel);
3811
AtSubCommit_Snapshot(s->nestingLevel);
3814
* We need to restore the upper transaction's read-only state, in case the
3815
* upper is read-write while the child is read-only; GUC will incorrectly
3816
* think it should leave the child state in place.
3818
XactReadOnly = s->prevXactReadOnly;
3820
CurrentResourceOwner = s->parent->curTransactionOwner;
3821
CurTransactionResourceOwner = s->parent->curTransactionOwner;
3822
ResourceOwnerDelete(s->curTransactionOwner);
3823
s->curTransactionOwner = NULL;
3825
AtSubCommit_Memory();
3827
s->state = TRANS_DEFAULT;
3833
* AbortSubTransaction
3836
AbortSubTransaction(void)
3838
TransactionState s = CurrentTransactionState;
3840
/* Prevent cancel/die interrupt while cleaning up */
3843
/* Make sure we have a valid memory context and resource owner */
3844
AtSubAbort_Memory();
3845
AtSubAbort_ResourceOwner();
3848
* Release any LW locks we might be holding as quickly as possible.
3849
* (Regular locks, however, must be held till we finish aborting.)
3850
* Releasing LW locks is critical since we might try to grab them again
3851
* while cleaning up!
3853
* FIXME This may be incorrect --- Are there some locks we should keep?
3854
* Buffer locks, for example? I don't think so but I'm not sure.
3864
* check the current transaction state
3866
ShowTransactionState("AbortSubTransaction");
3868
if (s->state != TRANS_INPROGRESS)
3869
elog(WARNING, "AbortSubTransaction while in %s state",
3870
TransStateAsString(s->state));
3872
s->state = TRANS_ABORT;
3875
* Reset user ID which might have been changed transiently. (See notes
3876
* in AbortTransaction.)
3878
SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
3881
* We can skip all this stuff if the subxact failed before creating a
3884
if (s->curTransactionOwner)
3886
AfterTriggerEndSubXact(false);
3887
AtSubAbort_Portals(s->subTransactionId,
3888
s->parent->subTransactionId,
3889
s->parent->curTransactionOwner);
3890
AtEOSubXact_LargeObject(false, s->subTransactionId,
3891
s->parent->subTransactionId);
3892
AtSubAbort_Notify();
3893
AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3894
s->parent->subTransactionId);
3896
/* Advertise the fact that we aborted in pg_clog. */
3897
(void) RecordTransactionAbort(true);
3899
/* Post-abort cleanup */
3900
if (TransactionIdIsValid(s->transactionId))
3901
AtSubAbort_childXids();
3903
CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3904
s->parent->subTransactionId);
3906
ResourceOwnerRelease(s->curTransactionOwner,
3907
RESOURCE_RELEASE_BEFORE_LOCKS,
3909
AtEOSubXact_RelationCache(false, s->subTransactionId,
3910
s->parent->subTransactionId);
3911
AtEOSubXact_Inval(false);
3913
ResourceOwnerRelease(s->curTransactionOwner,
3914
RESOURCE_RELEASE_LOCKS,
3916
ResourceOwnerRelease(s->curTransactionOwner,
3917
RESOURCE_RELEASE_AFTER_LOCKS,
3920
AtEOXact_GUC(false, s->gucNestLevel);
3921
AtEOSubXact_SPI(false, s->subTransactionId);
3923
AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3924
s->parent->subTransactionId);
3925
AtEOSubXact_Namespace(false, s->subTransactionId,
3926
s->parent->subTransactionId);
3927
AtEOSubXact_Files(false, s->subTransactionId,
3928
s->parent->subTransactionId);
3929
AtEOSubXact_HashTables(false, s->nestingLevel);
3930
AtEOSubXact_PgStat(false, s->nestingLevel);
3931
AtSubAbort_Snapshot(s->nestingLevel);
3935
* Restore the upper transaction's read-only state, too. This should be
3936
* redundant with GUC's cleanup but we may as well do it for consistency
3937
* with the commit case.
3939
XactReadOnly = s->prevXactReadOnly;
3941
RESUME_INTERRUPTS();
3945
* CleanupSubTransaction
3947
* The caller has to make sure to always reassign CurrentTransactionState
3948
* if it has a local pointer to it after calling this function.
3951
CleanupSubTransaction(void)
3953
TransactionState s = CurrentTransactionState;
3955
ShowTransactionState("CleanupSubTransaction");
3957
if (s->state != TRANS_ABORT)
3958
elog(WARNING, "CleanupSubTransaction while in %s state",
3959
TransStateAsString(s->state));
3961
AtSubCleanup_Portals(s->subTransactionId);
3963
CurrentResourceOwner = s->parent->curTransactionOwner;
3964
CurTransactionResourceOwner = s->parent->curTransactionOwner;
3965
if (s->curTransactionOwner)
3966
ResourceOwnerDelete(s->curTransactionOwner);
3967
s->curTransactionOwner = NULL;
3969
AtSubCleanup_Memory();
3971
s->state = TRANS_DEFAULT;
3978
* Create transaction state stack entry for a subtransaction
3980
* The caller has to make sure to always reassign CurrentTransactionState
3981
* if it has a local pointer to it after calling this function.
3984
PushTransaction(void)
3986
TransactionState p = CurrentTransactionState;
3990
* We keep subtransaction state nodes in TopTransactionContext.
3992
s = (TransactionState)
3993
MemoryContextAllocZero(TopTransactionContext,
3994
sizeof(TransactionStateData));
3997
* Assign a subtransaction ID, watching out for counter wraparound.
3999
currentSubTransactionId += 1;
4000
if (currentSubTransactionId == InvalidSubTransactionId)
4002
currentSubTransactionId -= 1;
4005
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4006
errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
4010
* We can now stack a minimally valid subtransaction without fear of
4013
s->transactionId = InvalidTransactionId; /* until assigned */
4014
s->subTransactionId = currentSubTransactionId;
4016
s->nestingLevel = p->nestingLevel + 1;
4017
s->gucNestLevel = NewGUCNestLevel();
4018
s->savepointLevel = p->savepointLevel;
4019
s->state = TRANS_DEFAULT;
4020
s->blockState = TBLOCK_SUBBEGIN;
4021
GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
4022
s->prevXactReadOnly = XactReadOnly;
4024
CurrentTransactionState = s;
4027
* AbortSubTransaction and CleanupSubTransaction have to be able to cope
4028
* with the subtransaction from here on out; in particular they should not
4029
* assume that it necessarily has a transaction context, resource owner,
4036
* Pop back to parent transaction state
4038
* The caller has to make sure to always reassign CurrentTransactionState
4039
* if it has a local pointer to it after calling this function.
4042
PopTransaction(void)
4044
TransactionState s = CurrentTransactionState;
4046
if (s->state != TRANS_DEFAULT)
4047
elog(WARNING, "PopTransaction while in %s state",
4048
TransStateAsString(s->state));
4050
if (s->parent == NULL)
4051
elog(FATAL, "PopTransaction with no parent");
4053
CurrentTransactionState = s->parent;
4055
/* Let's just make sure CurTransactionContext is good */
4056
CurTransactionContext = s->parent->curTransactionContext;
4057
MemoryContextSwitchTo(CurTransactionContext);
4059
/* Ditto for ResourceOwner links */
4060
CurTransactionResourceOwner = s->parent->curTransactionOwner;
4061
CurrentResourceOwner = s->parent->curTransactionOwner;
4063
/* Free the old child structure */
4070
* ShowTransactionState
4074
ShowTransactionState(const char *str)
4076
/* skip work if message will definitely not be printed */
4077
if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
4079
elog(DEBUG3, "%s", str);
4080
ShowTransactionStateRec(CurrentTransactionState);
4085
* ShowTransactionStateRec
4086
* Recursive subroutine for ShowTransactionState
4089
ShowTransactionStateRec(TransactionState s)
4093
initStringInfo(&buf);
4095
if (s->nChildXids > 0)
4099
appendStringInfo(&buf, "%u", s->childXids[0]);
4100
for (i = 1; i < s->nChildXids; i++)
4101
appendStringInfo(&buf, " %u", s->childXids[i]);
4105
ShowTransactionStateRec(s->parent);
4107
/* use ereport to suppress computation if msg will not be printed */
4109
(errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
4110
PointerIsValid(s->name) ? s->name : "unnamed",
4111
BlockStateAsString(s->blockState),
4112
TransStateAsString(s->state),
4113
(unsigned int) s->transactionId,
4114
(unsigned int) s->subTransactionId,
4115
(unsigned int) currentCommandId,
4116
currentCommandIdUsed ? " (used)" : "",
4117
s->nestingLevel, buf.data)));
4123
* BlockStateAsString
4127
BlockStateAsString(TBlockState blockState)
4131
case TBLOCK_DEFAULT:
4133
case TBLOCK_STARTED:
4137
case TBLOCK_INPROGRESS:
4138
return "INPROGRESS";
4143
case TBLOCK_ABORT_END:
4145
case TBLOCK_ABORT_PENDING:
4146
return "ABORT PEND";
4147
case TBLOCK_PREPARE:
4149
case TBLOCK_SUBBEGIN:
4151
case TBLOCK_SUBINPROGRESS:
4152
return "SUB INPROGRS";
4155
case TBLOCK_SUBABORT:
4157
case TBLOCK_SUBABORT_END:
4158
return "SUB ABORT END";
4159
case TBLOCK_SUBABORT_PENDING:
4160
return "SUB ABRT PEND";
4161
case TBLOCK_SUBRESTART:
4162
return "SUB RESTART";
4163
case TBLOCK_SUBABORT_RESTART:
4164
return "SUB AB RESTRT";
4166
return "UNRECOGNIZED";
4170
* TransStateAsString
4174
TransStateAsString(TransState state)
4182
case TRANS_INPROGRESS:
4191
return "UNRECOGNIZED";
4195
* xactGetCommittedChildren
4197
* Gets the list of committed children of the current transaction. The return
4198
* value is the number of child transactions. *ptr is set to point to an
4199
* array of TransactionIds. The array is allocated in TopTransactionContext;
4200
* the caller should *not* pfree() it (this is a change from pre-8.4 code!).
4201
* If there are no subxacts, *ptr is set to NULL.
4204
xactGetCommittedChildren(TransactionId **ptr)
4206
TransactionState s = CurrentTransactionState;
4208
if (s->nChildXids == 0)
4211
*ptr = s->childXids;
4213
return s->nChildXids;
4217
* XLOG support routines
4221
xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4223
TransactionId *sub_xids;
4224
TransactionId max_xid;
4227
/* Mark the transaction committed in pg_clog */
4228
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4229
TransactionIdCommitTree(xid, xlrec->nsubxacts, sub_xids);
4231
/* Make sure nextXid is beyond any XID mentioned in the record */
4233
for (i = 0; i < xlrec->nsubxacts; i++)
4235
if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4236
max_xid = sub_xids[i];
4238
if (TransactionIdFollowsOrEquals(max_xid,
4239
ShmemVariableCache->nextXid))
4241
ShmemVariableCache->nextXid = max_xid;
4242
TransactionIdAdvance(ShmemVariableCache->nextXid);
4245
/* Make sure files supposed to be dropped are dropped */
4246
for (i = 0; i < xlrec->nrels; i++)
4248
SMgrRelation srel = smgropen(xlrec->xnodes[i]);
4251
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4253
if (smgrexists(srel, fork))
4255
XLogDropRelation(xlrec->xnodes[i], fork);
4256
smgrdounlink(srel, fork, false, true);
4264
xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4266
TransactionId *sub_xids;
4267
TransactionId max_xid;
4270
/* Mark the transaction aborted in pg_clog */
4271
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4272
TransactionIdAbortTree(xid, xlrec->nsubxacts, sub_xids);
4274
/* Make sure nextXid is beyond any XID mentioned in the record */
4276
for (i = 0; i < xlrec->nsubxacts; i++)
4278
if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4279
max_xid = sub_xids[i];
4281
if (TransactionIdFollowsOrEquals(max_xid,
4282
ShmemVariableCache->nextXid))
4284
ShmemVariableCache->nextXid = max_xid;
4285
TransactionIdAdvance(ShmemVariableCache->nextXid);
4288
/* Make sure files supposed to be dropped are dropped */
4289
for (i = 0; i < xlrec->nrels; i++)
4291
SMgrRelation srel = smgropen(xlrec->xnodes[i]);
4294
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4296
if (smgrexists(srel, fork))
4298
XLogDropRelation(xlrec->xnodes[i], fork);
4299
smgrdounlink(srel, fork, false, true);
4307
xact_redo(XLogRecPtr lsn, XLogRecord *record)
4309
uint8 info = record->xl_info & ~XLR_INFO_MASK;
4311
/* Backup blocks are not used in xact records */
4312
Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
4314
if (info == XLOG_XACT_COMMIT)
4316
xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4318
xact_redo_commit(xlrec, record->xl_xid);
4320
else if (info == XLOG_XACT_ABORT)
4322
xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4324
xact_redo_abort(xlrec, record->xl_xid);
4326
else if (info == XLOG_XACT_PREPARE)
4328
/* the record contents are exactly the 2PC file */
4329
RecreateTwoPhaseFile(record->xl_xid,
4330
XLogRecGetData(record), record->xl_len);
4332
else if (info == XLOG_XACT_COMMIT_PREPARED)
4334
xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4336
xact_redo_commit(&xlrec->crec, xlrec->xid);
4337
RemoveTwoPhaseFile(xlrec->xid, false);
4339
else if (info == XLOG_XACT_ABORT_PREPARED)
4341
xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4343
xact_redo_abort(&xlrec->arec, xlrec->xid);
4344
RemoveTwoPhaseFile(xlrec->xid, false);
4347
elog(PANIC, "xact_redo: unknown op code %u", info);
4351
xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4355
appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4356
if (xlrec->nrels > 0)
4358
appendStringInfo(buf, "; rels:");
4359
for (i = 0; i < xlrec->nrels; i++)
4361
char *path = relpath(xlrec->xnodes[i], MAIN_FORKNUM);
4362
appendStringInfo(buf, " %s", path);
4366
if (xlrec->nsubxacts > 0)
4368
TransactionId *xacts = (TransactionId *)
4369
&xlrec->xnodes[xlrec->nrels];
4371
appendStringInfo(buf, "; subxacts:");
4372
for (i = 0; i < xlrec->nsubxacts; i++)
4373
appendStringInfo(buf, " %u", xacts[i]);
4378
xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4382
appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4383
if (xlrec->nrels > 0)
4385
appendStringInfo(buf, "; rels:");
4386
for (i = 0; i < xlrec->nrels; i++)
4388
char *path = relpath(xlrec->xnodes[i], MAIN_FORKNUM);
4389
appendStringInfo(buf, " %s", path);
4393
if (xlrec->nsubxacts > 0)
4395
TransactionId *xacts = (TransactionId *)
4396
&xlrec->xnodes[xlrec->nrels];
4398
appendStringInfo(buf, "; subxacts:");
4399
for (i = 0; i < xlrec->nsubxacts; i++)
4400
appendStringInfo(buf, " %u", xacts[i]);
4405
xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4407
uint8 info = xl_info & ~XLR_INFO_MASK;
4409
if (info == XLOG_XACT_COMMIT)
4411
xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4413
appendStringInfo(buf, "commit: ");
4414
xact_desc_commit(buf, xlrec);
4416
else if (info == XLOG_XACT_ABORT)
4418
xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4420
appendStringInfo(buf, "abort: ");
4421
xact_desc_abort(buf, xlrec);
4423
else if (info == XLOG_XACT_PREPARE)
4425
appendStringInfo(buf, "prepare");
4427
else if (info == XLOG_XACT_COMMIT_PREPARED)
4429
xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4431
appendStringInfo(buf, "commit %u: ", xlrec->xid);
4432
xact_desc_commit(buf, &xlrec->crec);
4434
else if (info == XLOG_XACT_ABORT_PREPARED)
4436
xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4438
appendStringInfo(buf, "abort %u: ", xlrec->xid);
4439
xact_desc_abort(buf, &xlrec->arec);
4442
appendStringInfo(buf, "UNKNOWN");