Quandu un servitore di basa di dati si abbanduneghja inaspettatamente in Linux, avete bisognu di truvà u mutivu. Ci pò esse parechje ragioni. Per esempiu, SIGSEGV - fallimentu per un bug in u servitore backend. Ma questu hè raru. A maiò spessu, avete solu scappatu di spaziu di discu o memoria. S'ellu ùn ci hè micca spaziu di discu, ci hè solu un modu - liberate u spaziu è ripigliate a basa di dati.
Assassinu fora di memoria
Quandu un servitore o un prucessu esce da a memoria, Linux offre 2 suluzioni: crash tuttu u sistema o finisce u prucessu (applicazione) chì manghja memoria. Hè megliu, sicuru, per finisce u prucessu è salvà u OS da crashing. In poche parole, Out-Of-Memory Killer hè un prucessu chì uccide una applicazione per salvà u kernel da crashing. Hè sacrificatu l'applicazione per mantene u SO in esecuzione. Discutemu prima cumu funziona OOM è cumu cuntrullà, è poi vede cumu OOM Killer decide quale applicazione finisce.
Unu di i travaglii principali di Linux hè di assignà memoria à i prucessi quandu u dumandanu. Di genere, un prucessu o applicazione richiede memoria da u SO, ma ùn l'utiliza micca cumplettamente. Se u sistema operativu dà memoria à tutti quelli chì a dumandanu, ma ùn hà micca intenzione di usà, assai prestu a memoria escerà è u sistema falla. Per evitari, u sistema operativu riserva memoria per u prucessu, ma ùn libera micca veramente. A memoria hè attribuita solu quandu un prucessu hà daveru aduprà. Succede chì u SO ùn hà micca memoria libera, ma assigna memoria à un prucessu, è quandu un prucessu ne hà bisognu, u SO l'assigna si pò. U svantaghju hè chì qualchì volta l'OS riserva memoria, ma à u mumentu ghjustu ùn ci hè micca memoria libera, è u sistema crashs. OOM ghjoca un rolu impurtante in questu scenariu è finisce i prucessi per prevene u kernel da u panicu. Quandu un prucessu PostgreSQL hè furzatu à finisce, un messagiu appare in u logu:
Out of Memory: Killed process 12345 (postgres).
Se u sistema hè pocu in memoria è ùn pò micca esse liberatu, a funzione hè chjamata out_of_memory
. À questu stadiu, hà solu una cosa da fà - compie unu o più prucessi. OOM-killer deve finisce immediatamente u prucessu o pò aspittà? Ovviamente, quandu out_of_memory hè chjamatu, hè dovutu à aspittà per una operazione I / O o paginazione à u discu. Dunque, l'assassinu OOM deve prima eseguisce cuntrolli è, basatu annantu à elli, decide chì u prucessu deve esse terminatu. Se tutti i cuntrolli sottu sò pusitivi, OOM finisce u prucessu.
Selezzione di prucessu
Quandu a memoria scorri, a funzione hè chjamata out_of_memory()
. Hà una funzione select_bad_process()
, chì riceve una valutazione da a funzione badness()
. U "peghju" prucessu serà destinatu. Funzione badness()
sceglie un prucessu secondu certi reguli.
- U kernel hà bisognu di qualchì memoria minima per ellu stessu.
- Avete bisognu di liberà assai memoria.
- Ùn ci hè bisognu di finisce i prucessi chì utilizanu pocu memoria.
- I prucessi minimi anu da esse cumpletati.
- Algoritmi cumplessi chì aumentanu e probabilità di cumpiimentu per quelli prucessi chì l'utilizatore stessu vole compie.
Dopu avè finitu tutti questi cuntrolli, OOM esamina u puntuatu (oom_score
). L'OOM assigna oom_score
ogni prucessu, è poi multiplica stu valore da a quantità di memoria. I prucessi cù valori più grande sò più probabili di fallu vittime di l'OOM Killer. I prucessi assuciati cù l'usu root anu un puntuatu più bassu è sò menu prubabile di esse furzati à finisce.
postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
3813
(1 row)
L'ID di u prucessu di Postgres hè 3813, cusì in un altru shell hè pussibule di ottene u puntuazione utilizendu stu paràmetru di kernel. oom_score
:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2
Se ùn vulete micca chì OOM-Killer uccida u prucessu, ci hè una altra opzione di kernel: oom_score_adj
. Aghjunghjite un grande valore negativu per riduce e probabilità di compie un prucessu chì valore.
sudo echo -100 > /proc/3813/oom_score_adj
Per stabilisce un valore oom_score_adj
, stabilisce OOMScoreAdjust in u bloccu di serviziu:
[Service]
OOMScoreAdjust=-1000
O aduprà oomprotect
in una squadra rcctl
.
rcctl set <i>servicename</i> oomprotect -1000
Forza a terminazione di un prucessu
Quandu unu o più prucessi sò digià sceltu, OOM-Killer chjama a funzione oom_kill_task()
. Sta funzione manda un signalu di terminazione à u prucessu. In casu di mancanza di memoria oom_kill()
Chjama sta funzione per mandà un signalu SIGKILL à u prucessu. Un missaghju hè scrittu à u logu di u kernel.
Out of Memory: Killed process [pid] [name].
Cumu cuntrullà OOM-Killer
In Linux, pudete attivà o disattivà OOM-Killer (ancu se l'ultimu ùn hè micca cunsigliatu). Per attivà o disattivà aduprà u paràmetru vm.oom-kill
. Per attivà OOM-Killer in runtime, eseguite u cumandimu sysctl
.
sudo -s sysctl -w vm.oom-kill = 1
Per disattivà OOM-Killer, specificate u valore 0 in u listessu cumandamentu:
sudo -s sysctl -w vm.oom-kill = 0
U risultatu di sta cumanda ùn serà micca salvatu per sempre, ma solu finu à u primu reboot. Sè avete bisognu di più persistenza, aghjunghje sta linea à u schedariu /etc/sysctl.conf
:
echo vm.oom-kill = 1 >>/etc/sysctl.conf
Un altru modu per attivà è disattivà hè di scrive una variabile panic_on_oom
. U valore pò sempre esse verificatu /proc
.
$ cat /proc/sys/vm/panic_on_oom
0
Se mette u valore à 0, quandu a memoria si esaurisce, ùn ci sarà micca u panicu di u kernel.
$ echo 0 > /proc/sys/vm/panic_on_oom
Se mette u valore à 1, quandu a memoria si esaurisce, un panicu di u kernel succede.
echo 1 > /proc/sys/vm/panic_on_oom
OOM-Killer ùn pò micca solu esse attivatu è disattivatu. Avemu digià dettu chì Linux pò riservà più memoria per i prucessi di ciò chì hè dispunibule senza in realtà l'assignà, è questu cumpurtamentu hè cuntrullatu da un paràmetru di kernel Linux. A variàbile hè rispunsevule per questu vm.overcommit_memory
.
Pudete specificà i seguenti valori per questu:
0: U kernel stessu decide s'ellu riservà troppu memoria. Questu hè u predefinitu in a maiò parte di e versioni di Linux.
1: U kernel riservà sempre memoria extra. Questu hè risicatu, perchè a memoria pò esce, perchè, assai prubabilmente, un ghjornu i prucessi l'avete bisognu.
2: u kernel ùn riservà più memoria di quella specificata in u paràmetru overcommit_ratio
.
Cù stu paràmetru, specificate u percentualità di memoria chì hè permessa di esse riservata. S'ellu ùn ci hè micca spaziu per questu, ùn hè micca attribuita memoria, è a riservazione serà denegata. Questa hè l'opzione più sicura cunsigliata per PostgreSQL. OOM-Killer hè affettatu da un altru elementu - a capacità di scambià, chì hè cuntrullata da a variabile cat /proc/sys/vm/swappiness
. Questi valori dicenu à u kernel cumu gestisce a paginazione. U più altu hè u valore, u menu prubabile hè chì OOM finisce u prucessu, ma per via di l'operazioni I/O hà un impattu negativu nantu à a basa di dati. E vice versa - u più bassu u valore, u più altu a probabilità di intervenzione OOM-Killer, ma u rendiment di a basa di dati hè ancu più altu. U valore predeterminatu hè 60, ma se tutta a basa di dati si mette in memoria, hè megliu stabilisce u valore à 1.
Risultati
Ùn lasciate micca chì u "assassinu" in OOM-Killer ti spaventa. In questu casu, l'assassinu serà u salvatore di u vostru sistema. Hè "uccide" i prucessi peghju è salva u sistema da crashing. Per evità di avè aduprà OOM-Killer per finisce PostgreSQL, impostate à vm.overcommit_memory
valore 2. Questu ùn guarantisci micca chì OOM-Killer ùn deve micca intervene, ma riducerà a probabilità di furzà u prucessu PostgreSQL per finisce.
Source: www.habr.com