Поставување без меморија убиец во Linux за PostgreSQL

Поставување без меморија убиец во Linux за PostgreSQL

Кога серверот за бази на податоци неочекувано ќе престане во Linux, треба да ја пронајдете причината. Може да има неколку причини. На пример, СИГСЕГВ — неуспех поради грешка во заднинскиот сервер. Но, ова е ретко. Најчесто, едноставно останувате без простор на дискот или меморија. Ако ви снема простор на дискот, има само еден излез - ослободи простор и рестартирајте ја базата на податоци.

Убиец без меморија

Кога на серверот или процес му снемува меморија, Linux нуди 2 решенија: да го прекине целиот систем или да го прекине процесот (апликацијата) што ја јаде меморијата. Подобро е, се разбира, да се прекине процесот и да се спаси ОС од паѓање. Накратко, Out-Of-Memory Killer е процес кој ја убива апликацијата за да го спаси кернелот од паѓање. Ја жртвува апликацијата за да продолжи да работи ОС. Ајде прво да разговараме како функционира OOM и како да го контролираме, а потоа да видиме како OOM Killer одлучува која апликација да ја прекине.

Една од главните задачи на Linux е да ја распредели меморијата на процесите кога ќе ја побараат. Обично, процес или апликација бара меморија од ОС, но не ја користи целосно. Ако оперативниот систем им дава меморија на сите што ја бараат, но не планираат да ја користат, многу брзо меморијата ќе се потроши и системот ќе пропадне. За да се избегне ова, ОС резервира меморија за процесот, но всушност не ја ослободува. Меморијата се доделува само кога некој процес всушност ќе ја користи. Се случува оперативниот систем да нема слободна меморија, но да доделува меморија на процес и кога на некој процес му треба, ОС ја доделува ако може. Недостаток е што понекогаш ОС резервира меморија, но во вистинско време нема слободна меморија и системот паѓа. OOM игра важна улога во ова сценарио и ги прекинува процесите за да спречи паника на кернелот. Кога еден процес на PostgreSQL е принуден да прекине, во дневникот се појавува порака:

Out of Memory: Killed process 12345 (postgres).

Ако меморијата на системот е слаба и не може да се ослободи, се повикува функцијата out_of_memory. Во оваа фаза, ѝ останува само една работа - да заврши еден или повеќе процеси. Дали OOM-убиецот треба веднаш да го прекине процесот или може да почека? Очигледно, кога се повикува out_of_memory, тоа се должи на чекање за I/O операција или страничење на дискот. Затоа, убиецот на ООМ мора прво да изврши проверки и врз основа на нив да одлучи дека процесот треба да се прекине. Ако сите проверки подолу се позитивни, OOM ќе го прекине процесот.

Процес на избор

Кога меморијата ќе истече, функцијата се повикува out_of_memory(). Има функција select_bad_process(), кој добива оценка од функцијата badness(). „Најлошиот“ процес ќе биде насочен. Функција badness() избира процес според одредени правила.

  1. На кернелот му треба минимална меморија за себе.
  2. Треба да ослободите многу меморија.
  3. Нема потреба да се прекинуваат процесите што користат мала меморија.
  4. Треба да се завршат минимум процеси.
  5. Комплексни алгоритми кои ги зголемуваат шансите за завршување за оние процеси кои самиот корисник сака да ги заврши.

Откако ги заврши сите овие проверки, ООМ го испитува резултатот (oom_score). ООМ назначува oom_score секој процес, а потоа ја множи оваа вредност со количината на меморија. Поверојатно е дека процесите со поголеми вредности ќе станат жртви на убиецот на ООМ. Процесите поврзани со корисникот на root имаат помал резултат и помала е веројатноста да бидат принудени да прекинат.

postgres=# SELECT pg_backend_pid();
pg_backend_pid 
----------------
    3813
(1 row)

ИД на процесот на Postgres е 3813, така што во друга школка е можно да се добие резултатот користејќи го овој параметар на јадрото oom_score:

vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2

Ако воопшто не сакате OOM-Killer да го убие процесот, постои друга опција за јадрото: oom_score_adj. Додадете голема негативна вредност за да ги намалите шансите да го завршите процесот што го цените.

sudo echo -100 > /proc/3813/oom_score_adj

За да поставите вредност oom_score_adj, поставете OOMScoreAdjust во сервисниот блок:

[Service]
OOMScoreAdjust=-1000

Или користете oomprotect во тим rcctl.

rcctl set <i>servicename</i> oomprotect -1000

Присилно завршување на процес

Кога еден или повеќе процеси се веќе избрани, OOM-Killer ја повикува функцијата oom_kill_task(). Оваа функција испраќа сигнал за завршување на процесот. Во случај на недостаток на меморија oom_kill() Ја повикува оваа функција за да испрати сигнал SIGKILL до процесот. Во дневникот на јадрото се пишува порака.

Out of Memory: Killed process [pid] [name].

Како да се контролира OOM-Killer

На Linux, можете да го вклучите или оневозможите OOM-Killer (иако второто не се препорачува). За да овозможите или исклучите, користете го параметарот vm.oom-kill. За да овозможите OOM-Killer при извршување, извршете ја командата sysctl.

sudo -s sysctl -w vm.oom-kill = 1

За да го исклучите OOM-Killer, наведете ја вредноста 0 во истата команда:

sudo -s sysctl -w vm.oom-kill = 0

Резултатот од оваа команда нема да се зачува засекогаш, туку само до првото рестартирање. Ако ви треба повеќе упорност, додајте ја оваа линија во датотеката /etc/sysctl.conf:

echo vm.oom-kill = 1 >>/etc/sysctl.conf

Друг начин да се овозможи и оневозможи е да се напише променлива panic_on_oom. Вредноста секогаш може да се провери /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Ако ја поставите вредноста на 0, тогаш кога меморијата ќе истече, нема да има паника во јадрото.

$ echo 0 > /proc/sys/vm/panic_on_oom

Ако ја поставите вредноста на 1, тогаш кога меморијата ќе истече, ќе се појави паника во јадрото.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer не само што може да се вклучи и исклучи. Веќе рековме дека Linux може да резервира повеќе меморија за процеси отколку што е достапно без всушност да ја додели, и ова однесување е контролирано од параметар на кернелот на Linux. Променливата е одговорна за ова vm.overcommit_memory.

Можете да ги наведете следните вредности за него:

0: Самиот кернел одлучува дали да резервира премногу меморија. Ова е стандардно на повеќето верзии на Linux.
1: Јадрото секогаш ќе резервира дополнителна меморија. Ова е ризично, бидејќи меморијата може да истече, бидејќи, најверојатно, еден ден процесите ќе го бараат тоа.
2: кернелот нема да резервира повеќе меморија отколку што е наведено во параметарот overcommit_ratio.

Со овој параметар, го одредувате процентот на меморија што е дозволено да биде пререзервирана. Ако нема место за тоа, не се доделува меморија, а резервацијата ќе биде одбиена. Ова е најбезбедната опција препорачана за PostgreSQL. OOM-Killer е под влијание на друг елемент - способноста за замена, која е контролирана од променливата cat /proc/sys/vm/swappiness. Овие вредности му кажуваат на кернелот како да се справи со страничење. Колку е поголема вредноста, толку е помала веројатноста дека OOM ќе го прекине процесот, но поради I/O операциите тоа навистина има негативно влијание врз базата на податоци. И обратно - колку е помала вредноста, толку е поголема веројатноста за интервенција на OOM-Killer, но перформансите на базата на податоци се исто така повисоки. Стандардната вредност е 60, но ако целата база на податоци се вклопува во меморијата, подобро е да ја поставите вредноста на 1.

Резултатите од

Не дозволувајте „убиецот“ во OOM-Killer да ве плаши. Во овој случај, убиецот ќе биде спасител на вашиот систем. Ги „убива“ најлошите процеси и го спасува системот од паѓање. За да не мора да користите OOM-Killer за да го прекинете PostgreSQL, поставете го на vm.overcommit_memory вредност 2. Ова не гарантира дека OOM-Killer нема да мора да интервенира, но ќе ја намали веројатноста да се принуди процесот на PostgreSQL да прекине.

Извор: www.habr.com

Додадете коментар