identify_xact_waits.v1.patch

application/octet-stream

Filename: identify_xact_waits.v1.patch
Type: application/octet-stream
Part: 0
Message: log_lock_waits to identify transaction's relation

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 */