前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GPDB-内核特性-资源组内存管理机制-2

GPDB-内核特性-资源组内存管理机制-2

作者头像
yzsDBA
发布2023-03-27 11:26:41
4830
发布2023-03-27 11:26:41
举报
文章被收录于专栏:PostgreSQL研究与原理解析

GPDB-内核特性-资源组内存管理机制-2

本次介绍资源组内存管理的实现。

1、资源组控制器的创建

资源组控制器由函数ResGroupControlInit创建:主要关注点:资源管理控制器pResGroupControl在共享内存中,hash表和slot池也在共享内存;资源组最多可以建100个,slot池大小为max_connections。

2、资源组控制器初始化

资源组控制器创建后,需要对其进行初始化,比如计算segment总内存等。该功能由InitResGroups完成。堆栈如:InitProcess->InitResManager->InitResGroups。

主要完成计算totalChunks、freeChunks、safeChunksThreshold100和完成CPU相关设置并将已有资源组加载到共享内存。计算方法前章节已有介绍。

3、创建资源组

资源组创建语句为:CREATE RESOURCE GROUP rgroup1 WITH (CPU_RATE_LIMIT=20, MEMORY_LIMIT=25, MEMORY_SHARED_QUOTA=60,MEMORY_SPILL_RATIO=20);

由函数CreateResourceGroup完成创建。资源组的创建流程:

重点关注下如何将资源组加入共享内存中的AllocResGroupEntry函数:

1)计算group->memExpected:资源组定义改组的总内存;

2)从pResGroupControl->freeChunks链表中分配内存,有可能比group->memExpected小;

3)将实际分配的内存chunk分配给slots和共享区,优先slots。slots的总配额为group->memQuotaGranted,共享区总配额为group->memSharedGranted

4、资源组SQL的分发与接收

Master需要将资源组创建SQL的执行计划发送给segment以供在segment上创建资源组。分发函数为CdbDispatchUtilityStatement。

Segment由exec_mpp_query接收到该SQL执行计划后进行反序列化解析并执行。

5、资源组信息的分发与接收

开启一个事务时,会将其分配到资源组中。由此可以控制资源组内并发数。这个动作在master上控制。

StartTransaction

if (ShouldAssignResGroupOnMaster())

AssignResGroupOnMaster();

Master上开启事务,开启事务时分配资源组。若gp_resource_group_bypass开启或者是SET、RESET、SHOW命令则资源组为bypass模式,内存的限制为30MB。其他SQL则走上图中蓝色框内的分支:从资源组的空闲链表中找一个空闲的slot;若超出并发数或者没有空闲slot了,则将该进程加入等待队列,直到gp_resource_group_queuing_timeout超时退出,或者被唤醒。被唤醒时要么将其从资源组等待队列中删除,要么该进程上的slot没有等待时将其释放。

开启事务,分配资源组后,在执行器执行时ExecutorStart会将该执行计划分发给segment。这就需要将执行计划序列化以便发送。

序列化执行计划时也会将资源组信息带进去,由函数SerializeResGroupInfo函数完成。QD上以bypass模式通过bypassedSlot.groupId分发资源组ID。

Segment上接收该执行计划,并将资源组信息反序列化出来。由函数SwitchResGroupOnSegment完成。

3、资源组内存如何限制

资源组下,申请内存同样是gp_malloc函数申请,也就是内存上下文中申请。

当需要申请新的chunk时,需要判断下是否达到了红线,达到红线后先清理下再申请。红线即pResGroupControl->safeChunksThreshold100。

申请块:VmemTracker_ReserveVmemChunks->ResGroupReserveMemory:

申请内存的顺序在函数groupIncMemUsage中:

代码语言:javascript
复制
static int32
groupIncMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks)
{
  int32      slotMemUsage;  /* 当前slot已使用chunk数*/
  int32      sharedMemUsage;  /* the total shared memory usage,
                    sum of group share and global share */
  int32      globalOveruse = 0;  /* the total over used chunks of global share*/

  /* slotMemUsage = slot->memUsage + chunks */
  slotMemUsage = pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &slot->memUsage,chunks);
  /* sharedMemUsage >0:slot配额不够分配 */
  sharedMemUsage = slotMemUsage - slot->memQuota;
  if (sharedMemUsage > 0){
    /* share区分配数 */
    int32 deltaSharedMemUsage = Min(sharedMemUsage, chunks);
    /* oldSharedUsage = group->memSharedUsage
    *  group->memSharedUsage+=deltaSharedMemUsage
    */
    int32 oldSharedUsage = pg_atomic_fetch_add_u32((pg_atomic_uint32 *)
                             &group->memSharedUsage,
                           deltaSharedMemUsage);
    /* 共享区空闲chunk数 */
    int32 oldSharedFree = Max(0, group->memSharedGranted - oldSharedUsage);
    /* 超出共享区分配数*/
    int32 deltaGlobalSharedMemUsage = Max(0, deltaSharedMemUsage - oldSharedFree);
    /* freeChunks -= deltaGlobalSharedMemUsage 全局共享区超出分配数 */
    int32 newFreeChunks = pg_atomic_sub_fetch_u32(&pResGroupControl->freeChunks,
                          deltaGlobalSharedMemUsage);
    /* globalOveruse >0:超出共享区分配数 */
    globalOveruse = Max(0, 0 - newFreeChunks);
  }
  /*分组已使用chunk数,不论在哪部分分配 */
  pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &group->memUsage,chunks);
  return globalOveruse;
}

5、总结

这里介绍了资源组内存分配如何执行,包括两种分配模式:bypass模式和资源组分配模式。尤其需要注意bypass模式,QE上它的内存分配限制仅10MB,QD上分配限制是30MB。Bypass模式仅适用于SET、RESET、SHOW语句,开始事务时分配资源组,然后将资源组信息分发到QE。可以看到同一个事务中的SQL语句都使用同一个资源组。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yanzongshuaiDBA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、资源组控制器的创建
  • 2、资源组控制器初始化
  • 3、创建资源组
  • 4、资源组SQL的分发与接收
  • 5、资源组信息的分发与接收
  • 3、资源组内存如何限制
  • 5、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档