Конфигуриране на убиец на липса на памет на Linux за PostgreSQL

Конфигуриране на убиец на липса на памет на Linux за PostgreSQL

Когато сървър на база данни се затвори неочаквано в Linux, трябва да намерите причината. Може да има няколко причини. Например, SIGSEGV — повреда поради грешка в бекенд сървъра. Но това е рядкост. Най-често просто ви липсва дисково пространство или памет. Ако ви свърши дисковото пространство, има само един изход - освободете място и рестартирайте базата данни.

Убиец на липса на памет

Когато на сървър или процес свърши паметта, Linux предлага 2 решения: срив на цялата система или прекратяване на процеса (приложението), който изяжда памет. По-добре е, разбира се, да прекратите процеса и да спасите операционната система от срив. С две думи, Out-Of-Memory Killer е процес, който убива приложение, за да спаси ядрото от срив. Той жертва приложението, за да поддържа операционната система работеща. Нека първо обсъдим как работи OOM и как да го контролираме, а след това да видим как OOM Killer решава кое приложение да прекрати.

Една от основните задачи на Linux е да разпределя памет за процеси, когато те я поискат. Обикновено процес или приложение изисква памет от операционната система, но не я използва напълно. Ако операционната система раздава памет на всеки, който я поиска, но няма намерение да я използва, много скоро паметта ще свърши и системата ще се провали. За да избегне това, ОС запазва памет за процеса, но всъщност не го освобождава. Паметта се разпределя само когато даден процес действително ще я използва. Случва се ОС да няма свободна памет, но заделя памет на процес и когато процесът има нужда от нея, ОС я заделя, ако може. Недостатъкът е, че понякога операционната система резервира памет, но в подходящия момент няма свободна памет и системата се срива. OOM играе важна роля в този сценарий и прекратява процесите, за да предотврати паниката на ядрото. Когато PostgreSQL процес бъде принуден да прекрати, в дневника се появява съобщение:

Out of Memory: Killed process 12345 (postgres).

Ако на системата липсва памет и тя не може да бъде освободена, функцията се извиква out_of_memory. На този етап й остава само едно нещо - да завърши един или повече процеси. Трябва ли OOM-killer да прекрати процеса веднага или може да изчака? Очевидно, когато се извиква out_of_memory, това се дължи на изчакване на I/O операция или пейджинг на диск. Следователно убиецът на OOM трябва първо да извърши проверки и въз основа на тях да реши, че процесът трябва да бъде прекратен. Ако всички проверки по-долу са положителни, OOM ще прекрати процеса.

Избор на процес

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

  1. Ядрото се нуждае от минимална памет за себе си.
  2. Трябва да освободите много памет.
  3. Няма нужда да прекратявате процеси, които използват малко памет.
  4. Трябва да бъдат завършени минимални процеси.
  5. Комплексни алгоритми, които увеличават шансовете за завършване на тези процеси, които самият потребител иска да завърши.

След като завърши всички тези проверки, OOM проверява резултата (oom_score). ООМ назначава oom_score всеки процес и след това умножава тази стойност по количеството памет. Процесите с по-големи стойности е по-вероятно да станат жертва на OOM Killer. Процесите, свързани с 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

Добавяне на нов коментар