OOM Killer - เซิร์ฟเวอร์ MySQL ที่ฆ่าแล้ว


10

หนึ่งในต้นแบบ MySQL ของเรา OOM Killer ถูกเรียกใช้และฆ่าเซิร์ฟเวอร์ MySQL ซึ่งนำไปสู่ปัญหาใหญ่ ต่อไปนี้เป็นบันทึกของเคอร์เนล:

[2006013.230723] mysqld invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[2006013.230733] Pid: 1319, comm: mysqld Tainted: P           2.6.32-5-amd64 #1
[2006013.230735] Call Trace:
[2006013.230744]  [<ffffffff810b6708>] ? oom_kill_process+0x7f/0x23f
[2006013.230750]  [<ffffffff8106bde2>] ? timekeeping_get_ns+0xe/0x2e
[2006013.230754]  [<ffffffff810b6c2c>] ? __out_of_memory+0x12a/0x141
[2006013.230757]  [<ffffffff810b6d83>] ? out_of_memory+0x140/0x172
[2006013.230762]  [<ffffffff810baae8>] ? __alloc_pages_nodemask+0x4ec/0x5fc
[2006013.230768]  [<ffffffff812fca02>] ? io_schedule+0x93/0xb7
[2006013.230773]  [<ffffffff810bc051>] ? __do_page_cache_readahead+0x9b/0x1b4
[2006013.230778]  [<ffffffff810652f8>] ? wake_bit_function+0x0/0x23
[2006013.230782]  [<ffffffff810bc186>] ? ra_submit+0x1c/0x20
[2006013.230785]  [<ffffffff810b4e53>] ? filemap_fault+0x17d/0x2f6
[2006013.230790]  [<ffffffff810cae1e>] ? __do_fault+0x54/0x3c3
[2006013.230794]  [<ffffffff812fce29>] ? __wait_on_bit_lock+0x76/0x84
[2006013.230798]  [<ffffffff810cd172>] ? handle_mm_fault+0x3b8/0x80f
[2006013.230803]  [<ffffffff8103a9a0>] ? pick_next_task+0x21/0x3c
[2006013.230808]  [<ffffffff810168ba>] ? sched_clock+0x5/0x8
[2006013.230813]  [<ffffffff81300186>] ? do_page_fault+0x2e0/0x2fc
[2006013.230817]  [<ffffffff812fe025>] ? page_fault+0x25/0x30

เครื่องนี้มี RAM 64GB

ต่อไปนี้เป็นตัวแปรการกำหนดค่า mysql:

innodb_buffer_pool_size        = 48G
innodb_additional_mem_pool_size = 512M
innodb_log_buffer_size         = 64M

ยกเว้นบางปลั๊กอิน nagios และสคริปต์การรวบรวมเมทริกไม่มีอะไรทำงานบนเครื่องนี้ ใครสามารถช่วยฉันค้นหาสาเหตุที่นักฆ่า OOM ถูกเรียกใช้และฉันจะป้องกันไม่ให้ถูกเรียกใช้ในอนาคตได้อย่างไร มีวิธีใดบ้างที่ฉันสามารถบอก OOM killer ว่าจะไม่ฆ่าเซิร์ฟเวอร์ mysql ฉันรู้ว่าเราสามารถกำหนดoom_adjค่าเป็นน้อยมากสำหรับกระบวนการเพื่อป้องกันไม่ให้ถูกฆ่าโดย OOM killer แต่มีวิธีอื่นในการป้องกันสิ่งนี้


2
ใช้หน่วยความจำจะสูงกว่า48G+ 512M+ 64Mเพราะยังมีค่าใช้จ่ายบางส่วนและโครงสร้างอื่น ๆ ที่จะต้องพิจารณา; มีสูตรสำหรับบางที่ แต่ฉันไม่สามารถหาได้ในขณะนี้ ไม่แน่ใจว่าจะทำให้เกิดการระเบิด64Gหรือไม่ เพียงเพื่อให้แน่ใจว่าfreeยืนยัน64Gมีอยู่ในสถานที่แรก?
frostschutz

@frostschutz: ใช่คำสั่งฟรีแสดง 64G
pradeepchhetri

การบอกนักฆ่า OOM ที่จะไม่ฆ่า mysqld นั้นมีโอกาสมากที่จะเกิดความล่าช้าในช่วงเวลาสั้น ๆ แก้ไขการกำหนดค่าของคุณให้ดีขึ้น
scai

คำตอบ:


25

Linux ทำหน่วยความจำเกินความจำเป็น นั่นหมายความว่าจะอนุญาตให้กระบวนการร้องขอหน่วยความจำมากกว่าที่มีในระบบจริงๆ เมื่อโปรแกรมพยายามที่จะ malloc () เคอร์เนลบอกว่า "ตกลงคุณมีหน่วยความจำ" แต่ไม่ต้องจอง หน่วยความจำจะถูกสงวนไว้เฉพาะเมื่อกระบวนการจะเขียนบางสิ่งในพื้นที่นี้

ในการดูความแตกต่างคุณมีตัวบ่งชี้ 2 ตัวคือหน่วยความจำเสมือนและหน่วยความจำถิ่นที่อยู่ เสมือนเป็นหน่วยความจำที่ร้องขอโดยกระบวนการ Resident เป็นหน่วยความจำที่กระบวนการใช้จริง

ด้วยระบบนี้คุณอาจเข้าสู่ "การจองมากกว่าจำนวนที่กำหนด" เคอร์เนลให้หน่วยความจำมากกว่าที่มี จากนั้นเมื่อระบบของคุณไปที่หน่วยความจำว่าง 0 ไบต์และสลับเขาต้องเสียสละ (ฆ่า)กระบวนการเพื่อให้ได้หน่วยความจำฟรี

นั่นคือเมื่อ OOM Killer ดำเนินการ OOM เลือกกระบวนการที่ขึ้นอยู่กับการใช้หน่วยความจำของเขาและองค์ประกอบอื่น ๆ อีกมากมาย (ผู้ปกครองได้รับคะแนน 1/2 ของลูกของเขาถ้าเป็นกระบวนการที่เป็นเจ้าของรูตคะแนนจะถูกหารด้วย 4 เป็นต้นดูที่Linux - MM.org/OOM_Killer

คุณสามารถมีอิทธิพลต่อการให้คะแนน OOM โดยปรับ/proc/MySQL_PID/oom_adjไฟล์ เมื่อตั้งค่าเป็น-17กระบวนการของคุณจะไม่ถูกทำลาย แต่ก่อนที่จะทำเช่นนั้นคุณควรปรับแต่งไฟล์คอนฟิกูเรชัน MySQL ของคุณเพื่อ จำกัด การใช้หน่วยความจำ MySQL มิฉะนั้น OOM Killer จะฆ่ากระบวนการของระบบอื่น ๆ (เช่น SSH, crontab และอื่น ๆ ) และเซิร์ฟเวอร์ของคุณจะอยู่ในสถานะที่ไม่เสถียรมากอาจนำไปสู่ความเสียหายของข้อมูลที่แย่กว่าอะไร

นอกจากนี้คุณอาจลองใช้การแลกเปลี่ยนมากขึ้น

[แก้ไข]

นอกจากนี้คุณยังสามารถเปลี่ยนพฤติกรรมการ overcommit ผ่าน 2 sysctls เหล่านี้:

vm.overcommit_memory
vm.overcommit_ratio

ตามที่ระบุในเอกสารเคอร์เนล

overcommit_memory:

ค่านี้มีการตั้งค่าสถานะที่เปิดใช้งานหน่วยความจำ overcommitment

เมื่อแฟล็กนี้เป็น 0 เคอร์เนลพยายามประเมินจำนวนหน่วยความจำว่างที่เหลือเมื่อ userspace ร้องขอหน่วยความจำเพิ่มเติม

เมื่อแฟล็กนี้คือ 1 เคอร์เนลจะแกล้งมีหน่วยความจำเพียงพอเสมอจนกว่าจะหมดจริง

เมื่อการตั้งค่าสถานะนี้เป็น 2 เคอร์เนลใช้นโยบาย "ไม่เคย overcommit" ที่พยายามป้องกันหน่วยความจำเกินหน่วยความจำใด ๆ โปรดทราบว่า user_reserve_kbytes มีผลต่อนโยบายนี้

คุณสมบัตินี้มีประโยชน์มากเพราะมีโปรแกรมจำนวนมากที่ malloc () หน่วยความจำจำนวนมาก "เพียงแค่ใช้ตัวพิมพ์ใหญ่" และไม่ได้ใช้งานมากนัก

ค่าเริ่มต้นคือ 0

ดูเอกสาร / vm / overcommit-accounting และความปลอดภัย / commoncap.c :: cap_vm_enough_memory () สำหรับข้อมูลเพิ่มเติม

overcommit_ratio:

เมื่อ overcommit_memory ถูกตั้งค่าเป็น 2 พื้นที่ที่อยู่ที่กำหนดไม่ได้รับอนุญาตให้ใช้เกิน swap บวกกับเปอร์เซ็นต์ของ RAM จริงนี้ ดูด้านบน.

[/ แก้ไข]


1
นี่คือคำตอบที่ถูกต้อง ฉันได้เห็นบทความเกี่ยวกับการใช้oom_score_adjเพื่อแก้ไขปัญหานี้ แต่พวกเขาไม่เข้าใจกลไกการให้คะแนนอย่างแท้จริง
3manuek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.