Konfiguriranje ubojice van memorije na Linuxu za PostgreSQL

Konfiguriranje ubojice van memorije na Linuxu za PostgreSQL

Kada se poslužitelj baze podataka neočekivano zatvori u Linuxu, morate pronaći razlog. Razloga može biti nekoliko. Na primjer, SIGSEGV — neuspjeh zbog greške u backend serveru. Ali ovo je retko. Najčešće vam jednostavno ponestane prostora na disku ili memorije. Ako vam ponestane prostora na disku, postoji samo jedan izlaz - oslobodite prostor i ponovo pokrenite bazu podataka.

Ubica bez memorije

Kada serveru ili procesu ponestane memorije, Linux nudi 2 rješenja: srušiti cijeli sistem ili prekinuti proces (aplikaciju) koji jede memoriju. Bolje je, naravno, prekinuti proces i spasiti OS od pada. Ukratko, Out-Of-Memory Killer je proces koji ubija aplikaciju kako bi spasio kernel od pada. On žrtvuje aplikaciju da bi OS nastavio da radi. Hajde da prvo razgovaramo o tome kako OOM radi i kako ga kontrolisati, a zatim da vidimo kako OOM Killer odlučuje koju aplikaciju da ugasi.

Jedan od glavnih zadataka Linuxa je da dodijeli memoriju procesima kada to zatraže. Obično proces ili aplikacija zahtijeva memoriju od OS-a, ali je ne koristi u potpunosti. Ako OS izda memoriju svima koji je traže, a ne planiraju je koristiti, vrlo brzo će memorija ponestati i sistem će otkazati. Da bi se to izbjeglo, OS rezervira memoriju za proces, ali je zapravo ne oslobađa. Memorija se dodjeljuje samo kada će je proces zapravo koristiti. Dešava se da OS nema slobodnu memoriju, ali dodeljuje memoriju procesu, a kada je nekom procesu potrebna, OS je dodeljuje ako može. Loša strana je što ponekad OS rezerviše memoriju, ali u pravom trenutku nema slobodne memorije i sistem se ruši. OOM igra važnu ulogu u ovom scenariju i prekida procese kako bi spriječio kernel od panike. Kada je PostgreSQL proces prisiljen da se prekine, u dnevniku se pojavljuje poruka:

Out of Memory: Killed process 12345 (postgres).

Ako sistemu nema dovoljno memorije i ne može se osloboditi, poziva se funkcija out_of_memory. U ovoj fazi, preostaje joj samo jedna stvar - završiti jedan ili više procesa. Treba li OOM-killer odmah prekinuti proces ili može pričekati? Očigledno, kada se pozove out_of_memory, to je zbog čekanja na I/O operaciju ili stranica na disk. Stoga, OOM ubica mora prvo izvršiti provjere i na osnovu njih odlučiti da proces treba prekinuti. Ako su sve donje provjere pozitivne, OOM će prekinuti proces.

Odabir procesa

Kada memorija ponestane, funkcija se poziva out_of_memory(). Ima funkciju select_bad_process(), koji prima ocjenu od funkcije badness(). "Najgori" proces će biti ciljani. Funkcija badness() odabire proces prema određenim pravilima.

  1. Kernelu je potrebna minimalna memorija za sebe.
  2. Morate osloboditi mnogo memorije.
  3. Nema potrebe za prekidom procesa koji koriste malo memorije.
  4. Minimalni procesi moraju biti završeni.
  5. Složeni algoritmi koji povećavaju šanse za završetak za one procese koje sam korisnik želi da završi.

Nakon što je završio sve ove provjere, OOM ispituje rezultat (oom_score). OOM imenuje oom_score svaki proces, a zatim množi ovu vrijednost sa količinom memorije. Veća je vjerovatnoća da će procesi s većim vrijednostima postati žrtva OOM Killera. Procesi povezani sa root korisnikom imaju niži rezultat i manja je vjerovatnoća da će biti prisiljeni prekinuti.

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

ID Postgres procesa je 3813, tako da je u drugoj ljusci moguće dobiti rezultat koristeći ovaj parametar kernela oom_score:

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

Ako ne želite da OOM-Killer uopće uništi proces, postoji još jedna opcija kernela: oom_score_adj. Dodajte veliku negativnu vrijednost da smanjite šanse za dovršetak procesa koji cijenite.

sudo echo -100 > /proc/3813/oom_score_adj

Za postavljanje vrijednosti oom_score_adj, postavite OOMScoreAdjust u servisni blok:

[Service]
OOMScoreAdjust=-1000

Ili koristite oomprotect u timu rcctl.

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

Prisilno okončanje procesa

Kada je jedan ili više procesa već odabrano, OOM-Killer poziva funkciju oom_kill_task(). Ova funkcija šalje signal završetka procesu. U slučaju nedostatka memorije oom_kill() Poziva ovu funkciju da pošalje SIGKILL signal procesu. Poruka se upisuje u dnevnik kernela.

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

Kako kontrolisati OOM-Killer

Na Linuxu možete omogućiti ili onemogućiti OOM-Killer (iako se ovo drugo ne preporučuje). Da biste omogućili ili onemogućili, koristite parametar vm.oom-kill. Da biste omogućili OOM-Killer u vrijeme izvođenja, pokrenite naredbu sysctl.

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

Da biste onemogućili OOM-Killer, navedite vrijednost 0 u istoj naredbi:

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

Rezultat ove naredbe neće biti sačuvan zauvijek, već samo do prvog ponovnog pokretanja. Ako vam treba više upornosti, dodajte ovaj red u datoteku /etc/sysctl.conf:

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

Drugi način za omogućavanje i onemogućavanje je pisanje varijable panic_on_oom. Vrijednost se uvijek može provjeriti /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Ako postavite vrijednost na 0, onda kada ponestane memorije, neće biti kernel panike.

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

Ako postavite vrijednost na 1, onda kada ponestane memorije, pojavit će se panika kernela.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer se ne može samo uključiti i isključiti. Već smo rekli da Linux može rezervirati više memorije za procese nego što je dostupno bez stvarnog dodjeljivanja, a ovo ponašanje kontrolira parametar Linux kernela. Za to je odgovorna varijabla vm.overcommit_memory.

Za njega možete odrediti sljedeće vrijednosti:

0: Kernel sam odlučuje da li će rezervisati previše memorije. Ovo je zadana postavka u većini verzija Linuxa.
1: Kernel će uvijek rezervisati dodatnu memoriju. Ovo je rizično, jer memorija može ponestati, jer će, najvjerovatnije, jednog dana procesi to zahtijevati.
2: kernel neće rezervisati više memorije nego što je navedeno u parametru overcommit_ratio.

Ovim parametrom određujete postotak memorije kojoj je dozvoljeno da bude prekomjerno rezervirana. Ako za to nema mjesta, memorija se ne dodjeljuje, a rezervacija će biti odbijena. Ovo je najsigurnija opcija preporučena za PostgreSQL. OOM-Killer je pod utjecajem još jednog elementa - mogućnosti zamjene, koji je kontroliran promjenljivom cat /proc/sys/vm/swappiness. Ove vrijednosti govore kernelu kako da rukuje stranicama. Što je veća vrijednost, manja je vjerovatnoća da će OOM prekinuti proces, ali zbog I/O operacija ima negativan utjecaj na bazu podataka. I obrnuto – što je niža vrijednost, veća je vjerovatnoća intervencije OOM-Killer-a, ali je i performansa baze podataka veća. Zadana vrijednost je 60, ali ako cijela baza podataka stane u memoriju, bolje je postaviti vrijednost na 1.

Ishodi

Ne dozvolite da vas "ubica" u OOM-Killeru uplaši. U ovom slučaju, ubica će biti spasilac vašeg sistema. On "ubija" najgore procese i spašava sistem od pada. Da biste izbjegli korištenje OOM-Killera za ukidanje PostgreSQL-a, postavite na vm.overcommit_memory vrijednost 2. Ovo ne garantuje da OOM-Killer neće morati intervenirati, ali će smanjiti vjerovatnoću prisiljavanja PostgreSQL procesa da se prekine.

izvor: www.habr.com

Dodajte komentar