agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Nikita Glukhov <[email protected]>
Subject: [PATCH 09/11] Optimize SQL/JSON subtransactions
Date: Mon, 26 Nov 2018 19:03:43 +0300
---
src/backend/access/transam/xact.c | 137 +++++++++++++++++++++++++++++++---
src/backend/executor/execExprInterp.c | 2 +-
src/include/access/xact.h | 1 +
3 files changed, 130 insertions(+), 10 deletions(-)
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index d967400..d8fe3a2 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -189,6 +189,8 @@ typedef struct TransactionStateData
bool startedInRecovery; /* did we start in recovery? */
bool didLogXid; /* has xid been included in WAL record? */
int parallelModeLevel; /* Enter/ExitParallelMode counter */
+ bool isCachedSubXact;
+ struct TransactionStateData *cachedSubXact;
struct TransactionStateData *parent; /* back link to parent */
} TransactionStateData;
@@ -302,7 +304,7 @@ static void CommitSubTransaction(void);
static void AbortSubTransaction(void);
static void CleanupSubTransaction(void);
static void PushTransaction(void);
-static void PopTransaction(void);
+static void PopTransaction(bool free);
static void AtSubAbort_Memory(void);
static void AtSubCleanup_Memory(void);
@@ -316,6 +318,8 @@ static void ShowTransactionStateRec(const char *str, TransactionState state);
static const char *BlockStateAsString(TBlockState blockState);
static const char *TransStateAsString(TransState state);
+static void ReleaseCurrentCachedSubTransaction(void);
+static void RollbackAndReleaseCurrentCachedSubTransaction(void);
/* ----------------------------------------------------------------
* transaction state accessors
@@ -2768,6 +2772,8 @@ CommitTransactionCommand(void)
{
TransactionState s = CurrentTransactionState;
+ ReleaseCurrentCachedSubTransaction();
+
switch (s->blockState)
{
/*
@@ -3008,6 +3014,8 @@ AbortCurrentTransaction(void)
{
TransactionState s = CurrentTransactionState;
+ RollbackAndReleaseCurrentCachedSubTransaction();
+
switch (s->blockState)
{
case TBLOCK_DEFAULT:
@@ -4155,6 +4163,47 @@ RollbackToSavepoint(const char *name)
BlockStateAsString(xact->blockState));
}
+static void
+RestoreSubTransactionState(TransactionState subxact)
+{
+ CurrentTransactionState = subxact;
+
+ CurTransactionContext = subxact->curTransactionContext;
+ MemoryContextSwitchTo(CurTransactionContext);
+ CurTransactionResourceOwner = subxact->curTransactionOwner;
+ CurrentResourceOwner = subxact->curTransactionOwner;
+}
+
+static void
+ReleaseCurrentCachedSubTransaction(void)
+{
+ TransactionState s = CurrentTransactionState;
+
+ if (s->cachedSubXact)
+ {
+ RestoreSubTransactionState(s->cachedSubXact);
+ ReleaseCurrentCachedSubTransaction();
+ MemoryContextSwitchTo(CurTransactionContext);
+ CommitSubTransaction();
+ Assert(s == CurrentTransactionState);
+ s->cachedSubXact = NULL;
+ }
+}
+
+static void
+RollbackAndReleaseCurrentCachedSubTransaction(void)
+{
+ TransactionState s = CurrentTransactionState;
+
+ if (s->cachedSubXact)
+ {
+ RestoreSubTransactionState(s->cachedSubXact);
+ RollbackAndReleaseCurrentSubTransaction();
+ Assert(s == CurrentTransactionState);
+ s->cachedSubXact = NULL;
+ }
+}
+
/*
* BeginInternalSubTransaction
* This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
@@ -4165,8 +4214,8 @@ RollbackToSavepoint(const char *name)
* CommitTransactionCommand/StartTransactionCommand instead of expecting
* the caller to do it.
*/
-void
-BeginInternalSubTransaction(const char *name)
+static void
+BeginInternalSubTransactionInternal(const char *name, bool cached)
{
TransactionState s = CurrentTransactionState;
@@ -4193,10 +4242,31 @@ BeginInternalSubTransaction(const char *name)
case TBLOCK_END:
case TBLOCK_PREPARE:
case TBLOCK_SUBINPROGRESS:
+ if (s->cachedSubXact)
+ {
+ TransactionState subxact = s->cachedSubXact;
+
+ s->cachedSubXact = NULL;
+
+ Assert(subxact->subTransactionId == currentSubTransactionId);
+ if (subxact->subTransactionId == currentSubTransactionId)
+ {
+ /* reuse cached subtransaction */
+ RestoreSubTransactionState(subxact);
+ return;
+ }
+ else
+ {
+ ReleaseCurrentCachedSubTransaction();
+ }
+ }
+
/* Normal subtransaction start */
PushTransaction();
s = CurrentTransactionState; /* changed by push */
+ s->isCachedSubXact = cached;
+
/*
* Savepoint names, like the TransactionState block itself, live
* in TopTransactionContext.
@@ -4229,6 +4299,18 @@ BeginInternalSubTransaction(const char *name)
StartTransactionCommand();
}
+void
+BeginInternalSubTransaction(const char *name)
+{
+ BeginInternalSubTransactionInternal(name, false);
+}
+
+void
+BeginInternalCachedSubTransaction(const char *name)
+{
+ BeginInternalSubTransactionInternal(name, true);
+}
+
/*
* ReleaseCurrentSubTransaction
*
@@ -4257,8 +4339,40 @@ ReleaseCurrentSubTransaction(void)
elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
BlockStateAsString(s->blockState));
Assert(s->state == TRANS_INPROGRESS);
- MemoryContextSwitchTo(CurTransactionContext);
- CommitSubTransaction();
+
+ ReleaseCurrentCachedSubTransaction();
+
+ if (s->isCachedSubXact &&
+ !TransactionIdIsValid(s->transactionId) &&
+ !s->cachedSubXact /*&
+ (!s->curTransactionOwner ||
+ (!s->curTransactionOwner->firstchild &&
+ s->curTransactionOwner->nlocks <= 0))*/)
+ {
+ if (s->curTransactionOwner)
+ {
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_BEFORE_LOCKS,
+ true, false);
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_LOCKS,
+ true, false);
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_AFTER_LOCKS,
+ true, false);
+ }
+
+ Assert(!s->parent->cachedSubXact);
+ s->parent->cachedSubXact = s;
+
+ PopTransaction(false);
+ }
+ else
+ {
+ MemoryContextSwitchTo(CurTransactionContext);
+ CommitSubTransaction();
+ }
+
s = CurrentTransactionState; /* changed by pop */
Assert(s->state == TRANS_INPROGRESS);
}
@@ -4314,6 +4428,8 @@ RollbackAndReleaseCurrentSubTransaction(void)
break;
}
+ RollbackAndReleaseCurrentCachedSubTransaction();
+
/*
* Abort the current subtransaction, if needed.
*/
@@ -4678,7 +4794,7 @@ CommitSubTransaction(void)
s->state = TRANS_DEFAULT;
- PopTransaction();
+ PopTransaction(true);
}
/*
@@ -4856,7 +4972,7 @@ CleanupSubTransaction(void)
s->state = TRANS_DEFAULT;
- PopTransaction();
+ PopTransaction(true);
}
/*
@@ -4926,11 +5042,11 @@ PushTransaction(void)
* if it has a local pointer to it after calling this function.
*/
static void
-PopTransaction(void)
+PopTransaction(bool free)
{
TransactionState s = CurrentTransactionState;
- if (s->state != TRANS_DEFAULT)
+ if (free && s->state != TRANS_DEFAULT)
elog(WARNING, "PopTransaction while in %s state",
TransStateAsString(s->state));
@@ -4947,6 +5063,9 @@ PopTransaction(void)
CurTransactionResourceOwner = s->parent->curTransactionOwner;
CurrentResourceOwner = s->parent->curTransactionOwner;
+ if (!free)
+ return;
+
/* Free the old child structure */
if (s->name)
pfree(s->name);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 7798812..973227d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4536,7 +4536,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
MemoryContext oldcontext = CurrentMemoryContext;
ResourceOwner oldowner = CurrentResourceOwner;
- BeginInternalSubTransaction(NULL);
+ BeginInternalCachedSubTransaction(NULL);
/* Want to execute expressions inside function's memory context */
MemoryContextSwitchTo(oldcontext);
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 689c57c..0a70936 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -381,6 +381,7 @@ extern void ReleaseSavepoint(const char *name);
extern void DefineSavepoint(const char *name);
extern void RollbackToSavepoint(const char *name);
extern void BeginInternalSubTransaction(const char *name);
+extern void BeginInternalCachedSubTransaction(const char *name);
extern void ReleaseCurrentSubTransaction(void);
extern void RollbackAndReleaseCurrentSubTransaction(void);
extern bool IsSubTransaction(void);
--
2.7.4
--------------0D18A6F3D5DF72C86FFB8E95--
view thread (3+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 09/11] Optimize SQL/JSON subtransactions
In-Reply-To: <no-message-id-239507@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox