內核不中斷前提下,Gaussdb(DWS)記憶體報錯排查方法

来源:https://www.cnblogs.com/huaweiyun/archive/2023/03/27/17261766.html
-Advertisement-
Play Games

摘要:本文主要講解如何在內核保證操作不能中斷採取的特殊處理,理論上用戶執行的sql使用的記憶體(dynamic_used_memory) 是不會大範圍的超過max_dynamic_memory的記憶體的 本文分享自華為雲社區《Gaussdb(DWS)記憶體報錯排查方法》,作者: fighttingman。 ...


摘要:本文主要講解如何在內核保證操作不能中斷採取的特殊處理,理論上用戶執行的sql使用的記憶體(dynamic_used_memory) 是不會大範圍的超過max_dynamic_memory的記憶體的

本文分享自華為雲社區《Gaussdb(DWS)記憶體報錯排查方法》,作者: fighttingman。

Gaussdb記憶體佈局

記憶體上下文memoryContext記憶體結構

一、記憶體問題定位方法

分析場景1:資料庫日誌出現ERROR:memory is temporarily unavailable

從報錯信息可以找到是哪個節點的記憶體不足,例如 dn_6003_6004: memory is temporarily unavailable , 這個就是dn_6003的記憶體不足了

1.從日誌分析

觀察對應dn的日誌,是否為“reaching the database memory limitation”,表示為資料庫的邏輯記憶體管理機制保護引起,需要進一步分析資料庫的視圖;若為“reaching the OS memory limitation”,表示為操作系統記憶體分配失敗引起,需要查看操作系統參數配置及記憶體硬體情況等。

1)reaching the database memory limitation情況實例

----debug_query_id=76279718689098154, memory allocation failed due to reaching the database memory limitation. Current thread is consuming about 10 MB, allocating 240064 bytes.
----debug_query_id=76279718689098154, Memory information of whole process in MB:max_dynamic_memory: 18770, dynamic_used_memory: 18770, dynamic_peak_memory: 18770, dynamic_used_shrctx: 1804, dynamic_peak_shrctx: 1826, max_sctpcomm_memory: 4000, sctpcomm_used_memory: 1786, sctpcomm_peak_memory: 1786, comm_global_memctx: 0, gpu_max_dynamic_memory: 0, gpu_dynamic_used_memory: 0, gpu_dynamic_peak_memory: 0, large_storage_memory: 0, process_used_memory: 22105, cstore_used_memory: 1022, shared_used_memory: 2605, other_used_memory: 0, os_totalmem: 257906, os_freemem: 16762.

此時,作業76279718689098154準備申請240064 bytes記憶體,dynamic_used_memory記憶體值為18770MB,二者之和大於max_dynamic_memory(18770MB),超出資料庫限制,記憶體申請失敗。

在811之後的版本還會列印top3的memoryContext記憶體占用,示例如下

----debug_query_id=72339069014641088, sessId: 1670914731.140604465997568.coordinator1, sessType: postgres, contextName: ExprContext, level: 5, parent: FunctionScan_140604465997568, totalSize: 950010640, freeSize: 0, usedSize: 950010640
----debug_query_id=72339069014641053, pid=140604465997568, application_name=gsql, query=select * from pv_total_memory_detail, state=retrying, query_start=2022-12-13 14:59:22.059805+08, enqueue=no waiting queue, connection_info={"driver_name":"gsql","driver_version":"(GaussDB 8.2.0 build bc4cec20) compiled at 2022-12-13 14:45:14 commit 3629 last mr 5138 debug","driver_path":"/data3/x00574567/self/gaussdb/mppdb_temp_install/bin/gsql","os_user":"x00574567"}
----debug_query_id=72339069014641088, sessId: 1670914731.140604738627328.coordinator1, sessType: postgres, contextName: ExprContext, level: 5, parent: FunctionScan_140604738627328, totalSize: 900010080, freeSize: 0, usedSize: 900010080
----debug_query_id=72339069014641057, pid=140604738627328, application_name=gsql, query=select * from pv_total_memory_detail, state=retrying, query_start=2022-12-13 14:59:22.098775+08, enqueue=no waiting queue, connection_info={"driver_name":"gsql","driver_version":"(GaussDB 8.2.0 build bc4cec20) compiled at 2022-12-13 14:45:14 commit 3629 last mr 5138 debug","driver_path":"/data3/x00574567/self/gaussdb/mppdb_temp_install/bin/gsql","os_user":"x00574567"}
----debug_query_id=72339069014641088, sessId: 1670914731.140603779163904.coordinator1, sessType: postgres, contextName: ExprContext, level: 5, parent: FunctionScan_140603779163904, totalSize: 890009968, freeSize: 0, usedSize: 890009968
----debug_query_id=72339069014641058, pid=140603779163904, application_name=gsql, query=select * from pv_total_memory_detail, state=retrying, query_start=2022-12-13 14:59:22.117463+08, enqueue=no waiting queue, connection_info={"driver_name":"gsql","driver_version":"(GaussDB 8.2.0 build bc4cec20) compiled at 2022-12-13 14:45:14 commit 3629 last mr 5138 debug","driver_path":"/data3/x00574567/self/gaussdb/mppdb_temp_install/bin/gsql","os_user":"x00574567"}
----allBackendSize=34, idleSize=7, runningSize=7, retryingSize=20

重要欄位解釋:

sessId:線程啟動時間+線程標識(字元串信息為timestamp.threadid)

sessType:線程名稱

contextName:memoryContext名字

totalSize:記憶體占用大小,單位Byte

freeSize:當前memoryContext釋放記憶體總數,單位Byte

usedSize:當前memoryContext已使用的記憶體總數,單位Byte

application_name:連接到該後端的應用名

query:查詢語句

enqueue:排隊情況

allBackendSize:匯流排程個數,idleSize:idle線程個數,runningSize:活躍的線程個數,retryingSize:重試的線程個數

資料庫還會在複雜作業中進行檢查,查看複雜作業預估記憶體是否超過實際使用記憶體,如果存在,則列印下列信息,供分析。

----debug_query_id=76279718689098154, Total estimated Memory is 15196 MB, total current cost Memory is 16454 MB, the difference is 1258 MB.The count of complicated queries is 17 and the count of uncontrolled queries is 1.

上述信息表示全部複雜作業預計使用記憶體15196 MB,實際使用16454 MB,超出1258 MB。

複雜作業共17個,其中有1個作業實際使用記憶體超過預計記憶體。

----debug_query_id=76279718689098154, The abnormal query thread id 140664667547392.It current used memory is 13618 MB and estimated memory is 1102 MB.It also is the query which costs the maximum memory.

上述信息表示,異常線程id為140664667547392,該線程預估消耗記憶體1102MB,實際消耗13618MB。

----debug_query_id=76279718689098154, It is not the current session and beentry info : datid<16389>, app_name<cn_5001>, query_id<76279718688746485>, tid<140664667547392>, lwtid<173496>, parent_tid<0>, thread_level<0>, query_string<explainperformance with ws as (select d_year AS ws_sold_year, ws_item_sk, ws_bill_customer_sk ws_customer_sk, sum(ws_quantity) ws_qty, sum(ws_wholesale_cost) ws_wc, sum(ws_sales_price) ws_sp from web_sales left join web_returns on wr_order_number=ws_order_number and ws_item_sk=wr_item_sk join date_dim on ws_sold_date_sk = d_date_sk where wr_order_number is null group by d_year, ws_item_sk, ws_bill_customer_sk ), cs as (select d_year AS cs_sold_year, cs_item_sk, cs_bill_customer_sk cs_customer_sk, sum(cs_quantity) cs_qty, sum(cs_wholesale_cost) cs_wc, sum(cs_sales_price) cs_sp from catalog_sales left join catalog_returns on cr_order_number=cs_order_number and cs_item_sk=cr_item_sk join date_dim on cs_sold_date_sk =d_date_sk where cr_order_number is null group by d_year, cs_item_sk, cs_bill_customer_sk ), ss as (select d_year AS ss_sold_year, ss_item_sk, ss_customer_sk, sum(ss_quantity) ss_qty, sum(ss_wholesale_cost) ss_wc, sum(ss_sales_price) ss_spfrom store_sales left join store_returns on sr_ticket_numbe>.
上述信息進一步顯示記憶體使用超過預估記憶體的作業信息的sql信息,其中datid表示資料庫的OID,app_name表示application name,query_string表示查詢sql。
----debug_query_id=76279718689098154, WARNING: the common memory context 'HashContext' is using 1059 MB size larger than 989 MB.----debug_query_id=76279718689098154, WARNING: the common memory context 'VecHashJoin_76279718688746485_6' is using 12359 MB size larger than 10 MB.
上述信息表示超限的memcontext,76279718689098154號查詢中,memory context預設值的最大值為989MB,實際使用了1059 MB。

2)reaching the OS memory limitation

當GaussDB記憶體使用符合GUC中相關參數限制,但操作系統可用記憶體不足時,會出現與1.1中類似的日誌信息,格式如下

----debug_query_id=%lu, FATAL: memory allocation failed due to reaching the OS memory limitation. Current thread is consuming about %d MB, allocating %ld bytes.
----debug_query_id=%lu, Please check the sysctl configuration and GUC variable max_process_memory.
----debug_query_id=%lu, Memory information of whole process in MB:"
                            "max_dynamic_memory: %d, dynamic_used_memory: %d,
dynamic_peak_memory: %d, dynamic_used_shrctx: %d,
dynamic_peak_shrctx: %d, max_sctpcomm_memory: %d,
sctpcomm_used_memory: %d, sctpcomm_peak_memory: %d,
comm_global_memctx: %d, gpu_max_dynamic_memory: %d,
gpu_dynamic_used_memory: %d,
gpu_dynamic_peak_memory: %d, large_storage_memory: %d,
process_used_memory: %d, cstore_used_memory: %d,
shared_used_memory: %d, other_used_memory: %d,
os_totalmem: %d, os_freemem: %d

其中,os_totalmem是當前OS中的總記憶體,即“free”命令中的total信息。os_freemem是當前OS中的可用記憶體,即“free”命令中的free信息。

第一條日誌中“allocating %ld bytes”中的待申請的記憶體大於第三條日誌中“os_freemem”項,且資料庫可運行,無其他異常,則符合預期,說明OS記憶體不足。

2. 實例每個實例的記憶體使用情況,查詢pgxc_total_memory_detail

記憶體報錯後,語句使用的記憶體就會釋放,當時占用記憶體高的語句可能會因為報錯,導致現場沒有了,查詢記憶體視圖查詢不到的情況

with a as (select *from pgxc_total_memory_detail where memorytype='dynamic_used_memory'), b as(select * from pgxc_total_memory_detail wherememorytype='dynamic_peak_memory'), c as (select * from pgxc_total_memory_detailwhere memorytype='max_dynamic_memory'), d as (select * frompgxc_total_memory_detail where memorytype='process_used_memory'), e as (select* from pgxc_total_memory_detail where memorytype='other_used_memory'), f as(select * from pgxc_total_memory_detail where memorytype='max_process_memory')select a.nodename,a.memorymbytes as dynamic_used_memory,b.memorymbytes asdynamic_peak_memory,c.memorymbytes as max_dynamic_memory,d.memorymbytes asprocess_used_memory,e.memorymbytes as other_used_memory,f.memorymbytes asmax_process_memory from a,b,c,d,e,f where a.nodename=b.nodename andb.nodename=c.nodename and c.nodename=d.nodename and d.nodename=e.nodename ande.nodename=f.nodename order by a.nodename;

在查詢這個視圖也有可能會因為記憶體不足報memory is temporarily unavailable,導致視圖查不出來,此時需要將disable_memory_protect設置為off。

set disable_memory_protect=off; 之後在查詢視圖就不會報錯。

通過上邊這視圖可以找到集群中哪個節點的記憶體使用有異常,之後連接那個節點通過pv_session_memory_detail視圖找到有問題的memorycontext。

SELECT * FROM pv_session_memory_detail ORDER BY totalsize desc LIMIT 100;

結合pg_stat_activity視圖可以找到哪個語句使用的memcontext最多。

select sessid, contextname, level,parent, pg_size_pretty(totalsize) as total ,pg_size_pretty(freesize) as freesize, pg_size_pretty(usedsize) as usedsize, datname,query_id, query from pv_session_memory_detail a , pg_stat_activity b where split_part(a.sessid,'.',2) = b.pid order by totalsize desc limit 100;

緊急恢復

EXECUTE DIRECT ON(cn_5001) 'SELECT pg_terminate_backend(139780156290816)';

二、記憶體占用高的場景分析

1.空閑連接過多導致記憶體占用

先確認是哪個實例的記憶體占用高,確認方法如上查詢pgxc_total_memory_detail,之後連上那個cn或者dn查詢如下sql

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;

如果是上圖的idle狀態的totalsize占用很多記憶體,可以嘗試清理idle狀態的空閑連接釋放記憶體

解決措施:清理idle狀態的空閑連接

CLEAN CONNECTION TO ALL FORCE FOR DATABASE xxxx;

clean connection 只能清理pg_pooler_status中 in_used是f狀態的空閑連接,不能清理in_used狀態為t的連接,in_used為t 一般是執行了pbe語句導致cn和dn的空閑連接不能釋放導致

如果上邊方法清理不掉,只能嘗試清理cn和客戶端的連接,之後在執行clean connection清理cn和dn之間的連接,可以嘗試在cn上找到是idle狀態的空閑連接,此操作會斷掉cn和客戶端的連接,需要和客戶確認是否可以執行

select 'execute direct on ('||coorname||') ''select pg_terminate_backend('||pid||')'';' from pgxc_stat_activity where usename not in ('Ruby', 'omm') and state='idle';
將select的結果依次執行。

2.語句占用記憶體過多,如果第一個步驟中的第一個語句查詢的是active狀態的語句記憶體占用多,說明是正在執行語句占用的記憶體多導致的

查詢下邊的語句找到記憶體占用多的語句

select b.state as state, a.sessid as sessid, b.query_id as query_id, substr(b.query,1,100) as query, 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 and usename not in ('Ruby', 'omm') group by state,sessid,query_id,query order by totalsize desc limit 100;
找到語句後,根據query_id去對應的cn上進行查殺這個異常sql

3.dynamic_used_shrctx記憶體使用較多

dynamic_used_shrctx是共用記憶體上下文使用的記憶體,也是通過MemoryContext分的,線上程之間共用。通過pg_shared_memory_detail視圖查看

select * from pg_shared_memory_detail order by totalsize desc limit 10;

一般共用記憶體上下文分配和語句有關的, contextname都會帶有線程號或者query_id,根據query_id或者線程號進行查殺異常sql,除此之外共用記憶體上下文一般是內核中各個模塊使用的記憶體,比如topsql,需要排查記憶體使用是否合理,以及釋放機制。

4. 記憶體視圖pv_total_memory_detail 中,dynamic_used_memory > max_dynamic_memory的情況

1)GUC參數disable_memory_protect為on的時候

2)分配記憶體的時候,debug_query_id為0

3)內核在執行關鍵代碼段的時候

4)內核Postmaster線程內的記憶體分配

5)在事務回滾階段

以上情況都是內核保證操作不能中斷採取的特殊處理,理論上用戶執行的sql使用的記憶體(dynamic_used_memory) 是不會大範圍的超過max_dynamic_memory的記憶體的

 

點擊關註,第一時間瞭解華為雲新鮮技術~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • @ 先看一下導出的整體效果(如下圖),其中標註的區域都是通過後臺動態生成的: 一、先在Word中建立好表格模板 1.1、參數創建方法(Word和WPS) 1.1.1、Office中Word域的創建 1.1.1.1、選中指定的單元格 -> 點擊頭部工具欄中的”插入“ -> 選擇 ”文檔部件“ -> 選 ...
  • jdk dockere pull openjdk:11 docker run -d -t --name java-11 openjdk:11 MySQL 可以從docker hup中查找自己想要安裝的版本 docker pull mysql:5.7 拉取鏡像 創建容器 # 在/root目錄下創建my ...
  • 一:相關信息 FTP:(File Transfer Protocol )文件傳輸協議,是基於C/S架構的應用層協議。 FTP伺服器的埠監聽: 預設監聽21/tcp埠 FTP的工作模式: FTP根據伺服器是否自動連接來分為主動模式和被動模式。 主動模式:FTP伺服器主動連接客戶端,這個時候FTP服 ...
  • 前騰訊工程師,經歷過大廠,也經歷過創業! 我已奔四,但我還在持續學習,持續成長! 我非常樂意把我的經驗和心得分享給你! 我是阿銘,關註我,和我一起成長為大牛! 存儲分類 話不多說,直接上圖 至於封閉的以及內置的存儲不是今天要討論的對象,本文主要針對三個外掛存儲DAS、NAS和SAN展開討論。 DAS ...
  • 基本操作 pwd命令 作用:顯示當前工作目錄 用法:pwd cd命令 作用:改變目錄位置 用法:cd [option] [dir] cd 目錄路徑 -進入指定目錄 cd .. -返回父目錄 cd / -進入根目錄 cd或cd ~ -進入用戶主目錄 ls命令 用法:ls [option] [file] ...
  • 一、總體設計思路 以AT89C52單片機為系統核心,充當分析和處理數據的功能。基於AT89C52設計智能濕度控制系統,該系統需對環境空氣中的濕度狀態具有實時監測的功能、當空氣中的相對濕度不理想時可以自動加濕或者自動除濕的功能、電子數位管可以隨時顯示空氣中的相對濕度、手動設置濕度範圍值、並且具有報警功 ...
  • 在伺服器資源有限的情況下,可利用該方案快速搭建各類 mysql 架構方案。各 MySQL 實例共用一個 mysqld 主程式,但各實例數據目錄是獨立的,存放在不同的文件夾中;好了、廢話不多說,直接上乾貨,具體搭建步驟如下 環境介紹 | 實例 | 主機 | mysql port | mysqlx po ...
  • 已測試可用的版本 MySQL 8.0; 環境: windows7/10MySQL 8.0.15免安裝版 項目需求 需要實現一個自動化MySQL配置安裝及初始化資料庫(初始化包括:設置用戶名和密碼)。 批處理 用來對某對象進行批量的處理,即可通過批處理讓相應的軟體執行自動化操作。 MySQL免安裝版使 ...
一周排行
    -Advertisement-
    Play Games
  • 一、openKylin簡介 openKylin(開放麒麟) 社區是在開源、自願、平等和協作的基礎上,由基礎軟硬體企業、非營利性組織、社團組織、高等院校、科研機構和個人開發者共同創立的一個開源社區,致力於通過開源、開放的社區合作,構建桌面操作系統開源社區,推動Linux開源技術及其軟硬體生態繁榮發展。 ...
  • 簡介 Flurl是一個用於構建基於HTTP請求的C#代碼的庫。它的主要目的是簡化和優雅地處理網路請求(只用很少的代碼完成請求)。Flurl提供了一種簡單的方法來構建GET、POST、PUT等類型的請求,以及處理響應和異常。它還提供了一些高級功能,如鏈式調用、緩存請求結果、自動重定向等。本文將介紹Fl ...
  • 一:背景 1. 講故事 最近也挺奇怪,看到了兩起 CPU 爆高的案例,且誘因也是一致的,覺得有一些代表性,合併分享出來幫助大家來避坑吧,閑話不多說,直接上 windbg 分析。 二:WinDbg 分析 1. CPU 真的爆高嗎 這裡要提醒一下,別人說爆高不一定真的就是爆高,我們一定要拿數據說話,可以 ...
  • 剛開始寫文章,封裝Base基類的時候,添加了trycatch異常塊,不過當時沒有去記錄日誌,直接return了。有小伙伴勸我不要吃了Exception 其實沒有啦,項目剛開始,我覺得先做好整體結構比較好。像是蓋樓一樣。先把樓體建造出來,然後再一步一步的美化完善。 基礎的倉儲模式已經ok,Autofa ...
  • 框架目標 什麼是框架,框架能做到什麼? 把一個方向的技術研發做封裝,具備通用性,讓使用框架的開發者用起來很輕鬆。 屬性: 通用性 健壯性 穩定性 擴展性 高性能 組件化 跨平臺 從零開始-搭建框架 建立項目 主鍵查詢功能開發 綁定實體 一步一步的給大家推導: 一邊寫一邊測試 從零開始--搭建框架 1 ...
  • 大家好,我是沙漠盡頭的狼。 本方首發於Dotnet9,介紹使用dnSpy調試第三方.NET庫源碼,行文目錄: 安裝dnSpy 編寫示常式序 調試示常式序 調試.NET庫原生方法 總結 1. 安裝dnSpy dnSpy是一款功能強大的.NET程式反編譯工具,可以對.NET程式進行反編譯,代替庫文檔的功 ...
  • 在`Windows`操作系統中,每個進程的虛擬地址空間都被劃分為若幹記憶體塊,每個記憶體塊都具有一些屬性,如記憶體大小、保護模式、類型等。這些屬性可以通過`VirtualQueryEx`函數查詢得到。該函數可用於查詢進程虛擬地址空間中的記憶體信息的函數。它的作用類似於`Windows`操作系統中的`Task... ...
  • 背景介紹 1,最近有一個大數據量插入的操作入庫的業務場景,需要先做一些其他修改操作,然後在執行插入操作,由於插入數據可能會很多,用到多線程去拆分數據並行處理來提高響應時間,如果有一個線程執行失敗,則全部回滾。 2,在spring中可以使用@Transactional註解去控制事務,使出現異常時會進行 ...
  • 線程(thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際 運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以併發多個線程,每條線 程並行執行不同的任務。 ...
  • 發現Java 21的StringBuilder和StringBuffer中多了repeat方法: /** * @throws IllegalArgumentException {@inheritDoc} * * @since 21 */ @Override public StringBuilder ...