Methode zur Fehlerbehebung bei Gaussdb (DWS)-Speicherfehlern ohne Kernel-Unterbrechung

Kurzfassung: Dieser Artikel erklärt hauptsächlich, wie eine spezielle Verarbeitung im Kernel vorgenommen werden kann, um sicherzustellen, dass die Operation nicht unterbrochen werden kann.Theoretisch wird der Speicher (dynamic_used_memory), der von dem vom Benutzer ausgeführten SQL verwendet wird, den Speicher von max_dynamic_memory in einem großen Bereich nicht überschreiten

Dieser Artikel wurde von der Huawei Cloud Community „ Gaussdb (DWS) Memory Error Troubleshooting Method “, Autor: fightman, geteilt.

Gaussdb-Speicherlayout

Speicherkontext memoryContext Speicherstruktur

1. Methode zur Lokalisierung von Speicherproblemen

Analyseszenario 1: FEHLER: Arbeitsspeicher ist vorübergehend nicht verfügbar erscheint im Datenbankprotokoll

Aus der Fehlermeldung können Sie entnehmen, welcher Knoten nicht genügend Speicher hat, z. B. dn_6003_6004: Speicher vorübergehend nicht verfügbar, das bedeutet, dass der Speicher von dn_6003 nicht ausreicht

1. Aus der Protokollanalyse

Beobachten Sie das Protokoll, das dem dn entspricht, ob es "das Erreichen der Datenbankspeicherbegrenzung" bedeutet, was bedeutet, dass es durch den Schutz des logischen Speicherverwaltungsmechanismus der Datenbank verursacht wird und die Ansicht der Datenbank weiter analysiert werden muss; Wenn es „das Erreichen der Speicherbegrenzung des Betriebssystems“ bedeutet, bedeutet dies, dass die Speicherzuweisung des Betriebssystems fehlschlägt. Wenn dies fehlschlägt, müssen Sie die Parameterkonfiguration des Betriebssystems und die Bedingungen der Speicherhardware überprüfen.

1) Beispiel für das Erreichen der Datenbankspeicherbegrenzung

----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.

Zu diesem Zeitpunkt ist der Job 76279718689098154 im Begriff, 240064 Bytes Speicher zu beantragen, und der Speicherwert dynamic_used_memory beträgt 18770 MB. Die Summe der beiden ist größer als max_dynamic_memory (18770 MB), was die Datenbankgrenze überschreitet, und die Speicheranwendung schlägt fehl.

Die Version nach 811 druckt auch die Top3-MemoryContext-Speichernutzung, das Beispiel ist wie folgt

----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

Erklärung wichtiger Felder:

sessId: Startzeit des Threads + Thread-ID (Zeichenfolgeninformationen sind timestamp.threadid)

Sitzungstyp: Threadname

contextName: Name des Speicherkontexts

totalSize: Größe der Speichernutzung, Einheit Byte

freeSize: die Gesamtspeichermenge, die vom aktuellen memoryContext freigegeben wird, in Byte

usedSize: die Gesamtspeichermenge, die vom aktuellen memoryContext verwendet wird, in Byte

Anwendungsname: Der Name der Anwendung, die mit diesem Backend verbunden ist

Abfrage: Abfrageanweisung

enqueue: Warteschlangenstatus

allBackendSize: Gesamtzahl der Threads, IdleSize: Anzahl der Leerlauf-Threads, RunningSize: Anzahl der aktiven Threads, RetryingSize: Anzahl der wiederholten Threads

Die Datenbank überprüft auch den komplexen Job, um festzustellen, ob der geschätzte Speicher des komplexen Jobs den tatsächlich verwendeten Speicher überschreitet, und druckt in diesem Fall die folgenden Informationen zur Analyse.

----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.

Die obigen Informationen zeigen, dass alle komplexen Jobs voraussichtlich 15196 MB Arbeitsspeicher verwenden, die tatsächliche Nutzung jedoch 16454 MB beträgt und 1258 MB übersteigt.

Es gibt 17 komplexe Jobs, von denen einer tatsächlich mehr Speicher verbraucht als erwartet.

----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.

Die obigen Informationen zeigen, dass die anormale Thread-ID 140664667547392 lautet und der geschätzte Speicherverbrauch dieses Threads 1102 MB beträgt, der tatsächliche Speicherverbrauch jedoch 13618 MB beträgt.

----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>.

Die obigen Informationen zeigen ferner die SQL-Informationen der Jobinformationen an, deren Speichernutzung den geschätzten Speicher überschreitet, wobei datid die OID der Datenbank angibt, app_name den Anwendungsnamen angibt und query_string die Abfrage-sql angibt.

----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.

Die obigen Informationen weisen darauf hin, dass der Speicherkontext das Limit überschreitet. In der Abfrage Nr. 76279718689098154 beträgt der maximale Wert des voreingestellten Speicherkontextwerts 989 MB, und tatsächlich werden 1059 MB verwendet.

2) Erreichen der Speicherbegrenzung des Betriebssystems

Wenn die Speichernutzung von GaussDB der entsprechenden Parametergrenze in GUC entspricht, der verfügbare Speicher des Betriebssystems jedoch nicht ausreicht, wird eine Protokollmeldung ähnlich der in 1.1 angezeigt, und das Format ist wie folgt

----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

Darunter ist os_totalmem der Gesamtspeicher im aktuellen Betriebssystem, also die Gesamtinformation im „free“-Befehl. os_freemem ist der verfügbare Speicher im aktuellen Betriebssystem, d. h. die freie Information im "free"-Befehl.

Wenn der anzufordernde Arbeitsspeicher beim „Allokieren von %ld Bytes“ im ersten Protokoll größer ist als das Element „os_freemem“ im dritten Protokoll und die Datenbank ohne andere Anomalien ausgeführt werden kann, ist dies wie erwartet, was darauf hinweist, dass der Betriebssystemspeicher vorhanden ist unzureichend.

2. Fragen Sie für die Speichernutzung jeder Instanz pgxc_total_memory_detail ab

Nachdem der Speicherfehler gemeldet wurde, wird der von der Anweisung verwendete Speicher freigegeben. Zu diesem Zeitpunkt kann die Anweisung, die viel Speicher belegt hat, aufgrund der Fehlermeldung verloren gehen, und die Abfragespeicheransicht kann nicht abgefragt werden.

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;

Wenn diese Ansicht abgefragt wird, wird möglicherweise gemeldet, dass aufgrund von unzureichendem Arbeitsspeicher vorübergehend kein Speicher verfügbar ist, wodurch die Ansicht nicht verfügbar ist. In diesem Fall müssen Sie disable_memory_protect auf „off“ setzen.

set disable_memory_protect=off; Danach wird beim Abfragen der Ansicht kein Fehler mehr gemeldet.

Über die obige Ansicht können Sie feststellen, welcher Knoten im Cluster eine anormale Speichernutzung aufweist, und dann eine Verbindung zu diesem Knoten herstellen, um den problematischen Speicherkontext über die Ansicht pv_session_memory_detail zu finden.

SELECT * FROM pv_session_memory_detail ORDER BY totalsize desc LIMIT 100;

In Kombination mit der pg_stat_activity-Ansicht können Sie herausfinden, welche Anweisung den meisten Memcontext verwendet.

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;

Notfallwiederherstellung

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

2. Analyse von Szenarien mit hoher Speicherauslastung

1. Zu viele Leerlaufverbindungen führen zu Speicherverbrauch

Bestätigen Sie zuerst, welche Instanz eine hohe Speicherauslastung hat. Die Bestätigungsmethode ist wie oben, um pgxc_total_memory_detail abzufragen, und stellen Sie dann eine Verbindung zu cn oder dn her, um die folgende SQL abzufragen

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;

Wenn die Gesamtgröße im Ruhezustand in der obigen Abbildung viel Speicher beansprucht, können Sie versuchen, die Ruheverbindungen im Ruhezustand zu bereinigen, um den Speicher freizugeben

Lösung: Leere Verbindungen im Ruhezustand bereinigen

CLEAN CONNECTION TO ALL FORCE FOR DATABASE xxxx;

clean connection kann nur die inaktiven Verbindungen bereinigen, deren in_used-Zustand f in pg_pooler_status ist, aber nicht die Verbindungen, deren in_used-Zustand t ist. In_used ist t. Im Allgemeinen wird die pbe-Anweisung ausgeführt und die inaktiven Verbindungen von cn und dn können nicht ausgeführt werden freigegeben.

Wenn die obige Methode nicht bereinigt werden kann, können Sie nur versuchen, die Verbindung zwischen cn und dem Client zu bereinigen und dann clean connection ausführen, um die Verbindung zwischen cn und dn zu bereinigen. Sie können versuchen, eine inaktive Verbindung auf cn zu finden. dieser Vorgang unterbricht cn Um sich mit dem Client zu verbinden, müssen Sie mit dem Client bestätigen, ob er ausgeführt werden kann

select 'execute direct on ('||coorname||') ''select pg_terminate_backend('||pid||')'';' from pgxc_stat_activity where usename not in ('Ruby', 'omm') and state='idle';

Führt die Ergebnisse von select nacheinander aus.

2. Die Anweisung belegt zu viel Speicher Wenn die erste Anweisung im ersten Schritt die Anweisung im aktiven Zustand abfragt und viel Speicher belegt, bedeutet dies, dass die Speicherbelegung der auszuführenden Anweisung durch zu viel Speicher verursacht wird.

Fragen Sie die folgende Anweisung ab, um die Anweisung zu finden, die viel Speicher beansprucht

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;

Nachdem Sie die Anweisung gefunden haben, suchen und beenden Sie die abnormale SQL auf dem entsprechenden cn gemäß der query_id

3. dynamic_used_shrctx verbraucht mehr Speicher

dynamic_used_shrctx ist der Speicher, der vom gemeinsam genutzten Speicherkontext verwendet wird, der ebenfalls durch MemoryContext geteilt und von Threads gemeinsam genutzt wird. Ansicht durch pg_shared_memory_detail-Ansicht

select * from pg_shared_memory_detail order by totalsize desc limit 10;

Im Allgemeinen bezieht sich die Zuordnung des Shared-Memory-Kontexts auf die Anweisung. Der Kontextname hat die Thread-Nummer oder query_id, und die anormale SQL wird gemäß der query_id oder Thread-Nummer überprüft und beendet. Außerdem ist der Shared-Memory-Kontext im Allgemeinen der Speicher, der von jedem Modul im Kernel verwendet wird, wie zum Beispiel topsql. Es ist zu prüfen, ob die Speichernutzung angemessen ist, und der Freigabemechanismus.

4. In der Speicheransicht pv_total_memory_detail, dynamic_used_memory > max_dynamic_memory

1) Wenn der GUC-Parameter disable_memory_protect eingeschaltet ist

2) Beim Zuweisen von Speicher ist debug_query_id 0

3) Wenn der Kernel Schlüsselcodesegmente ausführt

4) Speicherzuordnung innerhalb des Kernel-Postmaster-Threads

5) In der Transaktions-Rollback-Phase

Die oben genannten Situationen stellen allesamt Sonderbehandlungen des Kernels dar, um sicherzustellen, dass die Operation nicht unterbrochen werden kann Theoretisch wird der Speicher (dynamic_used_memory), der von der vom Benutzer ausgeführten SQL verwendet wird, den Speicher von max_dynamic_memory nicht in großem Umfang überschreiten.

 

Klicken Sie hier, um zu folgen und zum ersten Mal etwas über die neuen Technologien von Huawei Cloud zu erfahren~

{{o.name}}
{{m.name}}

Supongo que te gusta

Origin my.oschina.net/u/4526289/blog/8591169
Recomendado
Clasificación