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