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

Commit73981cb

Browse files
committed
Fix a problem introduced by my patch of 2010-01-12 that revised the way
relcache reload works. In the patched code, a relcache entry in process ofbeing rebuilt doesn't get unhooked from the relcache hash table; which meansthat if a cache flush occurs due to sinval queue overrun while we'rerebuilding it, the entry could get blown away by RelationCacheInvalidate,resulting in crash or misbehavior. Fix by ensuring that an entry beingrebuilt has positive refcount, so it won't be seen as a target for removalif a cache flush occurs. (This will mean that the entry gets rebuilt twicein such a scenario, but that's okay.) It appears that the problem can onlyarise within a transaction that has previously reassigned the relfilenode ofa pre-existing table, via TRUNCATE or a similar operation. Per bug #5412from Rusty Conover.Back-patch to 8.2, same as the patch that introduced the problem.I think that the failure can't actually occur in 8.2, since it lacks therd_newRelfilenodeSubid optimization, but let's make it work like the laterbranches anyway.Patch by Heikki, slightly editorialized on by me.
1 parent9d137a7 commit73981cb

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

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

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.308 2010/02/26 02:01:11momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.309 2010/04/14 21:31:11tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1823,18 +1823,33 @@ RelationDestroyRelation(Relation relation)
18231823
*
18241824
* Physically blow away a relation cache entry, or reset it and rebuild
18251825
* it from scratch (that is, from catalog entries). The latter path is
1826-
* usually used when we are notified of a change to an open relation
1827-
* (one with refcount > 0). However, this routine just does whichever
1828-
* it's told to do; callers must determine which they want.
1826+
* used when we are notified of a change to an open relation (one with
1827+
* refcount > 0).
18291828
*
1830-
* NB: when rebuilding, we'd better hold some lock on the relation.
1831-
* In current usages this is presumed true because it has refcnt > 0.
1829+
* NB: when rebuilding, we'd better hold some lock on the relation,
1830+
* else the catalog data we need to read could be changing under us.
1831+
* Also, a rel to be rebuilt had better have refcnt > 0. This is because
1832+
* an sinval reset could happen while we're accessing the catalogs, and
1833+
* the rel would get blown away underneath us by RelationCacheInvalidate
1834+
* if it has zero refcnt.
1835+
*
1836+
* The "rebuild" parameter is redundant in current usage because it has
1837+
* to match the relation's refcnt status, but we keep it as a crosscheck
1838+
* that we're doing what the caller expects.
18321839
*/
18331840
staticvoid
18341841
RelationClearRelation(Relationrelation,boolrebuild)
18351842
{
18361843
Oidold_reltype=relation->rd_rel->reltype;
18371844

1845+
/*
1846+
* As per notes above, a rel to be rebuilt MUST have refcnt > 0; while
1847+
* of course it would be a bad idea to blow away one with nonzero refcnt.
1848+
*/
1849+
Assert(rebuild ?
1850+
!RelationHasReferenceCountZero(relation) :
1851+
RelationHasReferenceCountZero(relation));
1852+
18381853
/*
18391854
* Make sure smgr and lower levels close the relation's files, if they
18401855
* weren't closed already. If the relation is not getting deleted, the
@@ -2024,27 +2039,31 @@ RelationClearRelation(Relation relation, bool rebuild)
20242039
staticvoid
20252040
RelationFlushRelation(Relationrelation)
20262041
{
2027-
boolrebuild;
2028-
20292042
if (relation->rd_createSubid!=InvalidSubTransactionId||
20302043
relation->rd_newRelfilenodeSubid!=InvalidSubTransactionId)
20312044
{
20322045
/*
20332046
* New relcache entries are always rebuilt, not flushed; else we'd
20342047
* forget the "new" status of the relation, which is a useful
20352048
* optimization to have. Ditto for the new-relfilenode status.
2049+
*
2050+
* The rel could have zero refcnt here, so temporarily increment
2051+
* the refcnt to ensure it's safe to rebuild it. We can assume that
2052+
* the current transaction has some lock on the rel already.
20362053
*/
2037-
rebuild= true;
2054+
RelationIncrementReferenceCount(relation);
2055+
RelationClearRelation(relation, true);
2056+
RelationDecrementReferenceCount(relation);
20382057
}
20392058
else
20402059
{
20412060
/*
20422061
* Pre-existing rels can be dropped from the relcache if not open.
20432062
*/
2044-
rebuild= !RelationHasReferenceCountZero(relation);
2045-
}
2063+
boolrebuild= !RelationHasReferenceCountZero(relation);
20462064

2047-
RelationClearRelation(relation,rebuild);
2065+
RelationClearRelation(relation,rebuild);
2066+
}
20482067
}
20492068

20502069
/*
@@ -2373,7 +2392,6 @@ AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,
23732392
relation->rd_createSubid=parentSubid;
23742393
else
23752394
{
2376-
Assert(RelationHasReferenceCountZero(relation));
23772395
RelationClearRelation(relation, false);
23782396
continue;
23792397
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp