gaussdb=# select contextname, sum(totalsize)/1024/1024 sum, sum(freesize)/1024/1024, count(*) count from gs_shared_memory_detail group by contextname order by sum desc limit 10;
ERROR: memory is temporarily unavailable
DETAIL: Failed on request of size 46 bytes under queryid 281475005884780 in heaptuple.cpp:1934.
原因分析
gaussdb=# select * from pv_total_memory_detail;
nodename | memorytype | memorymbytes
----------------+-------------------------+--------------
coordinator1 | max_process_memory | 81920
coordinator1 | process_used_memory | 14567
coordinator1 | max_dynamic_memory | 34012
coordinator1 | dynamic_used_memory | 1851
coordinator1 | dynamic_peak_memory | 3639
coordinator1 | dynamic_used_shrctx | 394
coordinator1 | dynamic_peak_shrctx | 399
coordinator1 | max_backend_memory | 648
coordinator1 | backend_used_memory | 1
coordinator1 | max_shared_memory | 46747
coordinator1 | shared_used_memory | 11618
coordinator1 | max_cstore_memory | 512
coordinator1 | cstore_used_memory | 0
coordinator1 | max_sctpcomm_memory | 0
coordinator1 | sctpcomm_used_memory | 0
coordinator1 | sctpcomm_peak_memory | 0
coordinator1 | other_used_memory | 1013
coordinator1 | gpu_max_dynamic_memory | 0
coordinator1 | gpu_dynamic_used_memory | 0
coordinator1 | gpu_dynamic_peak_memory | 0
coordinator1 | pooler_conn_memory | 0
coordinator1 | pooler_freeconn_memory | 0
coordinator1 | storage_compress_memory | 0
coordinator1 | udf_reserved_memory | 0
(24 rows)
出现内存过载的问题时,如果有内存过载的环境可以实时定位,可以使用思路一中的定位流程定位内存问题,如果现场环境已经被破坏(集群重启等导致),则按照思路二中的流程进行定位。当前GaussDB Kernel的内存管理采用内存上下文机制管理,在内存使用的统计上有着精准的统计和可视化的视图方便查询定位。
思路一:有现场环境
a. 查询内存统计信息
表1-1信息说明
视图 |
说明 |
pv_total_memory_detail |
全局内存信息概况。 |
pg_shared_memory_detail |
全局内存上下文内存使用详情。 |
pv_thread_memory_context |
线程级内存上下文内存使用详情。 |
pv_session_memory_context |
session级内存上下文使用详情,仅在线程池模式开启时生效。 |
b. 确定内存占用分类
视图 |
结果 |
process_used_memory |
数据库进程所使用的内存大小。 |
dynamic_used_memory |
已使用的动态内存。 |
dynamic_used_shrctx |
全局内存上下文已使用的动态内存。 |
shared_used_memory |
已使用的共享内存。 |
other_used_memory |
其他已使用的内存大小,一般进程释放后被缓存起来的内存会统计在内。 |
根据确定内存占用分类中查询出来的内存统计信息数据就可以确认数据库进程内存使用过高的原因,一般内存占用较高都是由如下2类原因导致。
原因 |
说明 |
|
内存堆积 |
业务执行时临时内存没有及时释放,导致动态内存持续上涨。 |
|
执行作业时,数据库内部频繁申请和释放内存如创建大量的cache plan的情况下会造成大量的内存碎片,由于底层内存机制的缘故,这些内存碎片不会被操作系统立即回收,而是缓存起来,导致数据库占用的内存持续居高不下。 |
常见已知的会导致内存缓存堆积的场景有如下几种: l 作业并发过大,且每个并发执行时都会申请和释放大量的内存。 l 开启GPC,且当pbe多次batch绑定,每bind一次,就会生成一次计划,硬解析一次,导致GPC产生内存碎片。 l 短时间内并发执行存储过程。 l 短时间内大量的申请和释放内存的业务场景。 |
|
实际需要 |
内存使用内存处于较高状态时,如果从内存统计视图数据上为发现有临时内存未释放的情况,此时就需要关注业务的并发量,执行的语句的复杂度等,业务并发过多也会导致内存占用过高,单条复杂的SQL也会造成使用大量内存的场景出现。 |
某些内存过载出现时会导致集群环境重启等,这种情况下没有实时的环境能够定位内存过载的原因是什么,就需要使用如下流程来定位已发生过的内存过载导致的原因。
a. 查看历史内存占用曲线
在环境上查看数据库进程使用内存大小的监控数据。根据数据库在一段时间内的内存变化曲线,可以确认内存过载的时间节点,如下图所示。
从历史内存曲线中,可以看出在8月22日内存出现瞬间上涨的情况。
b.分析历史内存统计信息
根据查看历史内存占用曲线中确认的时间节点信息,使用视图gs_get_history_memory_detail可获得该时间节点的内存快照日志,快照日志以时间戳作为文件名,能够迅速查找,根据快照日志能够快速的找到内存居高的内存上下文信息,然后联系华为工程师协助即可解决。
如果没有在历史内存统计信息中找到对应时间节点的内存快照信息,此时需要关注该时间节点业务的并发量,执行语句的复杂度等,根据实际业务情况进一步分析内存上涨的原因,需联系华为工程师协助解决。
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!