写点什么

DWS 临时内存不可用报错: memory temporarily unavailable

  • 2023-10-27
    广东
  • 本文字数:2155 字

    阅读完需:约 7 分钟

DWS临时内存不可用报错: memory temporarily unavailable

本文分享自华为云社区《DWS临时内存不可用报错: memory temporarily unavailable》,作者:漫天。

1、定位报错的 DN/CN


当出现 memory temporarily unavailable 报错时,首先根据报错信息确认具体是哪个 cn/dn 报的,如果报错信息没有类似 dnxxxx_xxxx 这样的信息,就是 cn 报的,需要去每个 cn 的日志里排查是哪个 cn。

2、DWS813 以前的版本内存报错定位


通过 free -g 或者 top 命令查看操作系统内存使用情况,确认是操作系统内存耗尽导致,还是 cn/dn 的内存使用达到限制,导致内存可不用报错。如果没有现场,需要查看操作系统的内存监控。


如果是 cn/dn 的内存使用达到限制,可以按照以下步骤定位:


步骤一:分析内存视图 pv_total_memory_detail(实例级别内存视图)


select * from pv_total_memory_detail ;
复制代码


判断(1)如果 dynamic_peak_memory 大于 max_dynamic_memory,说明是 cn/dn dynamic 内存使用达到上限,导致内存可不用报错。PS:要求历史上 dynamic_peak_memory 没有超过 max_dynamic_memory,即 dynamic_peak_memory 首次超过 max_dynamic_memory 时,该判断方式有效。


判断(2)dynamic_used_memory 接近 max_dynamic_memory,大概率是 cn/dn dynamic 内存使用达到上限,导致内存可不用报错。


判断(3)比较 dynamic_used_memory、dynamic_used_shrctx、sctpcomm_used_memory 大小,如果 dynamic_used_shrctx 非常大,说明多线程共享的动态内存太大,如果 sctpcomm_used_memory 非常大,说明通信库使用的内存非常大,如果 dynamic_used_shrctx 和 sctpcomm_used_memory 都很小,说明 session 占用的内存最多。


步骤二:分析内存视图 pv_session_memory_detail(会话级别内存视图)和活跃会话视图 pg_stat_activity


执行如下 SQL-X,查看每个 session 占用的内存大小:


-- 查看每个session占用的内存大小select split_part(pv_session_memory_detail.sessid,'.',2) pid,pg_size_pretty(sum(totalsize)) total_size,count(*) context_count from pv_session_memory_detail group by pid order by sum(totalsize) desc;
复制代码


如果 SQL-X 查询结果中,某个 session 占用内存特别高,说明该 session 上执行的 SQL 占用内存过高,可以找到对应的 SQL,杀掉该语句并进行整改:


-- 查看语句占用内存大小select b.state, a.sessid, b.query_id, substr(b.query,1,80) as query, sum(totalsize) as totalsize, sum(freesize), sum(usedsize) from pv_session_memory_detail a, pg_stat_activity b where split_part(a.sessid,'.',2) = b.pid group by state,sessid,query_id,query order by totalsize desc limit 100;-- 到对应的CN节点查杀对应的线程select pg_terminate_backend(pid);
复制代码


如果 SQL-X 查询结果中,每个 session 占用内存都不大,但 session 总量大,大概是空闲线程太多导致 dynamic 内存较高。


-- 查看idle线程数量SELECT count(*) FROM pg_stat_activity WHERE state='idle';-- 查看各个线程状态的内存使用select b.state, sum(totalsize) as totalsize, sum(freesize) as freesize, sum(usedsize) as usedsize from pv_session_memory_detail a, pg_stat_activity b where split_part(a.sessid,'.',2) = b.pid group by b.state order by totalsize desc limit 100;-- 查询各个应用的内存使用select b.application_name, sum(totalsize) as totalsize, sum(freesize) as freesize, sum(usedsize) as usedsize from pv_session_memory_detail a, pg_stat_activity b where split_part(a.sessid,'.',2) = b.pid group by b.application_name order by totalsize desc limit 100;-- 查询各个用户的内存使用select b.usename, sum(totalsize) as totalsize from pv_session_memory_detail a, pg_stat_activity b where split_part(a.sessid,'.',2) = b.pid group by b.usename order by totalsize desc limit 30;-- 查看各类型等待线程的数量select wait_status,wait_event,count(*) from pg_thread_wait_status group by 1,2 order by 3 desc;
复制代码


如果是空闲用户线程导致 dynamic 内存高,可以临时清理下空闲用户线程:


gsql -d postgres -p 25308 -c "clean connection to all for database xxx;"
复制代码


如果是空闲 stream 线程导致 dynamic 内存高,可以将参数 max_stream_pool 改小(stream 线程池的作用是缓存 stream 线程,stream 线程是用来进行 dn 之间数据的传输,一般多表 join 的时候 stream 线程会较多),减小 max_stream_pool 的影响是短查询的性能会降低,对复杂查询几乎没影响。

3、DWS813 及以后的版本内存报错定位


可以使用 813 以前版本的定位方式,也可以使用下面的方式。


步骤一:查看报错日志


813 及以上版本会打印出 debug 的信息,可以通过搜关键字 abnormal 来找到当时使用最高的语句,找到 thread id,再查找 thread id 找到对应 query id


步骤二:查看 topsql


上一步可以找到占用内存最大的 sql,如果该 sql 占用内存确实很大,通过 topsql 查找对应的 query id,从而找到对应的 SQL 语句,并通过 unique_sql_id 找到同一类型的 SQL,进行分析整改。


如果不是某个 sql 占用内存太高导致,分析方法和 813 以前的版本一样。


另外,813 及以后的版本可以使用如下方式清理空闲用户线程:


-- 清理空闲用户线程,每次清1/4-- 显示清理了多少,还剩多少select * from pgxc_clean_free_conn;
复制代码


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
DWS临时内存不可用报错: memory temporarily unavailable_数据库_华为云开发者联盟_InfoQ写作社区