MySQL OOM 系列一 Linux內(nèi)存分配
RDS(網(wǎng)易云關(guān)系數(shù)據(jù)庫服務(wù))上線已經(jīng)有一段時間,陸續(xù)不斷有產(chǎn)品遷入到了RDS中,在線上運(yùn)維的過程中,也遇到了一些曾經(jīng)沒有考慮到,或者考慮的不全的東西。后續(xù)有時間可以分享給大家。
今天想提到的是線上一個4G的RDS實例,發(fā)生了OOM(out of memory)的問題,MySQL進(jìn)程被直接Kill掉了。在解釋這個問題的時候,我們首先需要從Linux系統(tǒng)內(nèi)存分配策略講起。
一般寫C語言程序,我們習(xí)慣使用malloc動態(tài)的申請內(nèi)存空間(Java由JVM負(fù)責(zé)內(nèi)存管理),malloc函數(shù)會向操作系統(tǒng)申請一段連續(xù)的內(nèi)存單元,然后返回這段空間的起始地址。如果malloc函數(shù)返回為null則表示系統(tǒng)沒有可分配的內(nèi)存空間。這是我們的一般思維,當(dāng)然這在某些操作系統(tǒng)中確實也是正確的(Solaris)。
但是Linux不是這樣的,Linux的內(nèi)存分配采取的是一種更加積極的分配策略,它假設(shè)應(yīng)用申請了內(nèi)存空間后并不會立即去使用它,所以允許一定量的超售,當(dāng)應(yīng)用真的需要使用它的時候,操作系統(tǒng)可能已經(jīng)通過回收了其他應(yīng)用的內(nèi)存空間而變得有能力去滿足這個應(yīng)用的需求,簡單的說,就是允許應(yīng)用申請比實際可分配空間(包括物理內(nèi)存和Swap)更多的內(nèi)存,這個特性稱為OverCommit。
這個特性在Linux操作系統(tǒng)里面也是可配的,可以通過設(shè)置/proc/sys/overcommit_memory為不同的值來調(diào)整OverCommit策略。
overcommit_memory可以取3個值:
0:默認(rèn)值,由Linux內(nèi)核通過一些啟發(fā)式算法來決定是否超售和超售的大小,一般允許輕微的超售,拒絕一些明顯不可能提供的請求,同時做一些規(guī)則限制,比如不同用戶overcommit的大小也不一樣。
1:允許,不做限制的超售,當(dāng)然這個也不是無限大,還受到尋址空間的限制,32位系統(tǒng)最大可能只有4G,64位系統(tǒng)大概16T左右。
2:禁止,禁止超售,系統(tǒng)能夠分配的內(nèi)存不會超過swap+實際物理內(nèi)存*overcommit_ratio,該值可以通過/proc/sys/vm/overcommit_ratio設(shè)置,默認(rèn)50%。
為了驗證Linux的內(nèi)存分配,我們用個小程序來測試一下:
#include <stdio.h> #include <stdlib.h> #define MEGABYTE 1024*1024 int main(int argc, char *argv[]) { void *myblock = NULL; int count = 0; while (1) { myblock = (void *) malloc(MEGABYTE); if (!myblock) break; printf("Currently allocating %d MB\n", ++count); } exit(0); } #include <stdio.h> #include <stdlib.h> #define MEGABYTE 1024*1024 int main(int argc, char *argv[]) { void *myblock = NULL; int count = 0; while(1) { myblock = (void *) malloc(MEGABYTE); if (!myblock) break; memset(myblock,1, MEGABYTE); printf("Currently allocating %d MB\n",++count); } exit(0); }
前者再通過malloc()申請了內(nèi)存空間以后,并沒有立即去使用它,而后者相反,每次申請完都立即用1去填充。我們來看看兩個程序運(yùn)行的結(jié)果。
這是在1G的RAM,400M Swap的虛擬機(jī)上運(yùn)行的結(jié)果,前者申請了遠(yuǎn)遠(yuǎn)超過實際內(nèi)存的空間,后者并沒有超過實際內(nèi)存可用空間。這就驗證了前面敘述的Linux的內(nèi)存分配策略。
本身這是一個系統(tǒng)的優(yōu)化,無可厚非。但是我們知道,但凡“超售”都是基于不會有大量程序同時使用資源的假設(shè),這顯然也是有風(fēng)險的。所以Linux又使用了一種OOM Killer(Out Of Memory killer)的機(jī)制,在系統(tǒng)可用內(nèi)存(包括Swap)即將使用完之前,選擇性的Kill掉一些進(jìn)程以求釋放一些內(nèi)存。下一章我們重點(diǎn)討論一下Linux OOM Killer的機(jī)制。
相關(guān)文章
MySQL配置文件my.cnf中文詳解附mysql性能優(yōu)化方法分享
Mysql參數(shù)優(yōu)化對于新手來講,是比較難懂的東西,其實這個參數(shù)優(yōu)化,是個很復(fù)雜的東西,對于不同的網(wǎng)站,及其在線量,訪問量,帖子數(shù)量,網(wǎng)絡(luò)情況,以及機(jī)器硬件配置都有關(guān)系,優(yōu)化不可能一次性完成,需要不斷的觀察以及調(diào)試,才有可能得到最佳效果。2011-09-09mysqldump備份還原和mysqldump導(dǎo)入導(dǎo)出語句大全詳解
這篇文章主要介紹了mysqldump備份還原和mysqldump導(dǎo)入導(dǎo)出語句大全詳解,需要的朋友可以參考下2014-05-05mysql創(chuàng)建存儲過程實現(xiàn)往數(shù)據(jù)表中新增字段的方法分析
這篇文章主要介紹了mysql創(chuàng)建存儲過程實現(xiàn)往數(shù)據(jù)表中新增字段的方法,結(jié)合實例形式對比分析了通過存儲過程新增字段相關(guān)操作技巧,需要的朋友可以參考下2018-12-12