On 2013-10-23 03:18:55 +0200, Andres Freund wrote:
> (000[1-4])

Attached.

Greetings,

Andres Freund

-- 
 Andres Freund                     http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
>From bf329af4eb6d839ae2a75c4f8a2d6867877510f4 Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Wed, 23 Oct 2013 02:34:51 +0200
Subject: [PATCH 1/4] debug-lock-on-index-without-heap-lock

---
 src/backend/access/heap/heapam.c   | 10 ++++++++++
 src/backend/access/index/indexam.c | 14 ++++++++++++++
 src/backend/storage/lmgr/lmgr.c    |  9 +++++++++
 src/backend/storage/lmgr/lock.c    | 16 ++++++++++++++++
 src/backend/utils/cache/relcache.c | 10 ++++++++++
 src/include/storage/lmgr.h         |  2 ++
 src/include/storage/lock.h         |  2 ++
 7 files changed, 63 insertions(+)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a21f31b..3eecd5f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1203,6 +1203,16 @@ heap_open(Oid relationId, LOCKMODE lockmode)
 				 errmsg("\"%s\" is a composite type",
 						RelationGetRelationName(r))));
 
+	if (IsNormalProcessingMode() && lockmode == NoLock)
+	{
+		LOCKMODE	mode;
+
+		mode = StrongestLocalRelationLock(relationId);
+		if (mode == NoLock)
+			elog(WARNING, "no relation lock on rel %s",
+				 RelationGetRelationName(r));
+	}
+
 	return r;
 }
 
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index b878155..10c3991 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -65,6 +65,8 @@
 
 #include "postgres.h"
 
+#include "miscadmin.h"
+
 #include "access/relscan.h"
 #include "access/transam.h"
 #include "catalog/index.h"
@@ -142,6 +144,8 @@ static IndexScanDesc index_beginscan_internal(Relation indexRelation,
  * ----------------------------------------------------------------
  */
 
+#include "catalog/catalog.h"
+
 /* ----------------
  *		index_open - open an index relation by relation OID
  *
@@ -169,6 +173,16 @@ index_open(Oid relationId, LOCKMODE lockmode)
 				 errmsg("\"%s\" is not an index",
 						RelationGetRelationName(r))));
 
+	if (IsNormalProcessingMode())
+	{
+		LOCKMODE	mode;
+
+		mode = StrongestLocalRelationLock(r->rd_index->indrelid);
+		if (mode == NoLock)
+			elog(WARNING, "no relation lock on rel %u held while opening index %s",
+				 r->rd_index->indrelid,
+				 RelationGetRelationName(r));
+	}
 	return r;
 }
 
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index a978172..32d7bba 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -232,6 +232,15 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
 	LockRelease(&tag, lockmode, false);
 }
 
+LOCKMODE
+StrongestLocalRelationLock(Oid relid)
+{
+	LOCKTAG		tag;
+	SetLocktagRelationOid(&tag, relid);
+	return StrongestLocalLock(&tag);
+}
+
+
 /*
  *		LockHasWaitersRelation
  *
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index f4f32e9..2f068be 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -2365,6 +2365,22 @@ LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
 	ResourceOwnerForgetLock(CurrentResourceOwner, locallock);
 }
 
+LOCKMODE
+StrongestLocalLock(const LOCKTAG* locktag)
+{
+	HASH_SEQ_STATUS status;
+	LOCALLOCK  *locallock;
+	LOCKMODE	strongest = NoLock;
+	hash_seq_init(&status, LockMethodLocalHash);
+
+	while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
+	{
+		if (memcmp(&locallock->tag.lock, locktag, sizeof(LOCKTAG)) == 0)
+			strongest = Max(strongest, locallock->tag.mode);
+	}
+	return strongest;
+}
+
 /*
  * FastPathGrantRelationLock
  *		Grant lock using per-backend fast-path array, if there is space.
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index b4cc6ad..f74c6af 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1577,6 +1577,16 @@ RelationIdGetRelation(Oid relationId)
 {
 	Relation	rd;
 
+	if (IsNormalProcessingMode())
+	{
+		LOCKMODE	mode;
+
+		mode = StrongestLocalRelationLock(relationId);
+		if (mode == NoLock)
+			elog(WARNING, "no relation lock for descriptor of oid %u",
+				 relationId);
+	}
+
 	/*
 	 * first try to find reldesc in the cache
 	 */
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 1a8c018..c2c6026 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -40,6 +40,8 @@ extern void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
 extern void LockRelationForExtension(Relation relation, LOCKMODE lockmode);
 extern void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode);
 
+extern LOCKMODE StrongestLocalRelationLock(Oid relid);
+
 /* Lock a page (currently only used within indexes) */
 extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
 extern bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 7bcaf7c..ea915c8 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -495,6 +495,8 @@ extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
 extern void LockReleaseSession(LOCKMETHODID lockmethodid);
 extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
 extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
+extern LOCKMODE StrongestLocalLock(const LOCKTAG* locktag);
+
 extern bool LockHasWaiters(const LOCKTAG *locktag,
 			   LOCKMODE lockmode, bool sessionLock);
 extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
-- 
1.8.3.251.g1462b67

>From 61ad53f8e1d48264fab3a90f4104ffc308bd1f73 Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Wed, 23 Oct 2013 01:25:49 +0200
Subject: [PATCH 2/4] Acquire appropriate locks when rewriting during REFRESH
 MATERIALIZED VIEW

---
 src/backend/commands/matview.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index fcfc678..1c02eab 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -283,6 +283,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
 	Oid			save_userid;
 	int			save_sec_context;
 	int			save_nestlevel;
+	Query	   *copied_query;
 
 	/*
 	 * Switch to the owner's userid, so that any functions are run as that
@@ -294,8 +295,14 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
 						   save_sec_context | SECURITY_RESTRICTED_OPERATION);
 	save_nestlevel = NewGUCNestLevel();
 
-	/* Rewrite, copying the given Query to make sure it's not changed */
-	rewritten = QueryRewrite((Query *) copyObject(query));
+	/* copy the given Query to make sure it's not changed */
+	copied_query = copyObject(query);
+
+	/* acquire locks for rewriting */
+	AcquireRewriteLocks(copied_query, false);
+
+	/* Rewrite */
+	rewritten = QueryRewrite(copied_query);
 
 	/* SELECT should never rewrite to more or less than one SELECT query */
 	if (list_length(rewritten) != 1)
-- 
1.8.3.251.g1462b67

>From e49502bca39c70ebadc7cbe2fdacf68c33be627b Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Wed, 23 Oct 2013 02:35:05 +0200
Subject: [PATCH 3/4] hack INSERT INTO some_view; to lock rels in the
 underlying view

This is not an acceptable patch!
---
 src/backend/parser/parse_relation.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 5f46913..731ac7d 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -27,6 +27,7 @@
 #include "parser/parsetree.h"
 #include "parser/parse_relation.h"
 #include "parser/parse_type.h"
+#include "rewrite/rewriteHandler.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
@@ -1009,6 +1010,23 @@ parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode)
 								relation->relname)));
 		}
 	}
+	if (rel->rd_rel->relkind == RELKIND_VIEW)
+	{
+		int i;
+		for (i = 0; i < rel->rd_rules->numLocks; i++)
+		{
+			Query *v;
+			RewriteRule *r;
+			ListCell   *c;
+
+			r = rel->rd_rules->rules[i];
+			foreach(c, r->actions)
+			{
+				v = (Query *) lfirst(c);
+				AcquireRewriteLocks(copyObject(v), false);
+			}
+		}
+	}
 	cancel_parser_errposition_callback(&pcbstate);
 	return rel;
 }
-- 
1.8.3.251.g1462b67

>From b77ea7e33e0b2d9ae02559a52ac9f0326eac69fe Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Wed, 23 Oct 2013 03:08:45 +0200
Subject: [PATCH 4/4] matview: lock temp table till tx end during refresh for
 easier debugging

---
 src/backend/commands/matview.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 1c02eab..8e8981a 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -243,6 +243,10 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
 	/* Create the transient table that will receive the regenerated data. */
 	OIDNewHeap = make_new_heap(matviewOid, tableSpace, concurrent,
 							   ExclusiveLock);
+
+	/* lock temporary table till end of transaction */
+	heap_close(heap_open(OIDNewHeap, lockmode), NoLock);
+
 	dest = CreateTransientRelDestReceiver(OIDNewHeap);
 
 	/* Generate the data, if wanted. */
-- 
1.8.3.251.g1462b67

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to