savepoint_commit_performance.v1.patch
text/x-patch
Filename: savepoint_commit_performance.v1.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/access/transam/xact.c | 16 | 6 |
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 18e9ce1..07c84b4 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -269,7 +269,7 @@ static TransactionId RecordTransactionAbort(bool isSubXact);
static void StartTransaction(void);
static void StartSubTransaction(void);
-static void CommitSubTransaction(void);
+static void CommitSubTransaction(bool isTopLevel);
static void AbortSubTransaction(void);
static void CleanupSubTransaction(void);
static void PushTransaction(void);
@@ -2518,7 +2518,7 @@ CommitTransactionCommand(void)
case TBLOCK_SUBEND:
do
{
- CommitSubTransaction();
+ CommitSubTransaction(true);
s = CurrentTransactionState; /* changed by pop */
} while (s->blockState == TBLOCK_SUBEND);
/* If we had a COMMIT command, finish off the main xact too */
@@ -3664,7 +3664,7 @@ ReleaseCurrentSubTransaction(void)
BlockStateAsString(s->blockState));
Assert(s->state == TRANS_INPROGRESS);
MemoryContextSwitchTo(CurTransactionContext);
- CommitSubTransaction();
+ CommitSubTransaction(false);
s = CurrentTransactionState; /* changed by pop */
Assert(s->state == TRANS_INPROGRESS);
}
@@ -3925,9 +3925,13 @@ StartSubTransaction(void)
*
* The caller has to make sure to always reassign CurrentTransactionState
* if it has a local pointer to it after calling this function.
+ *
+ * isTopLevel means that this CommitSubTransaction() is being issued as a
+ * sequence of actions leading directly to a main transaction commit
+ * allowing some actions to be optimised.
*/
static void
-CommitSubTransaction(void)
+CommitSubTransaction(bool isTopLevel)
{
TransactionState s = CurrentTransactionState;
@@ -3974,15 +3978,21 @@ CommitSubTransaction(void)
/*
* The only lock we actually release here is the subtransaction XID lock.
- * The rest just get transferred to the parent resource owner.
*/
CurrentResourceOwner = s->curTransactionOwner;
if (TransactionIdIsValid(s->transactionId))
XactLockTableDelete(s->transactionId);
+ /*
+ * Other locks should get transferred to their parent resource owner.
+ * Doing that is an O(N^2) operation, so if isTopLevel then we can just
+ * leave the lock records as they are, knowing they will all get released
+ * by the top level commit using ProcReleaseLocks(). We only optimize
+ * this for commit; aborts may need to do other cleanup.
+ */
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_LOCKS,
- true, false);
+ true, isTopLevel);
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_AFTER_LOCKS,
true, false);