PG高速缓冲区(Cache)——系统表元组缓冲区SysCache初始化

系统缓冲管理器

  当数据库访问表时,需要表的模式信息,比如表的列属性、OID、统计信息等。PostgreSQL将表的模式信息存放在系统表中,因此要访问表,就需要首先在系统表中取得表的模式信息。对于一个PostgreSQL系统来说,对于系统表和普通表模式的访问是非常频繁的。为了提高这些访问的效率,PostgreSQL设立了高速缓存Cache来提高访问效率。Cache中包括一个系统表元组Cache(SysCache)和一个表模式信息Cache(RelCache)。SysCache中存放的是最近使用过的系统表的元组,而RelCache中包含所有最近访问过的表的模式信息(包含系统表的信息),RelCache中存放的不是元组,而是RelationData数据结构。两种Cache都不是所有进程共享的,每个PG进程都维护着自己的SysCache和RelCahce。SysCache机制允许parser、planner、executor快速查找系统表的内容。src/backend/utils/cache/syscache.c

PG高速缓冲区(Cache)——系统表元组缓冲区SysCache初始化

 

 

  SysCache主要用于缓存系统表元组。从实现上看SysCache就是一个数组,数组的长度为预定义的系统表的个数。在PG 8.4.1中实现了54个系统表,因此SysCache数组具有54个元素。每个元素的数据结构为CatCache,该结构体内使用Hash来存储被缓存的系统表元组,每个系统表唯一地对应一个SysCache数组中的CatCache结构。在Postgres进程初始化时,将会对SysCache进行初始化,实际上是填充SysCache数组中元素的CatCache结构体的过程,也就是将查找系统表元组的关键字信息写入SysCache数组元素中。在SysCache.c文件中将所有系统表的CatCache信息存储在一个名为cacheinfo的静态数组中。下面先介绍cacheinfo数组。

  将新缓存添加到include/utils/syscache.h中的列表中。将条目添加到下面的cacheinfo[]数组中。所有缓存列表都是按字母顺序排列的,因此请将其添加到适当的位置。指定关系OID、索引OID、键数、键属性号和哈希桶数。如果关系包含与特定关系(例如,其属性、规则、触发器等)关联的元组,则指定包含关联关系的OID的属性号。CatalogCacheFlushRelation()用于在表删除或relcache失效事件期间删除正确的元组。
桶数的幂必须是2的幂。将其设置为中等大小数据库中特定缓存中的条目数是合理的。每个syscache下必须有一个唯一的索引(即,其键与缓存的键相同的索引)。如果还没有,请为其添加包含/catalog/INDEX.h的定义:您需要为INDEX OID添加DECLARE_UNIQUE_INDEX宏和#define。(添加索引需要catversion.h更新,而简单地添加/删除缓存只需要重新编译。)
  最后,由于heap_*调用不更新索引,在关系表得到heap_insert()或heap_update()调用的任何位置,请确保存在CatalogUpdateIndexes()或类似调用。。

  1 static const struct cachedesc cacheinfo[] = {
  2     {AggregateRelationId, /* AGGFNOID */
  3         AggregateFnoidIndexId, 0, 1,
  4         {
  5             Anum_pg_aggregate_aggfnoid, 0, 0, 0
  6         }, 32 },
  7     {AccessMethodRelationId, /* AMNAME */
  8         AmNameIndexId, 0, 1,
  9         {
 10             Anum_pg_am_amname, 0, 0, 0
 11         }, 4 },
 12     {AccessMethodRelationId, /* AMOID */
 13         AmOidIndexId, 0, 1,
 14         {
 15             ObjectIdAttributeNumber, 0, 0, 0
 16         }, 4 },
 17     {AccessMethodOperatorRelationId, /* AMOPOPID */
 18         AccessMethodOperatorIndexId, 0, 2,
 19         {
 20             Anum_pg_amop_amopopr, 
 21                         Anum_pg_amop_amopfamily, 0, 0
 22         }, 64 },
 23     {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
 24         AccessMethodStrategyIndexId, 0, 4,
 25         {
 26             Anum_pg_amop_amopfamily,
 27             Anum_pg_amop_amoplefttype,
 28             Anum_pg_amop_amoprighttype,
 29             Anum_pg_amop_amopstrategy
 30         }, 64 },
 31     {AccessMethodProcedureRelationId, /* AMPROCNUM */
 32         AccessMethodProcedureIndexId, 0, 4,
 33         {
 34             Anum_pg_amproc_amprocfamily,
 35             Anum_pg_amproc_amproclefttype,
 36             Anum_pg_amproc_amprocrighttype,
 37             Anum_pg_amproc_amprocnum
 38         }, 64 },
 39     {AttributeRelationId, /* ATTNAME */
 40         AttributeRelidNameIndexId,
 41         Anum_pg_attribute_attrelid, 2,
 42         {
 43             Anum_pg_attribute_attrelid,
 44             Anum_pg_attribute_attname, 0, 0
 45         }, 2048 },
 46     {AttributeRelationId,        /* ATTNUM */
 47         AttributeRelidNumIndexId,
 48         Anum_pg_attribute_attrelid, 2,
 49         {
 50             Anum_pg_attribute_attrelid,
 51             Anum_pg_attribute_attnum, 0, 0
 52         }, 2048 },
 53     {AuthMemRelationId,            /* AUTHMEMMEMROLE */
 54         AuthMemMemRoleIndexId,
 55         0,
 56         2,
 57         {
 58             Anum_pg_auth_members_member,
 59             Anum_pg_auth_members_roleid,
 60             0,
 61             0
 62         },
 63         128
 64     },
 65     {AuthMemRelationId,            /* AUTHMEMROLEMEM */
 66         AuthMemRoleMemIndexId,
 67         0,
 68         2,
 69         {
 70             Anum_pg_auth_members_roleid,
 71             Anum_pg_auth_members_member,
 72             0,
 73             0
 74         },
 75         128
 76     },
 77     {AuthIdRelationId, /* AUTHNAME */
 78         AuthIdRolnameIndexId, 0, 1,
 79         {
 80             Anum_pg_authid_rolname, 0, 0, 0
 81         }, 128 },
 82     {AuthIdRelationId,            /* AUTHOID */
 83         AuthIdOidIndexId,
 84         0,
 85         1,
 86         {
 87             ObjectIdAttributeNumber,
 88             0,
 89             0,
 90             0
 91         },
 92         128
 93     },
 94     {
 95         CastRelationId,            /* CASTSOURCETARGET */
 96         CastSourceTargetIndexId,
 97         0,
 98         2,
 99         {
100             Anum_pg_cast_castsource,
101             Anum_pg_cast_casttarget,
102             0,
103             0
104         },
105         256
106     },
107     {OperatorClassRelationId,    /* CLAAMNAMENSP */
108         OpclassAmNameNspIndexId,
109         0,
110         3,
111         {
112             Anum_pg_opclass_opcmethod,
113             Anum_pg_opclass_opcname,
114             Anum_pg_opclass_opcnamespace,
115             0
116         },
117         64
118     },
119     {OperatorClassRelationId,    /* CLAOID */
120         OpclassOidIndexId,
121         0,
122         1,
123         {
124             ObjectIdAttributeNumber,
125             0,
126             0,
127             0
128         },
129         64
130     },
131     {ConversionRelationId,        /* CONDEFAULT */
132         ConversionDefaultIndexId,
133         0,
134         4,
135         {
136             Anum_pg_conversion_connamespace,
137             Anum_pg_conversion_conforencoding,
138             Anum_pg_conversion_contoencoding,
139             ObjectIdAttributeNumber,
140         },
141         128
142     },
143     {ConversionRelationId,        /* CONNAMENSP */
144         ConversionNameNspIndexId,
145         0,
146         2,
147         {
148             Anum_pg_conversion_conname,
149             Anum_pg_conversion_connamespace,
150             0,
151             0
152         },
153         128
154     },
155     {ConstraintRelationId,        /* CONSTROID */
156         ConstraintOidIndexId,
157         Anum_pg_constraint_conrelid,
158         1,
159         {
160             ObjectIdAttributeNumber,
161             0,
162             0,
163             0
164         },
165         1024
166     },
167     {ConversionRelationId,        /* CONVOID */
168         ConversionOidIndexId,
169         0,
170         1,
171         {
172             ObjectIdAttributeNumber,
173             0,
174             0,
175             0
176         },
177         128
178     },
179     {DatabaseRelationId,        /* DATABASEOID */
180         DatabaseOidIndexId,
181         0,
182         1,
183         {
184             ObjectIdAttributeNumber,
185             0,
186             0,
187             0
188         },
189         4
190     },
191     {EnumRelationId,            /* ENUMOID */
192         EnumOidIndexId,
193         0,
194         1,
195         {
196             ObjectIdAttributeNumber,
197             0,
198             0,
199             0
200         },
201         256
202     },
203     {EnumRelationId,            /* ENUMTYPOIDNAME */
204         EnumTypIdLabelIndexId,
205         0,
206         2,
207         {
208             Anum_pg_enum_enumtypid,
209             Anum_pg_enum_enumlabel,
210             0,
211             0
212         },
213         256
214     },
215     {ForeignDataWrapperRelationId,        /* FOREIGNDATAWRAPPERNAME */
216         ForeignDataWrapperNameIndexId,
217         0,
218         1,
219         {
220             Anum_pg_foreign_data_wrapper_fdwname,
221             0,
222             0,
223             0
224         },
225         8
226     },
227     {ForeignDataWrapperRelationId,        /* FOREIGNDATAWRAPPEROID */
228         ForeignDataWrapperOidIndexId,
229         0,
230         1,
231         {
232             ObjectIdAttributeNumber,
233             0,
234             0,
235             0
236         },
237         8
238     },
239     {ForeignServerRelationId,    /* FOREIGNSERVERNAME */
240         ForeignServerNameIndexId,
241         0,
242         1,
243         {
244             Anum_pg_foreign_server_srvname,
245             0,
246             0,
247             0
248         },
249         32
250     },
251     {ForeignServerRelationId,    /* FOREIGNSERVEROID */
252         ForeignServerOidIndexId,
253         0,
254         1,
255         {
256             ObjectIdAttributeNumber,
257             0,
258             0,
259             0
260         },
261         32
262     },
263     {IndexRelationId,            /* INDEXRELID */
264         IndexRelidIndexId,
265         Anum_pg_index_indrelid,
266         1,
267         {
268             Anum_pg_index_indexrelid,
269             0,
270             0,
271             0
272         },
273         1024
274     },
275     {LanguageRelationId,        /* LANGNAME */
276         LanguageNameIndexId,
277         0,
278         1,
279         {
280             Anum_pg_language_lanname,
281             0,
282             0,
283             0
284         },
285         4
286     },
287     {LanguageRelationId,        /* LANGOID */
288         LanguageOidIndexId,
289         0,
290         1,
291         {
292             ObjectIdAttributeNumber,
293             0,
294             0,
295             0
296         },
297         4
298     },
299     {NamespaceRelationId,        /* NAMESPACENAME */
300         NamespaceNameIndexId,
301         0,
302         1,
303         {
304             Anum_pg_namespace_nspname,
305             0,
306             0,
307             0
308         },
309         256
310     },
311     {NamespaceRelationId,        /* NAMESPACEOID */
312         NamespaceOidIndexId,
313         0,
314         1,
315         {
316             ObjectIdAttributeNumber,
317             0,
318             0,
319             0
320         },
321         256
322     },
323     {OperatorRelationId,        /* OPERNAMENSP */
324         OperatorNameNspIndexId,
325         0,
326         4,
327         {
328             Anum_pg_operator_oprname,
329             Anum_pg_operator_oprleft,
330             Anum_pg_operator_oprright,
331             Anum_pg_operator_oprnamespace
332         },
333         1024
334     },
335     {OperatorRelationId,        /* OPEROID */
336         OperatorOidIndexId,
337         0,
338         1,
339         {
340             ObjectIdAttributeNumber,
341             0,
342             0,
343             0
344         },
345         1024
346     },
347     {OperatorFamilyRelationId,    /* OPFAMILYAMNAMENSP */
348         OpfamilyAmNameNspIndexId,
349         0,
350         3,
351         {
352             Anum_pg_opfamily_opfmethod,
353             Anum_pg_opfamily_opfname,
354             Anum_pg_opfamily_opfnamespace,
355             0
356         },
357         64
358     },
359     {OperatorFamilyRelationId,    /* OPFAMILYOID */
360         OpfamilyOidIndexId,
361         0,
362         1,
363         {
364             ObjectIdAttributeNumber,
365             0,
366             0,
367             0
368         },
369         64
370     },
371     {ProcedureRelationId,        /* PROCNAMEARGSNSP */
372         ProcedureNameArgsNspIndexId,
373         0,
374         3,
375         {
376             Anum_pg_proc_proname,
377             Anum_pg_proc_proargtypes,
378             Anum_pg_proc_pronamespace,
379             0
380         },
381         2048
382     },
383     {ProcedureRelationId,        /* PROCOID */
384         ProcedureOidIndexId,
385         0,
386         1,
387         {
388             ObjectIdAttributeNumber,
389             0,
390             0,
391             0
392         },
393         2048
394     },
395     {RelationRelationId,        /* RELNAMENSP */
396         ClassNameNspIndexId,
397         ObjectIdAttributeNumber, 2,
398         {
399             Anum_pg_class_relname,
400             Anum_pg_class_relnamespace, 0, 0
401         }, 1024 },
402     {RelationRelationId,        /* RELOID */
403         ClassOidIndexId,
404         ObjectIdAttributeNumber,
405         1,
406         {
407             ObjectIdAttributeNumber,
408             0,
409             0,
410             0
411         },
412         1024
413     },
414     {RewriteRelationId,            /* RULERELNAME */
415         RewriteRelRulenameIndexId,
416         Anum_pg_rewrite_ev_class,
417         2,
418         {
419             Anum_pg_rewrite_ev_class,
420             Anum_pg_rewrite_rulename,
421             0,
422             0
423         },
424         1024
425     },
426     {StatisticRelationId,        /* STATRELATT */
427         StatisticRelidAttnumIndexId,
428         Anum_pg_statistic_starelid, 2,
429         {
430             Anum_pg_statistic_starelid,
431             Anum_pg_statistic_staattnum, 0, 0
432         }, 1024 },
433     {TSConfigMapRelationId,        /* TSCONFIGMAP */
434         TSConfigMapIndexId,
435         0,
436         3,
437         {
438             Anum_pg_ts_config_map_mapcfg,
439             Anum_pg_ts_config_map_maptokentype,
440             Anum_pg_ts_config_map_mapseqno,
441             0
442         },
443         4
444     },
445     {TSConfigRelationId,        /* TSCONFIGNAMENSP */
446         TSConfigNameNspIndexId,
447         0,
448         2,
449         {
450             Anum_pg_ts_config_cfgname,
451             Anum_pg_ts_config_cfgnamespace,
452             0,
453             0
454         },
455         16
456     },
457     {TSConfigRelationId,        /* TSCONFIGOID */
458         TSConfigOidIndexId,
459         0,
460         1,
461         {
462             ObjectIdAttributeNumber,
463             0,
464             0,
465             0
466         },
467         16
468     },
469     {TSDictionaryRelationId,    /* TSDICTNAMENSP */
470         TSDictionaryNameNspIndexId,
471         0,
472         2,
473         {
474             Anum_pg_ts_dict_dictname,
475             Anum_pg_ts_dict_dictnamespace,
476             0,
477             0
478         },
479         16
480     },
481     {TSDictionaryRelationId,    /* TSDICTOID */
482         TSDictionaryOidIndexId,
483         0,
484         1,
485         {
486             ObjectIdAttributeNumber,
487             0,
488             0,
489             0
490         },
491         16
492     },
493     {TSParserRelationId,        /* TSPARSERNAMENSP */
494         TSParserNameNspIndexId,
495         0,
496         2,
497         {
498             Anum_pg_ts_parser_prsname,
499             Anum_pg_ts_parser_prsnamespace,
500             0,
501             0
502         },
503         4
504     },
505     {TSParserRelationId, /* TSPARSEROID */
506         TSParserOidIndexId, 0, 1,
507         {
508             ObjectIdAttributeNumber, 0, 0, 0
509         }, 4 },
510     {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
511         TSTemplateNameNspIndexId, 0, 2,
512         {
513             Anum_pg_ts_template_tmplname,
514             Anum_pg_ts_template_tmplnamespace, 0, 0
515         }, 16 },
516     {TSTemplateRelationId,        /* TSTEMPLATEOID */
517         TSTemplateOidIndexId, 0, 1,
518         {
519             ObjectIdAttributeNumber, 0, 0, 0
520         }, 16 },
521     {TypeRelationId, /* TYPENAMENSP */
522         TypeNameNspIndexId, Anum_pg_type_typrelid, 2,
523         {
524             Anum_pg_type_typname,
525             Anum_pg_type_typnamespace, 0, 0
526         }, 1024 },
527     {TypeRelationId, /* TYPEOID */
528         TypeOidIndexId, Anum_pg_type_typrelid, 1,
529         {
530             ObjectIdAttributeNumber, 0, 0, 0
531         }, 1024 },
532     {UserMappingRelationId, /* USERMAPPINGOID */
533         UserMappingOidIndexId, 0, 1,
534         {
535             ObjectIdAttributeNumber, 0, 0, 0
536         }, 128 },
537     {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
538         UserMappingUserServerIndexId, 0, 2,
539         {
540             Anum_pg_user_mapping_umuser,
541             Anum_pg_user_mapping_umserver, 0, 0
542         }, 128 }
543 };

   看了静态数组cacheinfo,我们下一步看一下SysCache的庐山真面目。SysCache其实是一个由CatCache结构体指针组成的数组。CatCache结构体使用Hash来存储被缓存的系统表元组,每个系统表唯一地对应一个SysCache数组中的CatCache结构。每个CatCache都有若干个(不超过4个)查找关键字,这些关键字及其组合可以用来在CatCache中查找系统表元组,在初始化数据集簇时会在这些关键字上为系统表创建索引。为了便于查找,Catcache通过其cc_next字段构成一个单向链表,链表头使用全局变量CachHdr记录(数据结构为catcacheheader)。cc_lists是由CatClist结构构成的Dllist链表,用于缓存部分匹配的元组,每个CatClist结构保存一次部分匹配的结果元组。()CatCache中的cc_bucket数组中的每个元素都表示一个Hash桶,元组的键值通过Hash函数可以映射到cc_bucket数组的下标。每个桶都被组织成一个双向链表,节点为Dlelem类型。Dlelem是一个包装过的缓存元组,其dle_val字段指向一个CatCTup形式的缓存元组。

  在PG进程初始化时,会调用InitCatalogCache函数对SysCache数组进行初始化,并建立由CacheHdr记录的CatCache链表。InitCatalogCache函数中对SysCache的初始化主要分为以下几个步骤:

1) 根据cacheinfo为SysCache数组分配空间

2) 循环调用InitCatcache函数根据cacheinfo中的每个元素生成CatCache结构并放入SysCache数组的对应位置中。InitCatcache每调用一次将处理一个cachedesc结构,InitCatcache将首先确保CacheMemoryContext存在(如不存在会创建),然后切换到CacheMemoryContext中。接下来将检查CacheHdr是否存在,不存在则先建立CacheHdr。然后该函数根据cachedesc中要求的Hash桶的数量为即将建立的CatCache结构分配内存,并根据cachedesc结构中的信息填充CatCache的各个字段。最后将生成的CatCache链接在CacheHdr所指向的链表的头部。

 1 void InitCatalogCache(void) {
 2     int            cacheId;
 3     Assert(!CacheInitialized);
 4     MemSet(SysCache, 0, sizeof(SysCache));
 5     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
 6     {
 7         SysCache[cacheId] = InitCatCache(cacheId,                                 
 8                   cacheinfo[cacheId].reloid,                                         
 9                   cacheinfo[cacheId].indoid,                                         
10                   cacheinfo[cacheId].reloidattr,                                         
11                   cacheinfo[cacheId].nkeys,                                         
12                   cacheinfo[cacheId].key,                                         
13                   cacheinfo[cacheId].nbuckets);
14         if (!PointerIsValid(SysCache[cacheId]))
15             elog(ERROR, "could not initialize cache %u (%d)",
16                  cacheinfo[cacheId].reloid, cacheId);
17     }
18     CacheInitialized = true;
19 }

InitCatCache函数,nbuckets是hash桶的数量,必须是2的次方。首先需要创建MemoryContext内存上下文,并转换为CacheMemoryContext类型。如果第一次进入该函数,需要创建CacheHdr结构体。为CatCache结构体申请内存,大小为sizeof(CatCache) + nbuckets * sizeof(Dllist)字节。最后将生成的CatCache结构体插入CacheHdr链表。

 1 CatCache * InitCatCache(int id, Oid reloid, Oid indexoid,
 2              int reloidattr, int nkeys, const int *key,
 3              int nbuckets) {
 4     CatCache   *cp;
 5     MemoryContext oldcxt;
 6     int            i;
 7 
 8     Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
 9     if (!CacheMemoryContext)
10         CreateCacheMemoryContext();
11 
12     oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
13     if (CacheHdr == NULL)
14     {
15         CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
16         CacheHdr->ch_caches = NULL;
17         CacheHdr->ch_ntup = 0;
18 #ifdef CATCACHE_STATS
19         /* set up to dump stats at backend exit */
20         on_proc_exit(CatCachePrintStats, 0);
21 #endif
22     }
23     cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(Dllist));
24     cp->id = id;
25     cp->cc_relname = "(not known yet)";
26     cp->cc_reloid = reloid;
27     cp->cc_indexoid = indexoid;
28     cp->cc_relisshared = false; /* temporary */
29     cp->cc_tupdesc = (TupleDesc) NULL;
30     cp->cc_reloidattr = reloidattr;
31     cp->cc_ntup = 0;
32     cp->cc_nbuckets = nbuckets;
33     cp->cc_nkeys = nkeys;
34     for (i = 0; i < nkeys; ++i)
35         cp->cc_key[i] = key[i];
36     cp->cc_next = CacheHdr->ch_caches;
37     CacheHdr->ch_caches = cp;
38     MemoryContextSwitchTo(oldcxt);
39     return cp;
40 }

  在InitCatalogCache函数中实际只完成了SysCache初始化的第一个阶段,在稍后被调用的函数RelationCacheInitializePhase2(负责RelCache的初始化)还将调用InitCatcachePhase2进行第二阶段也是最后的SysCache初始化工作。InitCatcachePhase2将依次完善SysCacche数组中的CatCache结构,主要是根据对应的系统表填充CatCache结构中的元组描述符(cc_tupledesc)、系统表名(cc_relname)、查找关键字的相关字段(cc_hashfunc、cc_isname、cc_skey)等。SysCache数组初始化后,CatCache内是没有任何元组的,但是随着系统运行,对于系统表元组的访问,其中的系统表元组也会逐渐增多。

1 void InitCatalogCachePhase2(void) {
2     int            cacheId;
3     Assert(CacheInitialized);
4     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
5         InitCatCachePhase2(SysCache[cacheId], true);
6 }

InitCatCachePhase2每调用一次将处理一个SysCache元素指向的结构,如果对应的系统表元组描述符为NULL,则先调用CatalogCacheInitialize函数。对除了AMOID和AMNAME之外的系统表都尝试打开其引用的索引。

1 void InitCatCachePhase2(CatCache *cache, bool touch_index) {
2     if (cache->cc_tupdesc == NULL)
3         CatalogCacheInitializeCache(cache);
4     if (touch_index && cache->id != AMOID && cache->id != AMNAME) {
5         Relation    idesc;
6         idesc = index_open(cache->cc_indexoid, AccessShareLock);
7         index_close(idesc, AccessShareLock);
8     }
9 }

CatalogCacheInitialize函数是静态函数,先通过向heap_open传入相应系统表的OID获取RelationData结构体。将TupleDesc开呗到临时缓冲区中。初始化cache键相关信息。

 1 static void CatalogCacheInitializeCache(CatCache *cache) {
 2     Relation    relation;
 3     MemoryContext oldcxt;
 4     TupleDesc    tupdesc;
 5     int            i;
 6 
 7     relation = heap_open(cache->cc_reloid, AccessShareLock);
 8     Assert(CacheMemoryContext != NULL);
 9     oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
10 
11     /* copy the relcache‘s tuple descriptor to permanent cache storage */
12     tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
13 
14     cache->cc_relname = pstrdup(RelationGetRelationName(relation));
15     cache->cc_relisshared = RelationGetForm(relation)->relisshared;
16 
17     MemoryContextSwitchTo(oldcxt);
18     heap_close(relation, AccessShareLock);
19 
20     CACHE3_elog(DEBUG2, "CatalogCacheInitializeCache: %s, %d keys",
21                 cache->cc_relname, cache->cc_nkeys);
22 
23     /* initialize cache‘s key information */
24     for (i = 0; i < cache->cc_nkeys; ++i)
25     {
26         Oid            keytype;
27         RegProcedure eqfunc;
28 
29         if (cache->cc_key[i] > 0)
30             keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid;
31         else
32         {
33             if (cache->cc_key[i] != ObjectIdAttributeNumber)
34                 elog(FATAL, "only sys attr supported in caches is OID");
35             keytype = OIDOID;
36         }
37 
38         GetCCHashEqFuncs(keytype,
39                          &cache->cc_hashfunc[i],
40                          &eqfunc);
41 
42         cache->cc_isname[i] = (keytype == NAMEOID);
43 
44         fmgr_info_cxt(eqfunc,
45                       &cache->cc_skey[i].sk_func,
46                       CacheMemoryContext);
47 
48         /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
49         cache->cc_skey[i].sk_attno = cache->cc_key[i];
50 
51         /* Fill in sk_strategy as well --- always standard equality */
52         cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber;
53         cache->cc_skey[i].sk_subtype = InvalidOid;
54 
55         CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
56                     cache->cc_relname,
57                     i,
58                     cache);
59     }
60 
61     /*
62      * mark this cache fully initialized
63      */
64     cache->cc_tupdesc = tupdesc;
65 }

 

PG高速缓冲区(Cache)——系统表元组缓冲区SysCache初始化

上一篇:Linux看门狗脚本 1.4


下一篇:11Linux之软件包管理