華為雲GaussDB(DWS)記憶體知識點,你知道嗎?

華為雲開發者社群發表於2020-08-03

前言

在日常資料庫的使用中,難免會遇到一些記憶體問題。此次博文主要向大家分享一些華為雲數倉GaussDB(DWS)記憶體的基本框架以及基本檢視的使用,以便遇到記憶體問題後可以有一個基本的判斷。

注意,本篇博文基於華為雲數倉GaussDB(DWS) 8.0版本,其他版本細節上或許稍有不同。

記憶體常用檢視

1. PV_TOTAL_MEMORY_DETAIL檢視

該檢視會展示當前資料庫節點的記憶體使用資訊,單位為MB。

檢視中個欄位的含義:nodename:節點名稱,memorytype:記憶體型別,memorymbytes:對應記憶體型別的大小。

常用的記憶體型別有以下幾種:

  • max_process_memory:取自GUC引數max_process_memory的配置,表示一個資料庫節點最大可使用的實體記憶體。
  • process_used_memory:取自/proc/pid/statm(第二個值) * pagesize,pid替換為當前節點所在的程式號。表示當前節點所處程式已使用的記憶體。
  • max_dynamic_memory:由下面公式計算而來,表示Gaussdb核心所能使用的最大記憶體。
  • max_dynamic_memory = max_process_memory- max_cstore_memory - udf_reserved_memory - max_shared_memory ;
  • dynamic_used_memory:GaussDB核心已使用記憶體,由GaussDB記憶體管理在申請記憶體時統計而來。
  • dynamic_peak_memory:GaussDB核心使用記憶體峰值,由GaussDB記憶體管理在申請記憶體時統計而來。
  • dynamic_used_shrctx:GaussDB核心已使用執行緒間共享記憶體上下文記憶體大小,由GaussDB記憶體管理在申請記憶體時統計而來。
  • dynamic_peak_shrctx:GaussDB核心已使用執行緒間共享記憶體上下文記憶體峰值,由GaussDB記憶體管理在申請記憶體時統計而來。
  • max_shared_memory:程式間最大共享記憶體大小
  • shared_used_memory:程式間已使用共享記憶體大小,由/proc/pid/statm(第三個值) * pagesize值統計而來。
  • max_cstore_memory:列存允許的最大使用記憶體,由GUC引數cstore_buffers配置。
  • cstore_used_memory:列存已使用記憶體,一般包含列存或HDFS使用過程中所消耗的記憶體。
  • other_used_memory:通常表示除去GaussDB核心使用的記憶體以外的記憶體使用,通常是三方庫使用所消耗的記憶體,例如LLVM,Kerberos等。
postgres=# select * from  PV_TOTAL_MEMORY_DETAIL;
   nodename   |       memorytype        | memorymbytes
--------------+-------------------------+--------------
 coordinator1 | max_process_memory      |        12288
 coordinator1 | process_used_memory     |          240
 coordinator1 | max_dynamic_memory      |        11564
 coordinator1 | dynamic_used_memory     |          229
 coordinator1 | dynamic_peak_memory     |          234
 coordinator1 | dynamic_used_shrctx     |            1
 coordinator1 | dynamic_peak_shrctx     |            1
 coordinator1 | max_shared_memory       |          211
 coordinator1 | shared_used_memory      |          139
 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       |            0
 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
(22 rows)

2. PV_SESSION_MEMORY_DETAIL檢視

華為雲數倉GaussDB(DWS)的記憶體管理框架沿用了之前的記憶體上下文的思路。在PV_SESSION_MEMORY_DETAIL的檢視中,將會統計各執行緒的記憶體上下文維度統計的記憶體使用情況。

檢視中個欄位的含義如下:

Sessid:表示Session ID,由執行緒啟動時間+執行緒標識拼接而來。

Sesstype:執行緒名稱

Contextname:記憶體上下文名稱。

Level:記憶體上下文層級。

Parent:父記憶體上下文名稱。

Totalsize:當前記憶體上下文記憶體大小

Freesize:當前記憶體上下文已釋放記憶體大小

Usedsize:當前記憶體上下文已使用大小。

postgres=# select * from PV_SESSION_MEMORY_DETAIL order by totalsize desc;
           sessid           |        sesstype         |         contextname          | level |            parent            | totalsize | freesize | usedsize
----------------------------+-------------------------+------------------------------+-------+------------------------------+-----------+----------+----------
 0.140169093357952          | postmaster              | Postmaster                   |     1 | TopMemoryContext             |  26566912 |    23912 | 26543000
 0.140169093357952          | postmaster              | gs_signal                    |     1 | TopMemoryContext             |   4272464 |  2050224 |  2222240
 1594694378.140168361137920 | WLMCollectWorker        | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   268488 |  1186544
 1594694378.140168296134400 | WLMarbiter              | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   266696 |  1188336
 1594694378.140168465999616 | JobScheduler            | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   239584 |  1215448
 1594708276.140168270964480 | postgres                | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   316392 |  1138640
 1594694438.140168207001344 | postgres                | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   329944 |  1125088
 1594694378.140168344356608 | WLMmonitor              | CacheMemoryContext           |     1 | TopMemoryContext             |   1455032 |   269528 |  1185504
 1594708276.140168270964480 | postgres                | TempSmallContextGroup        |     0 |                              |    550592 |   160320 |      114
 1594694438.140168207001344 | postgres                | TempSmallContextGroup        |     0 |                              |    530816 |   148256 |      107
 1594708276.140168270964480 | postgres                | SRF multi-call context       |     5 | FunctionScan_140168270964480 |    496704 |     8032 |   488672

3. PG_SHARED_MEMORY_DETAIL檢視

華為雲數倉GaussDB(DWS)除了通用記憶體上下文以外,還包含共享記憶體上下文型別用於執行緒間共享資料。由於共享記憶體上下文是屬於一個程式的,故該檢視相比PV_SESSION_MEMORY_DETAIL,不存在sessid,其他的欄位含義相同。

postgres=# select * from PG_SHARED_MEMORY_DETAIL order by totalsize desc;
              contextname               | level |                 parent                 | totalsize | freesize | usedsize
----------------------------------------+-------+----------------------------------------+-----------+----------+----------
 Workload manager memory context        |     1 | ProcessMemory                          |   1056832 |     6080 |  1050752
 PoolerAgentContext                     |     2 | PoolerMemoryContext                    |     57344 |    36000 |    21344
 PoolerCoreContext                      |     2 | PoolerMemoryContext                    |     57344 |    30544 |    26800
 ProcessMemory                          |     0 |                                        |     57344 |    28304 |    29040
 wlm iostat info hash table             |     2 | Workload manager memory context        |     24576 |    10832 |    13744
 WaitCountGlobalContext                 |     1 | ProcessMemory                          |     24576 |     9984 |    14592
 wlm user info hash table               |     2 | Workload manager memory context        |     24576 |    10832 |    13744
 OBS connector cache                    |     1 | ProcessMemory                          |     24576 |    15056 |     9520
 Resource pool hash table               |     2 | Workload manager memory context        |     17984 |     2704 |    15280
 Dummy server cache                     |     1 | ProcessMemory                          |      8192 |     2832 |     5360
 Node Pool                              |     3 | PoolerCoreContext                      |      8192 |      768 |     7424

記憶體相關資料收集

通過前面講述的幾個記憶體檢視,我們可以對華為雲數倉GaussDB(DWS)記憶體有一個整體的理解。下面將分享幾個記憶體相關資料收集的功能。

注意: 鑑於論壇中的問題多是release版本,故debug版本的各種記憶體相關功能將不再此次介紹以免混淆。同時收集資料就會帶來一些消耗,避免長期大規模的使用下面的方案,僅用作問題診斷資料分析使用。

1. pv_session_memctx_detail函式

通過上面的檢視介紹我們瞭解到了PV_SESSION_MEMORY_DETAIL檢視的作用。我們可以通過pv_session_memctx_detail列印出該執行緒記憶體上下文的詳細資訊。注意第一個參數列示執行緒ID,我們根據上線的介紹得知sessid的後半部分就是執行緒ID。第二個參數列示需要列印記憶體上下文的名稱,在release為空才可以生效即由TopMemoryContext開始遞迴列印記憶體上下文資訊。Release版本不包含chunk的詳細資訊。

例如:

select * from pv_session_memctx_detail(140168207001344,'');

生成的檔案預設在/tmp/dumpmem下,檔案中三列分別表示記憶體上下文名稱,總大小,剩餘大小。

檔案內容樣例:

140168207001344_1594695418.log

TopMemoryContext, 460808, 24728
Record information cache, 24576, 14928
TableSpace cache, 8192, 2304
set params hash table, 8192, 2832
VecFuncHash, 122272, 20928
MaskPasswordCtx, 8192, 8144
RowDescriptionContext, 8192, 7104
MessageContext, 8192, 7104
Operator class cache, 8192, 768
smgr relation table, 24576, 8880

2. memory_tracking_mode引數

除了上面的記憶體上下文資料統計,我們還可以通過memory_tracking_mode設定記憶體資訊統計的模式,共支援四種模式:

none:不啟動記憶體統計功能。

normal:僅做記憶體實時統計,不生成檔案。

executor:生成統計檔案,包含執行層使用過的所有已分配記憶體的上下文資訊。當為executor模式時,將在GaussDB程式(取決於在哪個資料節點最終執行了該運算元)的pg_log目錄下生成cvs格式檔案,命名方式為:memory_track_<DN名稱>_query_<queryid>.csv。作業執行時,執行器postgres執行緒和所有stream執行緒執行的運算元資訊,都將輸入該檔案。其中各欄位分別為:輸出順序號、執行緒內分配記憶體上下文的順序號、當前記憶體上下文的名稱、父記憶體上下文的輸出順序號、父記憶體上下文的名稱、記憶體上下文樹形層次級別號、當前記憶體上下文使用的記憶體峰值、當前記憶體上下文及其所有子記憶體上下文使用的記憶體峰值、當前執行緒所在query的plannodeid。

fullexec:生成檔案包含執行層申請過的所有記憶體上下文資訊。當設定為fullexec模式時,輸出資訊和executor模式相同,但可能增加部分記憶體上

下文分配資訊,因為所有申請記憶體(無論是否申請成功)相關的資訊都會被列印出來。由於僅記錄記憶體申請資訊,故記錄中記憶體上下文使用的峰值均為0。

csv檔案內容樣例:

memory_track_datanode1_query_72339069014639220.csv

0, 0, ExecutorState, 0, (null), 0, 8K, 656K, 4
1, 4, CStoreScan_139944754403072, 0, ExecutorState, 1, 272K, 625K, 4
2, 9, cstore scan per scan memory context, 1, CStoreScan_139944754403072, 2, 24K, 24K, 4
3, 8, cstore scan memory context, 1, CStoreScan_139944754403072, 2, 328K, 328K, 4
4, 2, VecToRow_139944754403072, 0, ExecutorState, 1, 23K, 23K, 4
0, 0, ExecutorState, 0, (null), 0, 8K, 144K, 0
1, 13, Stream_72339069014639220_4, 0, ExecutorState, 1, 72K, 72K, 0
2, 10, Sort_72339069014639220_3, 0, ExecutorState, 1, 8K, 40K, 0
3, 16, TupleSort, 2, Sort_72339069014639220_3, 2, 32K, 32K, 0
4, 2, Agg_72339069014639220_2, 0, ExecutorState, 1, 24K, 24K, 0

一些診斷方案:

1. 記憶體膨脹

在release版本除錯工具以及資訊比較受限,基本都是先通過前面介紹的三種檢視初步定位大致功能。首先檢視PV_TOTAL_MEMORY_DETAIL檢視確定是哪一塊記憶體出現了膨脹或者洩露。若是other_used_memory則要考慮三方倉的場景。若是dynamic_used_memory較大,則要查PV_SESSION_MEMORY_DETAIL檢視,檢視哪個執行緒,哪個記憶體上下文佔用記憶體過多。根據這些資訊推斷出大致問題場景。

2. 記憶體不足

在核心發現記憶體不足的時候會有memory is temporarily unavailable的日誌提示。首先觀察日誌,若日誌裡是reaching the database memory limitation則說明核心使用記憶體到達了max_dynamic_memory,則需要根據PV_SESSION_MEMORY_DETAIL檢視分析是那個記憶體上下文佔用記憶體較多,分析出業務場景。若日誌裡是reaching the OS memory limitation,則表示是作業系統分配記憶體失敗導致,需要看作業系統引數配置以及記憶體硬體等情況。

小結:

生產環境出現記憶體問題一般會比較棘手,而且release版本記憶體檢測工具以及資料資訊使用都比較受限,遇到問題需要通過上述的方案以及手段快速定位出出現記憶體問題的相關業務場景。有了業務場景,後面通過debug版本使用ASAN地址消毒技術以及Jemalloc Profiling便可以較快的定位出來。

 

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

相關文章