Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb6197fe

Browse files
committed
Further review of xact.c state machine for nested transactions. Fix
problems with starting subtransactions inside already-failed transactions.Clean up some comments.
1 parente15d0bb commitb6197fe

File tree

3 files changed

+175
-32
lines changed

3 files changed

+175
-32
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.169 2004/07/0100:49:42 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.170 2004/07/0120:11:02 tgl Exp $
1212
*
1313
* NOTES
1414
*Transaction aborts can now occur two ways:
@@ -196,6 +196,7 @@ static void StartSubTransaction(void);
196196
staticvoidCommitSubTransaction(void);
197197
staticvoidAbortSubTransaction(void);
198198
staticvoidCleanupSubTransaction(void);
199+
staticvoidStartAbortedSubTransaction(void);
199200
staticvoidPushTransaction(void);
200201
staticvoidPopTransaction(void);
201202

@@ -317,7 +318,7 @@ IsAbortedTransactionBlockState(void)
317318
TransactionStates=CurrentTransactionState;
318319

319320
if (s->blockState==TBLOCK_ABORT||
320-
s->blockState==TBLOCK_SUBABORT)
321+
s->blockState==TBLOCK_SUBABORT)
321322
return true;
322323

323324
return false;
@@ -1579,10 +1580,9 @@ StartTransactionCommand(void)
15791580
break;
15801581

15811582
/*
1582-
* This is the case when are somewhere in a transaction block
1583+
* This is the case whenweare somewhere in a transaction block
15831584
* and about to start a new command. For now we do nothing
1584-
* but someday we may do command-local resource
1585-
* initialization.
1585+
* but someday we may do command-local resource initialization.
15861586
*/
15871587
caseTBLOCK_INPROGRESS:
15881588
caseTBLOCK_SUBINPROGRESS:
@@ -1699,7 +1699,9 @@ CommitTransactionCommand(void)
16991699

17001700
/*
17011701
* We were just issued a BEGIN inside a transaction block.
1702-
* Start a subtransaction.
1702+
* Start a subtransaction. (BeginTransactionBlock already
1703+
* did PushTransaction, so as to have someplace to put the
1704+
* SUBBEGIN state.)
17031705
*/
17041706
caseTBLOCK_SUBBEGIN:
17051707
StartSubTransaction();
@@ -1711,8 +1713,7 @@ CommitTransactionCommand(void)
17111713
* Start a subtransaction, and put it in aborted state.
17121714
*/
17131715
caseTBLOCK_SUBBEGINABORT:
1714-
StartSubTransaction();
1715-
AbortSubTransaction();
1716+
StartAbortedSubTransaction();
17161717
s->blockState=TBLOCK_SUBABORT;
17171718
break;
17181719

@@ -1724,7 +1725,7 @@ CommitTransactionCommand(void)
17241725
break;
17251726

17261727
/*
1727-
* Wewhere issued a COMMIT command, so we end the current
1728+
* Wewere issued a COMMIT command, so we end the current
17281729
* subtransaction and return to the parent transaction.
17291730
*/
17301731
caseTBLOCK_SUBEND:
@@ -1740,7 +1741,7 @@ CommitTransactionCommand(void)
17401741
break;
17411742

17421743
/*
1743-
* We are endingasubtransactionthat aborted nicely,
1744+
* We are endingan abortedsubtransactionvia ROLLBACK,
17441745
* so the parent can be allowed to live.
17451746
*/
17461747
caseTBLOCK_SUBENDABORT_OK:
@@ -1750,9 +1751,8 @@ CommitTransactionCommand(void)
17501751
break;
17511752

17521753
/*
1753-
* We are ending a subtransaction that aborted in a unclean
1754-
* way (e.g. the user issued COMMIT in an aborted subtrasaction.)
1755-
* Abort the subtransaction, and abort the parent too.
1754+
* We are ending an aborted subtransaction via COMMIT.
1755+
* End the subtransaction, and abort the parent too.
17561756
*/
17571757
caseTBLOCK_SUBENDABORT_ERROR:
17581758
CleanupSubTransaction();
@@ -1791,7 +1791,7 @@ AbortCurrentTransaction(void)
17911791
break;
17921792

17931793
/*
1794-
* If we are intheTBLOCK_BEGIN it means something screwed up
1794+
* If we are in TBLOCK_BEGIN it means something screwed up
17951795
* right after reading "BEGIN TRANSACTION" so we enter the
17961796
* abort state. Eventually an "END TRANSACTION" will fix
17971797
* things.
@@ -1803,10 +1803,10 @@ AbortCurrentTransaction(void)
18031803
break;
18041804

18051805
/*
1806-
* This is the case when are somewhere in a transaction block
1807-
*which abortedso we abort the transaction and set the ABORT
1808-
*state. Eventually an "END TRANSACTION"willfix things and
1809-
*restore us to a normal state.
1806+
* This is the case whenweare somewhere in a transaction block
1807+
*and we've gotten a failure,so we abort the transaction and
1808+
*set up the persistent ABORT state. Wewillstay in ABORT
1809+
*until we get an "END TRANSACTION".
18101810
*/
18111811
caseTBLOCK_INPROGRESS:
18121812
AbortTransaction();
@@ -1817,7 +1817,7 @@ AbortCurrentTransaction(void)
18171817
/*
18181818
* Here, the system was fouled up just after the user wanted
18191819
* to end the transaction block so we abort the transaction
1820-
* andput us back into the default state.
1820+
* andreturn to the default state.
18211821
*/
18221822
caseTBLOCK_END:
18231823
AbortTransaction();
@@ -1852,10 +1852,7 @@ AbortCurrentTransaction(void)
18521852
*/
18531853
caseTBLOCK_SUBBEGIN:
18541854
caseTBLOCK_SUBBEGINABORT:
1855-
PushTransaction();
1856-
s=CurrentTransactionState;/* changed by push */
1857-
StartSubTransaction();
1858-
AbortSubTransaction();
1855+
StartAbortedSubTransaction();
18591856
s->blockState=TBLOCK_SUBABORT;
18601857
break;
18611858

@@ -2092,8 +2089,10 @@ CallEOXactCallbacks(bool isCommit)
20922089
* transaction block support
20932090
* ----------------------------------------------------------------
20942091
*/
2092+
20952093
/*
20962094
*BeginTransactionBlock
2095+
*This executes a BEGIN command.
20972096
*/
20982097
void
20992098
BeginTransactionBlock(void)
@@ -2102,7 +2101,7 @@ BeginTransactionBlock(void)
21022101

21032102
switch (s->blockState) {
21042103
/*
2105-
* We are inside a transaction, so allowa transaction block
2104+
* We arenotinside a transaction block, so allowone
21062105
* to begin.
21072106
*/
21082107
caseTBLOCK_STARTED:
@@ -2149,6 +2148,7 @@ BeginTransactionBlock(void)
21492148

21502149
/*
21512150
*EndTransactionBlock
2151+
*This executes a COMMIT command.
21522152
*/
21532153
void
21542154
EndTransactionBlock(void)
@@ -2176,9 +2176,9 @@ EndTransactionBlock(void)
21762176
break;
21772177

21782178
/*
2179-
* here, we are in a transaction block which aborted and since the
2180-
* AbortTransaction() was already done, wedo whatever is needed
2181-
*andchange to the special "END ABORT" state. The upcoming
2179+
* here, we are in a transaction block which aborted. Since the
2180+
* AbortTransaction() was already done, weneed only
2181+
* change to the special "END ABORT" state. The upcoming
21822182
* CommitTransactionCommand() will recognise this and then put us
21832183
* back in the default state.
21842184
*/
@@ -2189,7 +2189,8 @@ EndTransactionBlock(void)
21892189
/*
21902190
* here we are in an aborted subtransaction. Signal
21912191
* CommitTransactionCommand() to clean up and return to the
2192-
* parent transaction.
2192+
* parent transaction. Since the user said COMMIT, we must
2193+
* fail the parent transaction.
21932194
*/
21942195
caseTBLOCK_SUBABORT:
21952196
s->blockState=TBLOCK_SUBENDABORT_ERROR;
@@ -2209,7 +2210,7 @@ EndTransactionBlock(void)
22092210
s->blockState=TBLOCK_ENDABORT;
22102211
break;
22112212

2212-
/*These cases are invalid. Reject them altogether. */
2213+
/*these cases are invalid. */
22132214
caseTBLOCK_DEFAULT:
22142215
caseTBLOCK_BEGIN:
22152216
caseTBLOCK_ENDABORT:
@@ -2227,6 +2228,7 @@ EndTransactionBlock(void)
22272228

22282229
/*
22292230
*UserAbortTransactionBlock
2231+
*This executes a ROLLBACK command.
22302232
*/
22312233
void
22322234
UserAbortTransactionBlock(void)
@@ -2244,7 +2246,10 @@ UserAbortTransactionBlock(void)
22442246
s->blockState=TBLOCK_ENDABORT;
22452247
break;
22462248

2247-
/* Ditto, for a subtransaction. */
2249+
/*
2250+
* Ditto, for a subtransaction. Here it is okay to allow the
2251+
* parent transaction to continue.
2252+
*/
22482253
caseTBLOCK_SUBABORT:
22492254
s->blockState=TBLOCK_SUBENDABORT_OK;
22502255
break;
@@ -2336,8 +2341,8 @@ AbortOutOfAnyTransaction(void)
23362341
caseTBLOCK_SUBBEGIN:
23372342
caseTBLOCK_SUBBEGINABORT:
23382343
/*
2339-
*Just starting a new transaction -- return to parent.
2340-
*FIXME -- Is this correct?
2344+
*We didn't get as far as starting the subxact, so there's
2345+
*nothing to abort. Just pop back to parent.
23412346
*/
23422347
PopTransaction();
23432348
s=CurrentTransactionState;/* changed by pop */
@@ -2353,6 +2358,7 @@ AbortOutOfAnyTransaction(void)
23532358
caseTBLOCK_SUBABORT:
23542359
caseTBLOCK_SUBENDABORT_OK:
23552360
caseTBLOCK_SUBENDABORT_ERROR:
2361+
/* As above, but AbortSubTransaction already done */
23562362
CleanupSubTransaction();
23572363
PopTransaction();
23582364
s=CurrentTransactionState;/* changed by pop */
@@ -2521,6 +2527,8 @@ CommitSubTransaction(void)
25212527
AtSubCommit_Portals(s->parent->transactionIdData);
25222528
DeferredTriggerEndSubXact(true);
25232529

2530+
s->state=TRANS_COMMIT;
2531+
25242532
/* Mark subtransaction as subcommitted */
25252533
CommandCounterIncrement();
25262534
RecordSubTransactionCommit();
@@ -2642,6 +2650,49 @@ CleanupSubTransaction(void)
26422650
s->state=TRANS_DEFAULT;
26432651
}
26442652

2653+
/*
2654+
* StartAbortedSubTransaction
2655+
*
2656+
* This function is used to start a subtransaction and put it immediately
2657+
* into aborted state. The end result should be equivalent to
2658+
* StartSubTransaction immediately followed by AbortSubTransaction.
2659+
* The reason we don't implement it just that way is that many of the backend
2660+
* modules aren't designed to handle starting a subtransaction when not
2661+
* inside a valid transaction. Rather than making them all capable of
2662+
* doing that, we just omit the paired start and abort calls in this path.
2663+
*/
2664+
staticvoid
2665+
StartAbortedSubTransaction(void)
2666+
{
2667+
TransactionStates=CurrentTransactionState;
2668+
2669+
if (s->state!=TRANS_DEFAULT)
2670+
elog(WARNING,"StartAbortedSubTransaction and not in default state");
2671+
2672+
s->state=TRANS_START;
2673+
2674+
/*
2675+
* We don't bother to generate a new Xid, so the end state is not
2676+
* *exactly* like we had done a full Start/AbortSubTransaction...
2677+
*/
2678+
s->transactionIdData=InvalidTransactionId;
2679+
2680+
/* Make sure currentUser is reasonably valid */
2681+
Assert(s->parent!=NULL);
2682+
s->currentUser=s->parent->currentUser;
2683+
2684+
/*
2685+
* Initialize only what has to be there for CleanupSubTransaction to work.
2686+
*/
2687+
AtSubStart_Memory();
2688+
2689+
s->state=TRANS_ABORT;
2690+
2691+
AtSubAbort_Memory();
2692+
2693+
ShowTransactionState("StartAbortedSubTransaction");
2694+
}
2695+
26452696
/*
26462697
* PushTransaction
26472698
*Set up transaction state for a subtransaction
@@ -2672,6 +2723,7 @@ PushTransaction(void)
26722723
*/
26732724
s->transactionIdData=p->transactionIdData;
26742725
s->curTransactionContext=p->curTransactionContext;
2726+
s->currentUser=p->currentUser;
26752727

26762728
CurrentTransactionState=s;
26772729
}

‎src/test/regress/expected/transactions.out

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,65 @@ SELECT * FROM barbaz;-- should have 1
132132
1
133133
(1 row)
134134

135+
-- check that starting a subxact in a failed xact or subxact works
136+
BEGIN;
137+
SELECT 0/0;-- fail the outer xact
138+
ERROR: division by zero
139+
BEGIN;
140+
SELECT 1;-- this should NOT work
141+
ERROR: current transaction is aborted, commands ignored until end of transaction block
142+
COMMIT;
143+
SELECT 1;-- this should NOT work
144+
ERROR: current transaction is aborted, commands ignored until end of transaction block
145+
BEGIN;
146+
SELECT 1;-- this should NOT work
147+
ERROR: current transaction is aborted, commands ignored until end of transaction block
148+
ROLLBACK;
149+
SELECT 1;-- this should NOT work
150+
ERROR: current transaction is aborted, commands ignored until end of transaction block
151+
COMMIT;
152+
SELECT 1;-- this should work
153+
?column?
154+
----------
155+
1
156+
(1 row)
157+
158+
BEGIN;
159+
BEGIN;
160+
SELECT 1;-- this should work
161+
?column?
162+
----------
163+
1
164+
(1 row)
165+
166+
SELECT 0/0;-- fail the subxact
167+
ERROR: division by zero
168+
SELECT 1;-- this should NOT work
169+
ERROR: current transaction is aborted, commands ignored until end of transaction block
170+
BEGIN;
171+
SELECT 1;-- this should NOT work
172+
ERROR: current transaction is aborted, commands ignored until end of transaction block
173+
ROLLBACK;
174+
BEGIN;
175+
SELECT 1;-- this should NOT work
176+
ERROR: current transaction is aborted, commands ignored until end of transaction block
177+
COMMIT;
178+
SELECT 1;-- this should NOT work
179+
ERROR: current transaction is aborted, commands ignored until end of transaction block
180+
ROLLBACK;
181+
SELECT 1;-- this should work
182+
?column?
183+
----------
184+
1
185+
(1 row)
186+
187+
COMMIT;
188+
SELECT 1;-- this should work
189+
?column?
190+
----------
191+
1
192+
(1 row)
193+
135194
DROP TABLE foo;
136195
DROP TABLE baz;
137196
DROP TABLE barbaz;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp