v2-0001-Wait-for-prepared-xacts-in-CREATE-INDEX-CONCURREN.patch
application/octet-stream
Filename: v2-0001-Wait-for-prepared-xacts-in-CREATE-INDEX-CONCURREN.patch
Type: application/octet-stream
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: format-patch
Series: patch v2-0001
Subject: Wait for prepared xacts in CREATE INDEX CONCURRENTLY locks infrastructure
| File | + | − |
|---|---|---|
| src/backend/storage/lmgr/lmgr.c | 2 | 3 |
| src/backend/storage/lmgr/lock.c | 23 | 12 |
| src/include/storage/lock.h | 5 | 0 |
From d86f33a09b556c179e34362b87154ea13a7efd4b Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sat, 19 Dec 2020 21:53:00 +0500
Subject: [PATCH v2 1/2] Wait for prepared xacts in CREATE INDEX CONCURRENTLY
locks infrastructure
---
src/backend/storage/lmgr/lmgr.c | 5 ++---
src/backend/storage/lmgr/lock.c | 35 ++++++++++++++++++++++-----------
src/include/storage/lock.h | 5 +++++
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 7409de9405..c1e8e76f41 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -904,8 +904,7 @@ WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
/*
* Note: GetLockConflicts() never reports our own xid, hence we need not
- * check for that. Also, prepared xacts are not reported, which is fine
- * since they certainly aren't going to do anything anymore.
+ * check for that. Also, prepared xacts are reported and awaited.
*/
/* Finally wait for each such transaction to complete */
@@ -913,7 +912,7 @@ WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
{
VirtualTransactionId *lockholders = lfirst(lc);
- while (VirtualTransactionIdIsValid(*lockholders))
+ while (VirtualTransactionIdIsValidOrPreparedXact(*lockholders))
{
/* If requested, publish who we're going to wait for. */
if (progress)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index d86566f455..c8cecd6f7a 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -2904,9 +2904,7 @@ FastPathGetRelationLockEntry(LOCALLOCK *locallock)
* so use of this function has to be thought about carefully.
*
* Note we never include the current xact's vxid in the result array,
- * since an xact never blocks itself. Also, prepared transactions are
- * ignored, which is a bit more debatable but is appropriate for current
- * uses of the result.
+ * since an xact never blocks itself.
*/
VirtualTransactionId *
GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
@@ -2931,15 +2929,17 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
/*
* Allocate memory to store results, and fill with InvalidVXID. We only
- * need enough space for MaxBackends + a terminator, since prepared xacts
- * don't count. InHotStandby allocate once in TopMemoryContext.
+ * need enough space for MaxBackends + max_prepared_xacts + a
+ * terminator. InHotStandby allocate once in TopMemoryContext.
*/
if (InHotStandby)
{
if (vxids == NULL)
vxids = (VirtualTransactionId *)
MemoryContextAlloc(TopMemoryContext,
- sizeof(VirtualTransactionId) * (MaxBackends + 1));
+ sizeof(VirtualTransactionId) * (MaxBackends
+ + max_prepared_xacts
+ + 1));
}
else
vxids = (VirtualTransactionId *)
@@ -3085,10 +3085,10 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
/*
* If we see an invalid VXID, then either the xact has already
- * committed (or aborted), or it's a prepared xact. In either
- * case we may ignore it.
+ * committed (or aborted), or it's a prepared xact. We take
+ * prepared xacts into account too.
*/
- if (VirtualTransactionIdIsValid(vxid))
+ if (VirtualTransactionIdIsValidOrPreparedXact(vxid))
{
int i;
@@ -3108,7 +3108,7 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
LWLockRelease(partitionLock);
- if (count > MaxBackends) /* should never happen */
+ if (count > MaxBackends + max_prepared_xacts) /* should never happen */
elog(PANIC, "too many conflicting locks found");
vxids[count].backendId = InvalidBackendId;
@@ -4461,9 +4461,20 @@ bool
VirtualXactLock(VirtualTransactionId vxid, bool wait)
{
LOCKTAG tag;
- PGPROC *proc;
+ PGPROC *proc = NULL;
- Assert(VirtualTransactionIdIsValid(vxid));
+ Assert(VirtualTransactionIdIsValidOrPreparedXact(vxid));
+
+ if (VirtualTransactionIdIsPreparedXact(vxid))
+ {
+ LockAcquireResult lar;
+ /* If it's prepared xact - just wait for it */
+ SET_LOCKTAG_TRANSACTION(tag, vxid.localTransactionId);
+ lar = LockAcquire(&tag, ShareLock, false, !wait);
+ if (lar == LOCKACQUIRE_OK)
+ LockRelease(&tag, ShareLock, false);
+ return lar != LOCKACQUIRE_NOT_AVAIL;
+ }
SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 1c3e9c1999..dbd2a32678 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -70,6 +70,11 @@ typedef struct
#define VirtualTransactionIdIsValid(vxid) \
(((vxid).backendId != InvalidBackendId) && \
LocalTransactionIdIsValid((vxid).localTransactionId))
+#define VirtualTransactionIdIsValidOrPreparedXact(vxid) \
+ (((vxid).backendId == InvalidBackendId) || \
+ LocalTransactionIdIsValid((vxid).localTransactionId))
+#define VirtualTransactionIdIsPreparedXact(vxid) \
+ ((vxid).backendId == InvalidBackendId)
#define VirtualTransactionIdEquals(vxid1, vxid2) \
((vxid1).backendId == (vxid2).backendId && \
(vxid1).localTransactionId == (vxid2).localTransactionId)
--
2.24.3 (Apple Git-128)