
Когато е в Linux Сървърът на базата данни се прекратява неочаквано и трябва да се определи причината. Може да има няколко причини. Например, SIGSEGV — повреда поради грешка в бекенд сървъра. Но това е рядкост. Най-често просто ви липсва дисково пространство или памет. Ако ви свърши дисковото пространство, има само един изход - освободете място и рестартирайте базата данни.
Убиец на липса на памет
Когато ти сървър или процесът изчерпва паметта, Linux „Убиецът на неуспех при липса на памет“ (Out-Of-Memory Killer) предлага две решения: срив на цялата система или прекратяване на процеса (приложението), който изразходва памет. Разбира се, по-добре е да се прекрати процесът и да се спаси операционната система от срив. Накратко, „Убиецът на неуспех при липса на памет“ е процес, който прекратява приложение, за да спаси ядрото от срив. Той жертва приложението, за да поддържа операционната система да работи. Нека първо обсъдим как работи OOM и как да го контролираме, а след това да разгледаме как „Убиецът на неуспех при липса на памет“ решава кои приложения да прекрати.
Една от основните задачи 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() избира процес според определени правила.
- Ядрото се нуждае от минимална памет за себе си.
- Трябва да освободите много памет.
- Няма нужда да прекратявате процеси, които използват малко памет.
- Трябва да бъдат завършени минимални процеси.
- Комплексни алгоритми, които увеличават шансовете за завършване на тези процеси, които самият потребител иска да завърши.
След като завърши всички тези проверки, 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_oomOOM-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
