identify_xact_waits.v1.patch
application/octet-stream
Filename: identify_xact_waits.v1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/access/heap/heapam.c | 8 | 8 |
| src/backend/access/nbtree/nbtinsert.c | 1 | 1 |
| src/backend/access/transam/multixact.c | 4 | 4 |
| src/backend/catalog/index.c | 2 | 2 |
| src/backend/executor/execMain.c | 1 | 1 |
| src/backend/executor/execUtils.c | 1 | 1 |
| src/backend/storage/lmgr/deadlock.c | 1 | 1 |
| src/backend/storage/lmgr/lmgr.c | 35 | 4 |
| src/backend/storage/lmgr/proc.c | 2 | 2 |
| src/include/access/multixact.h | 2 | 2 |
| src/include/storage/lmgr.h | 4 | 3 |
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b19d1cf..261c5be 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2494,7 +2494,7 @@ l1:
if (infomask & HEAP_XMAX_IS_MULTI)
{
/* wait for multixact */
- MultiXactIdWait((MultiXactId) xwait);
+ MultiXactIdWait((MultiXactId) xwait, relation->rd_id);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
@@ -2520,7 +2520,7 @@ l1:
else
{
/* wait for regular transaction to end */
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, relation->rd_id);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
@@ -2871,7 +2871,7 @@ l2:
if (infomask & HEAP_XMAX_IS_MULTI)
{
/* wait for multixact */
- MultiXactIdWait((MultiXactId) xwait);
+ MultiXactIdWait((MultiXactId) xwait, relation->rd_id);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
@@ -2897,7 +2897,7 @@ l2:
else
{
/* wait for regular transaction to end */
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, relation->rd_id);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
@@ -3612,14 +3612,14 @@ l3:
/* wait for multixact to end */
if (nowait)
{
- if (!ConditionalMultiXactIdWait((MultiXactId) xwait))
+ if (!ConditionalMultiXactIdWait((MultiXactId) xwait, relation->rd_id))
ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("could not obtain lock on row in relation \"%s\"",
RelationGetRelationName(relation))));
}
else
- MultiXactIdWait((MultiXactId) xwait);
+ MultiXactIdWait((MultiXactId) xwait, relation->rd_id);
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
@@ -3647,14 +3647,14 @@ l3:
/* wait for regular transaction to end */
if (nowait)
{
- if (!ConditionalXactLockTableWait(xwait))
+ if (!ConditionalXactLockTableWait(xwait, relation->rd_id))
ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("could not obtain lock on row in relation \"%s\"",
RelationGetRelationName(relation))));
}
else
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, relation->rd_id);
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 4432bb1..d48ffb2 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -165,7 +165,7 @@ top:
{
/* Have to wait for the other guy ... */
_bt_relbuf(rel, buf);
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, heapRel->rd_id);
/* start over... */
_bt_freestack(stack);
goto top;
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 1ae6717..cd6db82 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -583,7 +583,7 @@ MultiXactIdSetOldestVisible(void)
* of the containing tuple, so the caller needs to iterate on us somehow.
*/
void
-MultiXactIdWait(MultiXactId multi)
+MultiXactIdWait(MultiXactId multi, Oid relid)
{
TransactionId *members;
int nmembers;
@@ -601,7 +601,7 @@ MultiXactIdWait(MultiXactId multi)
debug_elog4(DEBUG2, "MultiXactIdWait: waiting for %d (%u)",
i, member);
if (!TransactionIdIsCurrentTransactionId(member))
- XactLockTableWait(member);
+ XactLockTableWait(member, relid);
}
pfree(members);
@@ -613,7 +613,7 @@ MultiXactIdWait(MultiXactId multi)
* As above, but only lock if we can get the lock without blocking.
*/
bool
-ConditionalMultiXactIdWait(MultiXactId multi)
+ConditionalMultiXactIdWait(MultiXactId multi, Oid relid)
{
bool result = true;
TransactionId *members;
@@ -633,7 +633,7 @@ ConditionalMultiXactIdWait(MultiXactId multi)
i, member);
if (!TransactionIdIsCurrentTransactionId(member))
{
- result = ConditionalXactLockTableWait(member);
+ result = ConditionalXactLockTableWait(member, relid);
if (!result)
break;
}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5892e44..73e2dfa 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2335,7 +2335,7 @@ IndexBuildHeapScan(Relation heapRelation,
* Must drop the lock on the buffer before we wait
*/
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, heapRelation->rd_id);
goto recheck;
}
}
@@ -2382,7 +2382,7 @@ IndexBuildHeapScan(Relation heapRelation,
* Must drop the lock on the buffer before we wait
*/
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, heapRelation->rd_id);
goto recheck;
}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 9d5d829..88bb8f0 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1836,7 +1836,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
if (TransactionIdIsValid(SnapshotDirty.xmax))
{
ReleaseBuffer(buffer);
- XactLockTableWait(SnapshotDirty.xmax);
+ XactLockTableWait(SnapshotDirty.xmax, relation->rd_id);
continue; /* loop back to repeat heap_fetch */
}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 9206195..f48a24c 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1291,7 +1291,7 @@ retry:
if (TransactionIdIsValid(xwait))
{
index_endscan(index_scan);
- XactLockTableWait(xwait);
+ XactLockTableWait(xwait, heap->rd_id);
goto retry;
}
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index a0f7d34..67fb75e 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -916,7 +916,7 @@ DeadLockReport(void)
/* reset locktagbuf to hold next object description */
resetStringInfo(&locktagbuf);
- DescribeLockTag(&locktagbuf, &info->locktag);
+ DescribeLockTag(&locktagbuf, &info->locktag, false);
if (i > 0)
appendStringInfoChar(&clientbuf, '\n');
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 2b7a1db..20e935b 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -24,6 +24,7 @@
#include "storage/procarray.h"
#include "utils/inval.h"
+static Oid XactLockTableRelid = InvalidOid; /* Relid of table we are waiting for */
/*
* RelationInitLockInfo
@@ -481,10 +482,12 @@ XactLockTableDelete(TransactionId xid)
* and if so wait for its parent.
*/
void
-XactLockTableWait(TransactionId xid)
+XactLockTableWait(TransactionId xid, Oid WaitRelid)
{
LOCKTAG tag;
+ XactLockTableRelid = WaitRelid;
+
for (;;)
{
Assert(TransactionIdIsValid(xid));
@@ -500,6 +503,8 @@ XactLockTableWait(TransactionId xid)
break;
xid = SubTransGetParent(xid);
}
+
+ XactLockTableRelid = InvalidOid;
}
/*
@@ -509,10 +514,11 @@ XactLockTableWait(TransactionId xid)
* Returns TRUE if the lock was acquired.
*/
bool
-ConditionalXactLockTableWait(TransactionId xid)
+ConditionalXactLockTableWait(TransactionId xid, Oid WaitRelid)
{
LOCKTAG tag;
+ XactLockTableRelid = WaitRelid;
for (;;)
{
Assert(TransactionIdIsValid(xid));
@@ -521,7 +527,10 @@ ConditionalXactLockTableWait(TransactionId xid)
SET_LOCKTAG_TRANSACTION(tag, xid);
if (LockAcquire(&tag, ShareLock, false, true) == LOCKACQUIRE_NOT_AVAIL)
+ {
+ XactLockTableRelid = InvalidOid;
return false;
+ }
LockRelease(&tag, ShareLock, false);
@@ -530,10 +539,21 @@ ConditionalXactLockTableWait(TransactionId xid)
xid = SubTransGetParent(xid);
}
+ XactLockTableRelid = InvalidOid;
return true;
}
/*
+ * Return the relid of the table we are currently waiting on, to
+ * allow full reporting of lock waits.
+ */
+Oid
+GetXactLockTableRelid(void)
+{
+ return XactLockTableRelid;
+}
+
+/*
* LockDatabaseObject
*
* Obtain a lock on a general object of the current database. Don't use
@@ -664,9 +684,13 @@ UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
* Ideally we would print names for the numeric values, but that requires
* getting locks on system tables, which might cause problems since this is
* typically used to report deadlock situations.
+ *
+ * describeXact can be used by a backend that is describing a lock of type
+ * LOCKTAG_TRANSACTION that the backend is requesting. This information
+ * isn't available for locks requested or held by other backends.
*/
void
-DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
+DescribeLockTag(StringInfo buf, const LOCKTAG *tag, bool describeXact)
{
switch ((LockTagType) tag->locktag_type)
{
@@ -698,7 +722,14 @@ DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
tag->locktag_field1);
break;
case LOCKTAG_TRANSACTION:
- appendStringInfo(buf,
+ if (describeXact && OidIsValid(GetXactLockTableRelid()))
+ appendStringInfo(buf,
+ _("transaction %u on relation %u of database %u"),
+ tag->locktag_field1,
+ GetXactLockTableRelid(),
+ MyDatabaseId);
+ else
+ appendStringInfo(buf,
_("transaction %u"),
tag->locktag_field1);
break;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 2e012fa..5ec0eed 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1128,7 +1128,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
initStringInfo(&locktagbuf);
initStringInfo(&logbuf);
- DescribeLockTag(&locktagbuf, &lock->tag);
+ DescribeLockTag(&locktagbuf, &lock->tag, false);
appendStringInfo(&logbuf,
_("Process %d waits for %s on %s."),
MyProcPid,
@@ -1176,7 +1176,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
long msecs;
initStringInfo(&buf);
- DescribeLockTag(&buf, &locallock->tag.lock);
+ DescribeLockTag(&buf, &locallock->tag.lock, true);
modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
lockmode);
TimestampDifference(get_timeout_start_time(DEADLOCK_TIMEOUT),
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
index b5486be..6cca9fa 100644
--- a/src/include/access/multixact.h
+++ b/src/include/access/multixact.h
@@ -46,8 +46,8 @@ extern MultiXactId MultiXactIdCreate(TransactionId xid1, TransactionId xid2);
extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid);
extern bool MultiXactIdIsRunning(MultiXactId multi);
extern bool MultiXactIdIsCurrent(MultiXactId multi);
-extern void MultiXactIdWait(MultiXactId multi);
-extern bool ConditionalMultiXactIdWait(MultiXactId multi);
+extern void MultiXactIdWait(MultiXactId multi, Oid relid);
+extern bool ConditionalMultiXactIdWait(MultiXactId multi, Oid relid);
extern void MultiXactIdSetOldestMember(void);
extern int GetMultiXactIdMembers(MultiXactId multi, TransactionId **xids);
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 9b1fb93..5aee9f5 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -54,8 +54,9 @@ extern void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
/* Lock an XID (used to wait for a transaction to finish) */
extern void XactLockTableInsert(TransactionId xid);
extern void XactLockTableDelete(TransactionId xid);
-extern void XactLockTableWait(TransactionId xid);
-extern bool ConditionalXactLockTableWait(TransactionId xid);
+extern void XactLockTableWait(TransactionId xid, Oid WaitRelid);
+extern bool ConditionalXactLockTableWait(TransactionId xid, Oid WaitRelid);
+extern Oid GetXactLockTableRelid(void);
/* Lock a general object (other than a relation) of the current database */
extern void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
@@ -75,6 +76,6 @@ extern void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid
LOCKMODE lockmode);
/* Describe a locktag for error messages */
-extern void DescribeLockTag(StringInfo buf, const LOCKTAG *tag);
+extern void DescribeLockTag(StringInfo buf, const LOCKTAG *tag, bool describeXact);
#endif /* LMGR_H */