MySQL OOM 系列一 Linux記憶體分配
RDS(網易雲關聯式資料庫服務)上線已經有一段時間,陸續不斷有產品遷入到了RDS中,線上上運維的過程中,也遇到了一些曾經沒有考慮到,或者考慮的不全的東西。後續有時間可以分享給大家。
今天想提到的是線上一個4G的RDS例項,發生了OOM(out of memory)的問題,MySQL程式被直接Kill掉了。在解釋這個問題的時候,我們首先需要從Linux系統記憶體分配策略講起。
一般寫C語言程式,我們習慣使用malloc動態的申請記憶體空間(Java由JVM負責記憶體管理),malloc函式會向作業系統申請一段連續的記憶體單元,然後返回這段空間的起始地址。如果malloc函式返回為null則表示系統沒有可分配的記憶體空間。這是我們的一般思維,當然這在某些作業系統中確實也是正確的(Solaris)。
但是Linux不是這樣的,Linux的記憶體分配採取的是一種更加積極的分配策略,它假設應用申請了記憶體空間後並不會立即去使用它,所以允許一定量的超售,當應用真的需要使用它的時候,作業系統可能已經透過回收了其他應用的記憶體空間而變得有能力去滿足這個應用的需求,簡單的說,就是允許應用申請比實際可分配空間(包括實體記憶體和Swap)更多的記憶體,這個特性稱為OverCommit。
這個特性在Linux作業系統裡面也是可配的,可以透過設定/proc/sys/overcommit_memory為不同的值來調整OverCommit策略。
overcommit_memory可以取3個值:
0:預設值,由Linux核心透過一些啟發式演算法來決定是否超售和超售的大小,一般允許輕微的超售,拒絕一些明顯不可能提供的請求,同時做一些規則限制,比如不同使用者overcommit的大小也不一樣。
1:允許,不做限制的超售,當然這個也不是無限大,還受到定址空間的限制,32位系統最大可能只有4G,64位系統大概16T左右。
2:禁止,禁止超售,系統能夠分配的記憶體不會超過swap+實際實體記憶體*overcommit_ratio,該值可以透過/proc/sys/vm/overcommit_ratio設定,預設50%。
為了驗證Linux的記憶體分配,我們用個小程式來測試一下:
?
#include #include #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 MBn" , ++count); } exit (0); } #include #include #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 MBn" ,++count); } exit (0); }
|
前者再透過malloc()申請了記憶體空間以後,並沒有立即去使用它,而後者相反,每次申請完都立即用1去填充。我們來看看兩個程式執行的結果。
這是在1G的RAM,400M Swap的虛擬機器上執行的結果,前者申請了遠遠超過實際記憶體的空間,後者並沒有超過實際記憶體可用空間。這就驗證了前面敘述的Linux的記憶體分配策略。
本身這是一個系統的最佳化,無可厚非。但是我們知道,但凡“超售”都是基於不會有大量程式同時使用資源的假設,這顯然也是有風險的。所以Linux又使用了一種OOM Killer(Out Of Memory killer)的機制,在系統可用記憶體(包括Swap)即將使用完之前,選擇性的Kill掉一些程式以求釋放一些記憶體。下一章我們重點討論一下Linux OOM Killer的機制。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4479/viewspace-2811140/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- 告別記憶體OOM,解決MySQL記憶體增長問題記憶體OOMMySql
- MySQL記憶體管理,記憶體分配器和作業系統MySql記憶體作業系統
- MySQL 配置InnoDB的記憶體分配器MySql記憶體
- [20191114]linux記憶體分配的討論.txtLinux記憶體
- 垃圾收集器與記憶體分配策略_記憶體分配策略記憶體
- 當linux報 “-bash: fork: 無法分配記憶體”Linux記憶體
- 動態記憶體分配記憶體
- JVM-記憶體區域與OOMJVM記憶體OOM
- 記憶體的分配與釋放,記憶體洩漏記憶體
- java-方法記憶體分配Java記憶體
- go記憶體分配器Go記憶體
- java基礎-記憶體分配Java記憶體
- hadoop 記憶體分配規則Hadoop記憶體
- C語言-記憶體分配C語言記憶體
- 記憶體分配策略學習記憶體
- 深度理解glibc記憶體分配記憶體
- 一個可以參考的JVM記憶體分配JVM記憶體
- 一夜搞懂 | JVM GC&記憶體分配JVMGC記憶體
- 深入理解 Linux 實體記憶體分配全鏈路實現Linux記憶體
- 【Java】 記憶體分配全面淺析Java記憶體
- JVM GC 與 記憶體分配策略JVMGC記憶體
- C++動態記憶體分配C++記憶體
- 記憶體分配問題處理記憶體
- mimalloc記憶體分配程式碼分析記憶體
- C語言的記憶體分配C語言記憶體
- C中的記憶體分配模型記憶體模型
- [20210126]探究oracle記憶體分配.txtOracle記憶體
- JVM記憶體洩露(OOM)!帶你一一揭秘【第一彈】JVM記憶體洩露OOM
- Python如何管理記憶體?記憶體分配機制是什麼?Python記憶體
- jvm:記憶體模型、記憶體分配及GC垃圾回收機制JVM記憶體模型GC
- 圖解Go語言記憶體分配圖解Go記憶體
- Android O 8.0 以上 bitmap記憶體分配Android記憶體
- v8記憶體分配淺談記憶體
- curl 中減少記憶體分配操作記憶體
- JVM 之 記憶體分配與回收策略JVM記憶體
- 深入理解golang:記憶體分配原理Golang記憶體
- Netty 中的記憶體分配淺析Netty記憶體