
Ne zaman Linux Veritabanı sunucusu beklenmedik bir şekilde kapanıyor ve bunun nedeninin belirlenmesi gerekiyor. Birkaç nedeni olabilir. Örneğin, SIGSEGV — arka uç sunucusundaki bir hatadan kaynaklanan arıza. Ancak bu nadirdir. Çoğu zaman, disk alanınız veya belleğiniz biter. Disk alanınız biterse tek çıkış yolu vardır; alanı boşaltmak ve veritabanını yeniden başlatmak.
Yetersiz Bellek Katili
Ne zaman sunucu veya işlem bellek yetersizliğinden dolayı başarısız olur, Linux Bellek Yetersizliği Katili (Out-Of-Memory Killer) iki çözüm sunar: tüm sistemi çökertmek veya belleği tüketen işlemi (uygulamayı) sonlandırmak. Elbette, işlemi sonlandırmak ve işletim sisteminin çökmesini önlemek daha iyidir. Kısaca, Bellek Yetersizliği Katili, çekirdeğin çökmesini önlemek için bir uygulamayı sonlandıran bir işlemdir. İşletim sisteminin çalışmaya devam etmesi için uygulamayı feda eder. Öncelikle OOM'nin nasıl çalıştığını ve nasıl kontrol edileceğini ele alalım, ardından OOM Katilinin hangi uygulamaları sonlandıracağına nasıl karar verdiğine bakalım.
Ana görevlerden biri Linux — İşlemler talep ettiğinde onlara bellek tahsis edin. Tipik olarak, bir işlem veya uygulama işletim sisteminden bellek talep eder ancak bunu tamamen kullanmaz. İşletim sistemi, talep eden herkese bellek tahsis eder ancak bunu kullanmayı planlamazsa, sistem hızla bellek yetersizliği sorunuyla karşılaşır ve sistem çöker. Bunu önlemek için, işletim sistemi bir işlem için bellek ayırır ancak bunu fiilen tahsis etmez. Bellek yalnızca bir işlem gerçekten kullanmayı amaçladığında tahsis edilir. Bazen işletim sisteminin boş belleği yoktur, ancak bir işleme bellek tahsis eder ve işlem buna ihtiyaç duyduğunda, işletim sistemi bunu yapabiliyorsa tahsis eder. Dezavantajı, bazen işletim sisteminin bellek ayırması, ancak ihtiyaç duyulduğunda boş bellek olmaması ve bunun da sistem çökmesine neden olmasıdır. Bellek yetersizliği (OOM), bu senaryoda çekirdeğin paniklemesini önlemek için işlemleri sonlandırarak önemli bir rol oynar. PostgreSQL işlemi zorla sonlandırıldığında, günlükte aşağıdaki mesaj görünür:
Out of Memory: Killed process 12345 (postgres).Sistemin belleği azsa ve boşaltılamıyorsa işlev çağrılır. out_of_memory. Bu aşamada yapması gereken tek şey kaldı; bir veya daha fazla işlemi tamamlamak. OOM-killer süreci hemen sonlandırmalı mı yoksa bekleyebilir mi? Açıkçası, out_of_memory çağrıldığında bunun nedeni bir G/Ç işleminin veya diske sayfalamanın beklenmesidir. Bu nedenle, OOM katilinin öncelikle kontroller yapması ve bunlara dayanarak sürecin sonlandırılması gerektiğine karar vermesi gerekir. Aşağıdaki kontrollerin tümü olumluysa OOM süreci sonlandıracaktır.
Süreç seçimi
Bellek dolduğunda fonksiyon çağrılır out_of_memory(). Bir işlevi var select_bad_process()işlevden bir değerlendirme alan badness(). “En kötü” süreç hedeflenecek. İşlev badness() Belirli kurallara göre bir süreç seçer.
- Çekirdeğin kendisi için minimum belleğe ihtiyacı vardır.
- Çok fazla hafıza boşaltmanız gerekiyor.
- Az bellek kullanan işlemleri sonlandırmaya gerek yoktur.
- Minimum süreçlerin tamamlanması gerekiyor.
- Kullanıcının kendisinin tamamlamak istediği süreçlerin tamamlanma şansını artıran karmaşık algoritmalar.
Tüm bu kontrolleri tamamlayan OOM, puanı inceler (oom_score). OOM atar oom_score her işlem ve ardından bu değeri bellek miktarıyla çarpar. Daha büyük değerlere sahip süreçlerin OOM Killer'ın kurbanı olma olasılığı daha yüksektir. Kök kullanıcıyla ilişkili işlemlerin puanı daha düşüktür ve sonlandırılmaya zorlanma olasılıkları daha düşüktür.
postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
3813
(1 row)Postgres işlem kimliği 3813'tür, dolayısıyla başka bir kabukta bu çekirdek parametresini kullanarak puanı almak mümkündür oom_score:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2OOM-Killer'ın süreci sonlandırmasını istemiyorsanız başka bir çekirdek seçeneği daha vardır: oom_score_adj. Değer verdiğiniz bir süreci tamamlama şansınızı azaltmak için büyük bir negatif değer ekleyin.
sudo echo -100 > /proc/3813/oom_score_adjBir değer ayarlamak için oom_score_adj, hizmet bloğunda OOMScoreAdjust'ı ayarlayın:
[Service]
OOMScoreAdjust=-1000Ya da kullan oomprotect bir takımda rcctl.
rcctl set <i>servicename</i> oomprotect -1000Bir işlemin zorla sonlandırılması
Bir veya daha fazla işlem zaten seçildiğinde, OOM-Killer işlevi çağırır oom_kill_task(). Bu fonksiyon sürece bir sonlandırma sinyali gönderir. Bellek yetersizliği durumunda oom_kill() Sürece bir SIGKILL sinyali göndermek için bu işlevi çağırır. Çekirdek günlüğüne bir mesaj yazılır.
Out of Memory: Killed process [pid] [name].OOM-Killer nasıl kontrol edilir
В Linux OOM-Killer'ı etkinleştirebilir veya devre dışı bırakabilirsiniz (ancak devre dışı bırakma önerilmez). Etkinleştirmek veya devre dışı bırakmak için parametreyi kullanın. vm.oom-kill. OOM-Killer'ı çalışma zamanında etkinleştirmek için şu komutu çalıştırın: sysctl.
sudo -s sysctl -w vm.oom-kill = 1OOM-Killer'ı devre dışı bırakmak için aynı komutta 0 değerini belirtin:
sudo -s sysctl -w vm.oom-kill = 0Bu komutun sonucu sonsuza kadar kaydedilmeyecek, yalnızca ilk yeniden başlatmaya kadar kaydedilecektir. Daha fazla ısrara ihtiyacınız varsa bu satırı dosyaya ekleyin /etc/sysctl.conf:
echo vm.oom-kill = 1 >>/etc/sysctl.confEtkinleştirmenin ve devre dışı bırakmanın başka bir yolu da bir değişken yazmaktır panic_on_oom. Değer her zaman kontrol edilebilir /proc.
$ cat /proc/sys/vm/panic_on_oom
0Değeri 0 olarak ayarlarsanız, bellek bittiğinde çekirdek paniği oluşmaz.
$ echo 0 > /proc/sys/vm/panic_on_oomDeğeri 1 olarak ayarlarsanız, bellek bittiğinde çekirdek paniği meydana gelir.
echo 1 > /proc/sys/vm/panic_on_oomDaha önce de belirttiğimiz gibi, OOM-Killer açılıp kapatılabilir. Linux Çekirdek, mevcut bellekten daha fazlasını işlemler için ayırabilir ancak bu belleği fiilen tahsis etmeyebilir ve bu davranış bir çekirdek parametresi tarafından kontrol edilir. LinuxBu durumdan değişken sorumludur. vm.overcommit_memory.
Bunun için aşağıdaki değerleri belirleyebilirsiniz:
0: Çekirdek, çok fazla bellek ayırıp ayırmayacağına kendisi karar verir. Bu, çoğu sürümde varsayılan değerdir. Linux.
1: Çekirdek her zaman ekstra bellek ayıracaktır. Bu risklidir çünkü hafıza tükenebilir, çünkü büyük olasılıkla bir gün süreçler bunu gerektirecektir.
2: çekirdek parametrede belirtilenden daha fazla bellek ayırmayacaktır overcommit_ratio.
Bu parametreyle, aşırı rezerve edilmesine izin verilen belleğin yüzdesini belirtirsiniz. Yer yoksa, hafıza tahsis edilmez ve rezervasyon reddedilir. Bu PostgreSQL için önerilen en güvenli seçenektir. OOM-Killer başka bir unsurdan etkilenir; değişken tarafından kontrol edilen değiştirme yeteneği cat /proc/sys/vm/swappiness. Bu değerler çekirdeğe sayfalamanın nasıl işleneceğini anlatır. Değer ne kadar yüksek olursa, OOM'un süreci sonlandırma olasılığı da o kadar düşük olur, ancak G/Ç işlemleri nedeniyle veritabanı üzerinde olumsuz bir etkisi vardır. Ve bunun tersi de geçerlidir; değer ne kadar düşük olursa, OOM-Killer'ın müdahale olasılığı da o kadar yüksek olur, ancak veritabanı performansı da daha yüksek olur. Varsayılan değer 60'tır ancak veritabanının tamamı belleğe sığıyorsa değeri 1 olarak ayarlamak daha iyidir.
sonuçlar
OOM-Killer'daki "katil"in sizi korkutmasına izin vermeyin. Bu durumda katil sisteminizin kurtarıcısı olacaktır. En kötü süreçleri “öldürür” ve sistemi çökmekten kurtarır. PostgreSQL'i sonlandırmak için OOM-Killer'ı kullanmak zorunda kalmamak için, şu şekilde ayarlayın: vm.overcommit_memory değer 2. Bu, OOM-Killer'in müdahale etmek zorunda kalmayacağını garanti etmez ancak PostgreSQL sürecini sonlandırmaya zorlama olasılığını azaltır.
Kaynak: habr.com
