避免内存错误和GPDB资源问题
内存管理对GPDB集群具有重要的性能影响。大多数环境推荐使用默认设置。不要去改变默认设置,除非你真的理解了自己系统的需求。
解决内存溢出错误
内存不足错误绘制出遇到内存不足错误的GPDB的段数据库,节点,进程信息
例如:
Out of memeory ( seg27 host. example.com pid = 47093 )
VM Protecte failed to allocate 4096 bytes , 0MB available
通常情况下GPDB内存溢出的情况可以归因于以下情况:
- 系统本身内存资源就不足,不够使用
- 在段数据库层次上,数据倾斜
- 在查询层次上,计算倾斜
解决GPDB内存溢出的情况,可以是用如下方法
- 修改查询语句,尽量减少内存消耗
- 使用资源队列,减少并发查询的数量
- 在数据库层面上检查 gp_vmem_protect_limit 参数配置。 使用下面的例子计算该值
- 在资源队列中,为每一个查询设置内存配额
- 是用会话设置来减少查询的 statement_mem在数据库层面减少 statememt_mem
- 减少集群中节点上段数据库的数量,但是这需要重新安装数据库集群和重新加载数据
- 在节点上增加硬件资源,如果可能(可以根据自身需求添加)
增加段数据库的数量并不会缓和内存不足的问题。每个查询使用的内存是有 statememt_mem 来确定的。
增加节点,并减少段数据库的数量,调整 gp_vmem_protect_limit 增加,来提升内存分配量。
Greenplum 内存参数的配置
- 如果认真配置系统参数可以很好的避免大部分内存溢出问题。
- 如果不能增加系统硬件资源,我们可以通过配置资源队列来管理任务,避免内存溢出。
- 当段数据库失效时,内存需求对于镜像段来说非常重要,因为它需要
推荐如下的系统设置和数据库内存参数设置
- 不要是用系统级别的大存储页
- vm.overcommit_memory 系统级的参数设置。推荐设置为2, 它决定系统分配多少资源给进程使用。
- vm.overcommit_ratio linux系统级别的参数设置。内存使用的百分比。默认设置为50.如果这个值设置的太高,将会导致系统没有可用的资源,这也会导致段失败或者数据库失败; 如果这个只设置的太低,将会导致查询的并发量和查询的复杂度,可以通过减少数据库集群的设置内存量实现。如果要增加该值,一定要记住保留部分资源留给操作系统使用。
- gp_vmem_protect_limit . 段数据库上的全部工作所能申请的最大内存由该值控制。永远不要设置该值大于操作系统所含有的物理内存大小 (RAM)。如果设置太大,很容易引起问题,操作失败等。如果设置的值太小,也有问题。例如,真正系统需要内存时,会被制止。查询很可能会失败,因为hiting 受限。但是却可以很好的保护段数剧库失效和节点失效的问题。
runaway_detector_activation_percent中止失控查询,引入到GPDB4.3.4,避免内存异常。
- 这个参数 runaway_detector_activation_percent 系统参数控制内存使用了 gp_vmem_protect_limit 的到达某个百分比,然后去触发中止失控查询。
这个值的默认值为90%。如果在段数据库上,使用的内存量超过这个百分比,GPDB将会根据内存使用情况中止查询。查询内存使用量低于要求的百分比,将不会被中止。
- statement_mem一个段数据库中,一条查询使用的内存量。如果多余该值的内存被申请,将会产生溢出文件到磁盘上。使用如下公式来确定 statement_mem 的值.
(vmprotect * 0.9) / max_expected_concurrent_queries
- statement_mem 的默认值是125MB。例如, 一个查询运行在DEll EMC DCA V2 系统上,使用默认值将会改变为 1GB 内存对于每一个段数据库(8 segments * 125MB)。 在会话层面设置
- statement_mem 去完成查询任务。这种设置任务将会降低查询的并发性。对于集群高并发使用资源队列来实现额外的控制,集群运行多少查询。
- gp_workfle_limit_files_per_query 这个参数用来控制磁盘溢出文件的最大数量对于每一个查询任务。 溢出文件是在查询需要更多的内存资源时,创建的磁盘临时文件。当某一查询申请的磁盘溢出文件数量超过该值时,就会导致查询被中止。这个值默认是0,意味着对于查询语句的溢出文件数量没有限制,知道溢出文件数量填满整个文件系统为止。想想很疯狂。
- gp_workfile_compress_algorithm 为溢出文件设置压缩算法,可以避免溢出文件太大的问题,减轻I/O操作的压力。
样例分析
集群所含有物理内存为: 256GB
交换空间 SWAP : 64GB
一共有4个节点,其中每一个节点有 8个段数据库,8个镜像段数据库;
每个主节点最多允许失败的节点数是11
gp_vmem = ( (SWAP + RAM) - (7.5GB + 0.05 * RAM ) ) / 1.7
= ( (64 + 256) - (7.5 + 0.05*256) ) / 1.7
= 176
vm.overcommit_ratio = ( RAM - (0.026 * gp_vmeme) )/RAM
= (256 - (0.026 * 176)) / 256
= 0.982
所以设置 vm.overcommit_ratio = 98
计算
gp_vmem_protect_limit = gp_vmem / maximum_acting_primary_segments
= 176 / 11
= 16 GB
= 16384 MB
资源队列配置
GPDB 资源队列为管理整个集群的负载提供非常有力的机制。资源队列可以限制在队列中查询的数量和查询语句内存的使用量。当一个查询提交给GPDB集群,它就会被追加到资源队列中。这决定了这个查询是否被资源队列接收并确定是否有足够的资源用于查询的执行。
将所有用户和管理员定义的资源队列关联,每一个登录的用户都有自己的资源队列;这个用户提交的任何查询都将会和管理员提供的资源队列关联起来。如果没有显示的分配队列,则用户的查询将会转换为默认队列。
不要使用 gpadmin 用户或者其他超级用户角色去运行查询。因为超级用户并不受资源队列的限制,超级用户运行在其指定的资源队列上,并且不受之前设定的参数限制。
- 使用 ACTIVE_STATEMENTS 资源队列参数来限制特定的资源队列成员可以同时运行的活动查询的数量
- 使用 MEMORY_LIMIT 参数来限制资源队列中全部查询所能使用的内存总量。通过结合 ACTIVE_STATEMENTS 和 MEMORY_LIMIT 属性,管理员可以完全控制从给定资源队列发出的活动。分配工作如下
提供一个资源队列, 名称为: sample_queue, ACTIVE_STATEMENTS 设置为10 , MEMORY_LIMIT 设置为2000MB。 这个资源队列对每个段数据库上执行查询的内存限制为近似为 2GB。 对于一个集群,每个节点上有8个段数据库,那么该节点执行查询所需要的内存为 16GB 对于 sample_queue 这个队列。 (2GB 8 segmnet / server)。假设一个节点有64GB内存,那么像 sample_queue 这样的资源队列不要超过4个 (4 queues 16 GB per queue)。
- 请注意,通过使用 STATEMENT_MEM , 在队列中运行各个查询可以分配更多多余他们 "share" 的内部才能。 从而减少可用于其他查询的内存。
可以使用资源队列来控制工作负载以获得期望的效果。具有MAX优先级的队列会阻止其他较低优先级的队列运行。直到MAX队列都执行完,较低优先级的队里才执行
- 根据负载和一天中的时间段动态调整资源队列的优先级以满足业务需求。根据时间段和系统的使用情况,典型的环境会有动态调整队列优先级的操作流。可以通过脚本实现工作流并加入到 crontab 中。
- 使用 gptoolkit 工具来查看监控资源队列的使用情况,了解队列的工作原理