Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0e6b8b8

Browse files
author
Nikita Glukhov
committed
Optimize sqljson subtransactions
1 parent 743c812 commit 0e6b8b8

File tree

3 files changed

+130
-10
lines changed

3 files changed

+130
-10
lines changed

src/backend/access/transam/xact.c

Lines changed: 128 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ typedef struct TransactionStateData
189189
bool startedInRecovery; /* did we start in recovery? */
190190
bool didLogXid; /* has xid been included in WAL record? */
191191
int parallelModeLevel; /* Enter/ExitParallelMode counter */
192+
bool isCachedSubXact;
193+
struct TransactionStateData *cachedSubXact;
192194
struct TransactionStateData *parent; /* back link to parent */
193195
} TransactionStateData;
194196

@@ -302,7 +304,7 @@ static void CommitSubTransaction(void);
302304
static void AbortSubTransaction(void);
303305
static void CleanupSubTransaction(void);
304306
static void PushTransaction(void);
305-
static void PopTransaction(void);
307+
static void PopTransaction(bool free);
306308

307309
static void AtSubAbort_Memory(void);
308310
static void AtSubCleanup_Memory(void);
@@ -316,6 +318,8 @@ static void ShowTransactionStateRec(const char *str, TransactionState state);
316318
static const char *BlockStateAsString(TBlockState blockState);
317319
static const char *TransStateAsString(TransState state);
318320

321+
static void ReleaseCurrentCachedSubTransaction(void);
322+
static void RollbackAndReleaseCurrentCachedSubTransaction(void);
319323

320324
/* ----------------------------------------------------------------
321325
* transaction state accessors
@@ -2768,6 +2772,8 @@ CommitTransactionCommand(void)
27682772
{
27692773
TransactionState s = CurrentTransactionState;
27702774

2775+
ReleaseCurrentCachedSubTransaction();
2776+
27712777
switch (s->blockState)
27722778
{
27732779
/*
@@ -3008,6 +3014,8 @@ AbortCurrentTransaction(void)
30083014
{
30093015
TransactionState s = CurrentTransactionState;
30103016

3017+
RollbackAndReleaseCurrentCachedSubTransaction();
3018+
30113019
switch (s->blockState)
30123020
{
30133021
case TBLOCK_DEFAULT:
@@ -4155,6 +4163,47 @@ RollbackToSavepoint(const char *name)
41554163
BlockStateAsString(xact->blockState));
41564164
}
41574165

4166+
static void
4167+
RestoreSubTransactionState(TransactionState subxact)
4168+
{
4169+
CurrentTransactionState = subxact;
4170+
4171+
CurTransactionContext = subxact->curTransactionContext;
4172+
MemoryContextSwitchTo(CurTransactionContext);
4173+
CurTransactionResourceOwner = subxact->curTransactionOwner;
4174+
CurrentResourceOwner = subxact->curTransactionOwner;
4175+
}
4176+
4177+
static void
4178+
ReleaseCurrentCachedSubTransaction(void)
4179+
{
4180+
TransactionState s = CurrentTransactionState;
4181+
4182+
if (s->cachedSubXact)
4183+
{
4184+
RestoreSubTransactionState(s->cachedSubXact);
4185+
ReleaseCurrentCachedSubTransaction();
4186+
MemoryContextSwitchTo(CurTransactionContext);
4187+
CommitSubTransaction();
4188+
Assert(s == CurrentTransactionState);
4189+
s->cachedSubXact = NULL;
4190+
}
4191+
}
4192+
4193+
static void
4194+
RollbackAndReleaseCurrentCachedSubTransaction(void)
4195+
{
4196+
TransactionState s = CurrentTransactionState;
4197+
4198+
if (s->cachedSubXact)
4199+
{
4200+
RestoreSubTransactionState(s->cachedSubXact);
4201+
RollbackAndReleaseCurrentSubTransaction();
4202+
Assert(s == CurrentTransactionState);
4203+
s->cachedSubXact = NULL;
4204+
}
4205+
}
4206+
41584207
/*
41594208
* BeginInternalSubTransaction
41604209
* This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
@@ -4165,8 +4214,8 @@ RollbackToSavepoint(const char *name)
41654214
* CommitTransactionCommand/StartTransactionCommand instead of expecting
41664215
* the caller to do it.
41674216
*/
4168-
void
4169-
BeginInternalSubTransaction(const char *name)
4217+
static void
4218+
BeginInternalSubTransactionInternal(const char *name, bool cached)
41704219
{
41714220
TransactionState s = CurrentTransactionState;
41724221

@@ -4193,10 +4242,31 @@ BeginInternalSubTransaction(const char *name)
41934242
case TBLOCK_END:
41944243
case TBLOCK_PREPARE:
41954244
case TBLOCK_SUBINPROGRESS:
4245+
if (s->cachedSubXact)
4246+
{
4247+
TransactionState subxact = s->cachedSubXact;
4248+
4249+
s->cachedSubXact = NULL;
4250+
4251+
Assert(subxact->subTransactionId == currentSubTransactionId);
4252+
if (subxact->subTransactionId == currentSubTransactionId)
4253+
{
4254+
/* reuse cached subtransaction */
4255+
RestoreSubTransactionState(subxact);
4256+
return;
4257+
}
4258+
else
4259+
{
4260+
ReleaseCurrentCachedSubTransaction();
4261+
}
4262+
}
4263+
41964264
/* Normal subtransaction start */
41974265
PushTransaction();
41984266
s = CurrentTransactionState; /* changed by push */
41994267

4268+
s->isCachedSubXact = cached;
4269+
42004270
/*
42014271
* Savepoint names, like the TransactionState block itself, live
42024272
* in TopTransactionContext.
@@ -4229,6 +4299,18 @@ BeginInternalSubTransaction(const char *name)
42294299
StartTransactionCommand();
42304300
}
42314301

4302+
void
4303+
BeginInternalSubTransaction(const char *name)
4304+
{
4305+
BeginInternalSubTransactionInternal(name, false);
4306+
}
4307+
4308+
void
4309+
BeginInternalCachedSubTransaction(const char *name)
4310+
{
4311+
BeginInternalSubTransactionInternal(name, true);
4312+
}
4313+
42324314
/*
42334315
* ReleaseCurrentSubTransaction
42344316
*
@@ -4257,8 +4339,40 @@ ReleaseCurrentSubTransaction(void)
42574339
elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
42584340
BlockStateAsString(s->blockState));
42594341
Assert(s->state == TRANS_INPROGRESS);
4260-
MemoryContextSwitchTo(CurTransactionContext);
4261-
CommitSubTransaction();
4342+
4343+
ReleaseCurrentCachedSubTransaction();
4344+
4345+
if (s->isCachedSubXact &&
4346+
!TransactionIdIsValid(s->transactionId) &&
4347+
!s->cachedSubXact /*&
4348+
(!s->curTransactionOwner ||
4349+
(!s->curTransactionOwner->firstchild &&
4350+
s->curTransactionOwner->nlocks <= 0))*/)
4351+
{
4352+
if (s->curTransactionOwner)
4353+
{
4354+
ResourceOwnerRelease(s->curTransactionOwner,
4355+
RESOURCE_RELEASE_BEFORE_LOCKS,
4356+
true, false);
4357+
ResourceOwnerRelease(s->curTransactionOwner,
4358+
RESOURCE_RELEASE_LOCKS,
4359+
true, false);
4360+
ResourceOwnerRelease(s->curTransactionOwner,
4361+
RESOURCE_RELEASE_AFTER_LOCKS,
4362+
true, false);
4363+
}
4364+
4365+
Assert(!s->parent->cachedSubXact);
4366+
s->parent->cachedSubXact = s;
4367+
4368+
PopTransaction(false);
4369+
}
4370+
else
4371+
{
4372+
MemoryContextSwitchTo(CurTransactionContext);
4373+
CommitSubTransaction();
4374+
}
4375+
42624376
s = CurrentTransactionState; /* changed by pop */
42634377
Assert(s->state == TRANS_INPROGRESS);
42644378
}
@@ -4314,6 +4428,8 @@ RollbackAndReleaseCurrentSubTransaction(void)
43144428
break;
43154429
}
43164430

4431+
RollbackAndReleaseCurrentCachedSubTransaction();
4432+
43174433
/*
43184434
* Abort the current subtransaction, if needed.
43194435
*/
@@ -4678,7 +4794,7 @@ CommitSubTransaction(void)
46784794

46794795
s->state = TRANS_DEFAULT;
46804796

4681-
PopTransaction();
4797+
PopTransaction(true);
46824798
}
46834799

46844800
/*
@@ -4856,7 +4972,7 @@ CleanupSubTransaction(void)
48564972

48574973
s->state = TRANS_DEFAULT;
48584974

4859-
PopTransaction();
4975+
PopTransaction(true);
48604976
}
48614977

48624978
/*
@@ -4926,11 +5042,11 @@ PushTransaction(void)
49265042
* if it has a local pointer to it after calling this function.
49275043
*/
49285044
static void
4929-
PopTransaction(void)
5045+
PopTransaction(bool free)
49305046
{
49315047
TransactionState s = CurrentTransactionState;
49325048

4933-
if (s->state != TRANS_DEFAULT)
5049+
if (free && s->state != TRANS_DEFAULT)
49345050
elog(WARNING, "PopTransaction while in %s state",
49355051
TransStateAsString(s->state));
49365052

@@ -4947,6 +5063,9 @@ PopTransaction(void)
49475063
CurTransactionResourceOwner = s->parent->curTransactionOwner;
49485064
CurrentResourceOwner = s->parent->curTransactionOwner;
49495065

5066+
if (!free)
5067+
return;
5068+
49505069
/* Free the old child structure */
49515070
if (s->name)
49525071
pfree(s->name);

src/backend/executor/execExprInterp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4536,7 +4536,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
45364536
MemoryContext oldcontext = CurrentMemoryContext;
45374537
ResourceOwner oldowner = CurrentResourceOwner;
45384538

4539-
BeginInternalSubTransaction(NULL);
4539+
BeginInternalCachedSubTransaction(NULL);
45404540
/* Want to execute expressions inside function's memory context */
45414541
MemoryContextSwitchTo(oldcontext);
45424542

src/include/access/xact.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ extern void ReleaseSavepoint(const char *name);
381381
extern void DefineSavepoint(const char *name);
382382
extern void RollbackToSavepoint(const char *name);
383383
extern void BeginInternalSubTransaction(const char *name);
384+
extern void BeginInternalCachedSubTransaction(const char *name);
384385
extern void ReleaseCurrentSubTransaction(void);
385386
extern void RollbackAndReleaseCurrentSubTransaction(void);
386387
extern bool IsSubTransaction(void);

0 commit comments

Comments
 (0)