
מתי בפנים Linux שרת מסד הנתונים מסתיים באופן בלתי צפוי, ויש לקבוע את הסיבה. יכולות להיות מספר סיבות. לדוגמה, SIGSEGV - כשל עקב באג בשרת הקצה האחורי. אבל זה נדיר. לרוב, פשוט נגמר לך שטח הדיסק או הזיכרון. אם נגמר לך שטח הדיסק, יש רק מוצא אחד - פנה מקום והפעל מחדש את מסד הנתונים.
רוצח חסר זיכרון
כאשר אתה שרת או שהתהליך אוזל הזיכרון, Linux ה-Out-Of-Memory Killer מציע שני פתרונות: קריסת המערכת כולה או סיום התהליך (האפליקציה) שצורכת זיכרון. עדיף, כמובן, לסיים את התהליך ולהציל את מערכת ההפעלה מקריסה. בקיצור, ה-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() בוחר תהליך לפי כללים מסוימים.
- הקרנל זקוק למינימום זיכרון לעצמו.
- אתה צריך לפנות הרבה זיכרון.
- אין צורך להפסיק תהליכים המשתמשים בזיכרון מועט.
- צריך להשלים מינימום תהליכים.
- אלגוריתמים מורכבים המגדילים את סיכויי ההשלמה לאותם תהליכים שהמשתמש עצמו רוצה להשלים.
לאחר השלמת כל הבדיקות הללו, OOM בוחנת את הציון (oom_score). OOM מקצה oom_score כל תהליך, ולאחר מכן מכפיל את הערך הזה בכמות הזיכרון. תהליכים בעלי ערכים גדולים יותר נוטים יותר ליפול קורבן לרוצח OOM. לתהליכים הקשורים למשתמש השורש יש ציון נמוך יותר וסביר פחות שייאלצו להפסיק.
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
