PG高速缓冲区(Cache)——系统表元组缓冲区SysCache访问

  在CatCache中查找元组有两种方式:精确匹配SearchCatCache和部分匹配SearchCatcacheList。前者用于给定CatCache所需的所有键值,并返回CatCache中能完全匹配这个键值的元组;而后者只需要给出部分键值,并将部分匹配的元组以一个CatCList的方式返回。

  SysCache提供了SearchSysCache、SearchSysCacheList、ReleaseSysCache、SearchSysCacheCopy、SearchSysCacheExists、GetSysCacheOid、SearchSysCacheAttName、SearchSysCacheCopyAttName、SearchSysCacheExistsAttName,主要就是调用catcache.c提供的查找元组的函数,以及释放计数函数。

SearchSysCache是SearchCatCache的一层封装,为调用者执行初始化和进行查找键设置。如果找到元组,则返回该元组的缓存副本;如果未找到,则返回NULL。元组是“cache”副本,不能修改。调用方使用完元组后,调用ReleaseSysCache()释放SearchSysCache()获取的引用计数。如果不这样做,元组将一直锁定在缓存中,直到事务结束,这是可以容忍的,但不可取的。注意:调用方不能释放返回的元组!

1 HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4) {
2     if (cacheId < 0 || cacheId >= SysCacheSize ||
3         !PointerIsValid(SysCache[cacheId]))
4         elog(ERROR, "invalid cache id: %d", cacheId);
5     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
6 }

SearchSysCacheList同理

1 struct catclist *SearchSysCacheList(int cacheId, int nkeys,
2                    Datum key1, Datum key2, Datum key3, Datum key4){
3     if (cacheId < 0 || cacheId >= SysCacheSize ||
4         !PointerIsValid(SysCache[cacheId]))
5         elog(ERROR, "invalid cache id: %d", cacheId);
6 
7     return SearchCatCacheList(SysCache[cacheId], nkeys,
8                               key1, key2, key3, key4);
9 }

 

ReleaseSysCache是RelesaseCatCache的房子,用于释放tuple的引用计数

1 void ReleaseSysCache(HeapTuple tuple) {
2     ReleaseCatCache(tuple);
3 }

SearchSysCacheCopy调用SearchSysCache并返回syscache条目的一份拷贝,并释放原条目

1 HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4) {
2     HeapTuple    tuple, newtuple;
3     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
4     if (!HeapTupleIsValid(tuple))
5         return tuple;
6     newtuple = heap_copytuple(tuple);
7     ReleaseSysCache(tuple);
8     return newtuple;
9 }

SearchSysCacheExists查看某个tuple释放存在

1 bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4) {
2     HeapTuple    tuple;
3     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
4     if (!HeapTupleIsValid(tuple))
5         return false;
6     ReleaseSysCache(tuple);
7     return true;
8 }

GetSysCacheOid调用SearchSysCache,返回获取到的tuple的OID

 1 Oid GetSysCacheOid(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4){
 2     HeapTuple    tuple;
 3     Oid            result;
 4     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
 5     if (!HeapTupleIsValid(tuple))
 6         return InvalidOid;
 7     result = HeapTupleGetOid(tuple);
 8     ReleaseSysCache(tuple);
 9     return result;
10 }

SearchSysCacheAttName调用SearchSysCache查找ATTNAME,返回获取到的tuple

 1 HeapTuple SearchSysCacheAttName(Oid relid, const char *attname){
 2     HeapTuple    tuple;
 3     tuple = SearchSysCache(ATTNAME,
 4                            ObjectIdGetDatum(relid),
 5                            CStringGetDatum(attname),
 6                            0, 0);
 7     if (!HeapTupleIsValid(tuple))
 8         return NULL;
 9     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped){
10         ReleaseSysCache(tuple);
11         return NULL;
12     }
13     return tuple;
14 }
 1 HeapTuple
 2 SearchSysCacheCopyAttName(Oid relid, const char *attname)
 3 {
 4     HeapTuple    tuple,
 5                 newtuple;
 6 
 7     tuple = SearchSysCacheAttName(relid, attname);
 8     if (!HeapTupleIsValid(tuple))
 9         return tuple;
10     newtuple = heap_copytuple(tuple);
11     ReleaseSysCache(tuple);
12     return newtuple;
13 }

 

SysCacheAttr给定先前由SearchSysCache()获取的元组,提取特定属性。这相当于对从非缓存关系获取的元组使用heap_ghtattr()。通常,这只用于可能为NULL或可变长度的属性;通过将元组映射到include/catalog/中的C struct声明,可以访问系统表中的固定大小属性。与heap_getattr()一样,如果属性是按引用传递的类型,则返回一个指向元组数据区域的指针---调用方不能修改或释放数据!注意:使用带有cacheId的SysCacheGetAttr()是合法的,它引用了从中获取元组的同一目录的不同缓存。

 1 Datum
 2 SysCacheGetAttr(int cacheId, HeapTuple tup,
 3                 AttrNumber attributeNumber,
 4                 bool *isNull)
 5 {
 6     /*
 7      * We just need to get the TupleDesc out of the cache entry, and then we
 8      * can apply heap_getattr().  Normally the cache control data is already
 9      * valid (because the caller recently fetched the tuple via this same
10      * cache), but there are cases where we have to initialize the cache here.
11      */
12     if (cacheId < 0 || cacheId >= SysCacheSize ||
13         !PointerIsValid(SysCache[cacheId]))
14         elog(ERROR, "invalid cache id: %d", cacheId);
15     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
16     {
17         InitCatCachePhase2(SysCache[cacheId], false);
18         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
19     }
20 
21     return heap_getattr(tup, attributeNumber,
22                         SysCache[cacheId]->cc_tupdesc,
23                         isNull);
24 }

 

posted @ 2020-11-19 23:14  肥叔菌  阅读(941)  评论(0)    收藏  举报