Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita1dfaef

Browse files
committed
Modify index-opening code to guarantee that the indexes of a relation
are opened in a consistent order by different backends (I ordered themby index OID because that's easy, but any other consistent order woulddo as well). This avoids potential deadlock for index types that weacquire exclusive locks on ... ie, rtree.
1 parent1f75cdd commita1dfaef

File tree

2 files changed

+71
-16
lines changed

2 files changed

+71
-16
lines changed

‎src/backend/executor/execUtils.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.60 2000/06/17 21:48:49 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.61 2000/06/19 23:40:47 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -799,15 +799,20 @@ ExecOpenIndices(RelationInfo *resultRelationInfo)
799799
/* ----------------
800800
* Open (and lock, if necessary) the index relation
801801
*
802-
* Hack for not btree and hash indices: they use relation
803-
* level exclusive locking on update (i.e. - they are not
804-
* ready for MVCC) and so we have to exclusively lock
805-
* indices here to prevent deadlocks if we will scan them
806-
* - index_beginscan places AccessShareLock, indices
807-
* update methods don't use locks at all. We release this
808-
* lock in ExecCloseIndices. Note, that hashes use page
809-
* level locking - i.e. are not deadlock-free, - let's
810-
* them be on their way -:)) vadim 03-12-1998
802+
* Hack for not btree and hash indices: they use relation level
803+
* exclusive locking on update (i.e. - they are not ready for MVCC)
804+
* and so we have to exclusively lock indices here to prevent
805+
* deadlocks if we will scan them - index_beginscan places
806+
* AccessShareLock, indices update methods don't use locks at all.
807+
* We release this lock in ExecCloseIndices. Note, that hashes use
808+
* page level locking - i.e. are not deadlock-free - let's them be
809+
* on their way -:)) vadim 03-12-1998
810+
*
811+
* If there are multiple not-btree-or-hash indices, all backends must
812+
* lock the indices in the same order or we will get deadlocks here
813+
* during concurrent updates. This is now guaranteed by
814+
* RelationGetIndexList(), which promises to return the index list
815+
* in OID order. tgl 06-19-2000
811816
* ----------------
812817
*/
813818
indexDesc=index_open(indexOid);

‎src/backend/utils/cache/relcache.c

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.102 2000/06/18 22:44:17 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.103 2000/06/19 23:40:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -230,6 +230,7 @@ static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo,
230230
staticvoidIndexedAccessMethodInitialize(Relationrelation);
231231
staticvoidAttrDefaultFetch(Relationrelation);
232232
staticvoidRelCheckFetch(Relationrelation);
233+
staticList*insert_ordered_oid(List*list,Oiddatum);
233234

234235
staticboolcriticalRelcacheBuild= false;
235236

@@ -2078,6 +2079,12 @@ RelCheckFetch(Relation relation)
20782079
* so that we must recompute the index list on next request. This handles
20792080
* creation or deletion of an index.
20802081
*
2082+
* The returned list is guaranteed to be sorted in order by OID. This is
2083+
* needed by the executor, since for index types that we obtain exclusive
2084+
* locks on when updating the index, all backends must lock the indexes in
2085+
* the same order or we will get deadlocks (see ExecOpenIndices()). Any
2086+
* consistent ordering would do, but ordering by OID is easy.
2087+
*
20812088
* Since shared cache inval causes the relcache's copy of the list to go away,
20822089
* we return a copy of the list palloc'd in the caller's context. The caller
20832090
* may freeList() the returned list after scanning it. This is necessary
@@ -2163,7 +2170,7 @@ RelationGetIndexList(Relation relation)
21632170

21642171
index= (Form_pg_index)GETSTRUCT(htup);
21652172

2166-
result=lappendi(result,index->indexrelid);
2173+
result=insert_ordered_oid(result,index->indexrelid);
21672174

21682175
if (hasindex)
21692176
ReleaseBuffer(buffer);
@@ -2178,7 +2185,7 @@ RelationGetIndexList(Relation relation)
21782185
heap_endscan(hscan);
21792186
heap_close(indrel,AccessShareLock);
21802187

2181-
/* Nowwe can save the completed list in the relcache entry. */
2188+
/* Nowsave a copy of the completed list in the relcache entry. */
21822189
oldcxt=MemoryContextSwitchTo((MemoryContext)CacheCxt);
21832190
relation->rd_indexlist=listCopy(result);
21842191
relation->rd_indexfound= true;
@@ -2187,6 +2194,39 @@ RelationGetIndexList(Relation relation)
21872194
returnresult;
21882195
}
21892196

2197+
/*
2198+
* insert_ordered_oid
2199+
*Insert a new Oid into a sorted list of Oids, preserving ordering
2200+
*
2201+
* Building the ordered list this way is O(N^2), but with a pretty small
2202+
* constant, so for the number of entries we expect it will probably be
2203+
* faster than trying to apply qsort(). Most tables don't have very many
2204+
* indexes...
2205+
*/
2206+
staticList*
2207+
insert_ordered_oid(List*list,Oiddatum)
2208+
{
2209+
List*l;
2210+
2211+
/* Does the datum belong at the front? */
2212+
if (list==NIL||datum< (Oid)lfirsti(list))
2213+
returnlconsi(datum,list);
2214+
/* No, so find the entry it belongs after */
2215+
l=list;
2216+
for (;;)
2217+
{
2218+
List*n=lnext(l);
2219+
2220+
if (n==NIL||datum< (Oid)lfirsti(n))
2221+
break;/* it belongs before n */
2222+
l=n;
2223+
}
2224+
/* Insert datum into list after item l */
2225+
lnext(l)=lconsi(datum,lnext(l));
2226+
returnlist;
2227+
}
2228+
2229+
21902230
/*
21912231
*init_irels(), write_irels() -- handle special-case initialization of
21922232
* index relation descriptors.
@@ -2412,7 +2452,14 @@ write_irels(void)
24122452

24132453
fd=PathNameOpenFile(tempfilename,O_WRONLY |O_CREAT |O_TRUNC |PG_BINARY,0600);
24142454
if (fd<0)
2415-
elog(FATAL,"cannot create init file %s",tempfilename);
2455+
{
2456+
/*
2457+
* We used to consider this a fatal error, but we might as well
2458+
* continue with backend startup ...
2459+
*/
2460+
elog(NOTICE,"Cannot create init file %s: %m\n\tContinuing anyway, but there's something wrong.",tempfilename);
2461+
return;
2462+
}
24162463

24172464
FileSeek(fd,0L,SEEK_SET);
24182465

@@ -2540,7 +2587,10 @@ write_irels(void)
25402587

25412588
/*
25422589
* And rename the temp file to its final name, deleting any
2543-
* previously-existing init file.
2590+
* previously-existing init file.
25442591
*/
2545-
rename(tempfilename,finalfilename);
2592+
if (rename(tempfilename,finalfilename)<0)
2593+
{
2594+
elog(NOTICE,"Cannot rename init file %s to %s: %m\n\tContinuing anyway, but there's something wrong.",tempfilename,finalfilename);
2595+
}
25462596
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp