MySQL記憶體管理,記憶體分配器和作業系統
導讀
作者:Sveta Smirnova
翻譯:鄭志江
校對:徐晨亮
原文 :MySQL Memory Management, Memory Allocators and Operating System
本文涉及連結在文末展示
當使用者使用任何軟體(包括MySQL)碰到記憶體問題時,我們第一反應就是記憶體洩漏。正如這篇文章所示,其實並不總是這樣。
這篇文章闡述一個關於記憶體的bug。
所有percona所支援的客戶都有獲得bug修復的資格,但他們也有不同的選擇。比如,vip客戶在軟體補丁正式釋出之前就可以獲得hotfiix版本,高階客戶甚至不需要使用percona的軟體,我們也可以為他們把補丁推到上游。但對於與percona產品來說,所有支援等級都有權得到bug修復。
即便如此,這並不意味著我們會修復所有的意外情況,即使我們接受這種情況為一個有效bug。做出這樣的決定的原因之一可能是這個意外情況雖然很明確是錯誤的,但對於percona產品本身來說確實一個產品需求
作為學習案例的一個bug
最近一個很好的案例是 PS-5312<連結3>——這個bug可在上游復現並被記錄在bugs.mysql.com/95065<連結4>。
這個報告闡述了一種情況,當訪問InnoDB的全文索引的時候會導致記憶體使用量增長。這種情況出現在一些全文索引的查詢,記憶體會持續增長直到達到最大值,並且很長時間不會釋放。
來自Percona工程團隊的Yura Sorokin研究表明,這種情況並不屬於記憶體洩漏範疇。
當InnoDB解析一個全文查詢時,它會在fts_query_phrase_search函式中建立一個記憶體堆,這個堆可能增長到80M。另外,這個過程還會使用到大量非連續塊(mem_block_t)進而產生的記憶體碎片。
在函式出口,這些記憶體堆會被釋放。InnoDB會為其分配的每一個塊做這個操作。在函式執行結束時,呼叫一個記憶體分配器庫中的free()操作,比如malloc或者jemalloc。從MySQL本身來看,這都是沒問題的,不存在記憶體洩漏。
然而,free()函式被呼叫時確實應該釋放記憶體,但不需要將其返回給作業系統。如果記憶體分配器發現這些記憶體塊馬上還需要被用到,則會將他們保留住繼續用於mysqld程式。這就解釋了為什麼mysqld在完成工作及釋放記憶體都結束後還會佔用大量記憶體。
這個在實際生產中並不是一個大問題,按道理不應該造成任何事故。但是如果你需要更快地將記憶體返回給作業系統,你可以嘗試非傳統的記憶體分配器,類似jemallolc。它被證明可以解決PS-5312<連結5>的問題。
另一個改善記憶體管理的因素是cpu核心數量:在測試中,cpu核數越多,記憶體返回給作業系統的速度會越快。這可能是你擁有多個CPU,而其中一個可專門用作記憶體分配器釋放記憶體給作業系統。
正如我們的工程師Yura Sorokin所發現的一樣,下面兩點闡述了InnoDB全文索引的早期實現引入了這個缺陷:
5.6版本MySQL最早對InnoDB WL全文索引功能引入的介紹:#5538: InnoDB全文搜尋支援 – https://dev.mysql.com/worklog/task/?id=5538
實現WL #5538 InnoDB全文搜尋支援與合併 - - 也存在同樣的問題問題
修復方法
我們有兩種方法來修復這個問題:
1.修改InnoDB全文索引的實現
2.使用自定義記憶體庫,例如jemalloc
這兩種方法都有各自的優缺點。
方法1 :意味著我們引入了與軟體上游不相容性的風險,這可能會導致新版本中出現未知的錯誤。也意味著徹底重寫InnoDB全文索引部分程式碼,這在使用者們使用的GA版本中是有風險的。
方法2 則意味著我們可能會命中一些jemalloc庫中專門為效能設計但不是最安全的記憶體分配的bug。
因此我們不得不在這兩個並不完美的方法中選擇一個。
鑑於方法一可能導致percona服務與上游的不相容,我們更傾向於用方法二來解決問題,並期待著上游修復這個bug。
結論
如果發現mysqld程式佔用記憶體很高,並不代表一定是記憶體洩漏。我們可以在Performance Schema中使用記憶體檢測來了解程式是如何使用已分配的記憶體。也可以嘗試替換記憶體庫來更好地處理記憶體分配與釋放。關於LD_RELOAD如何配置,請查閱MySQL使用者手冊對應頁面 mysqld-safe<連結6>和using-system<連結7>。
連結1:
連結2:
連結3:
連結4:https://www.percona.com/blog/2019/05/02/mysql-memory-management-memory-allocators-and-operating-system/
連結5:
連結6:https://dev.mysql.com/doc/refman/8.0/en/mysqld-safe.html
連結7:https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/using-systemd.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69985270/viewspace-2726783/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 作業系統-記憶體管理作業系統記憶體
- 作業系統——記憶體管理作業系統記憶體
- 作業系統記憶體管理概述作業系統記憶體
- 作業系統記憶體管理-原理作業系統記憶體
- 【作業系統】記憶體管理概述作業系統記憶體
- 作業系統-記憶體、檔案管理作業系統記憶體
- 作業系統——記憶體管理學習筆記作業系統記憶體筆記
- 作業系統的記憶體管理你知道嗎作業系統記憶體
- 淺談作業系統對記憶體的管理作業系統記憶體
- 計算機作業系統——虛擬記憶體與實體記憶體計算機作業系統記憶體
- MySQL 配置InnoDB的記憶體分配器MySql記憶體
- go記憶體分配器Go記憶體
- 探索Linux 作業系統記憶體模型和管理-1(轉)Linux作業系統記憶體模型
- 探索Linux 作業系統記憶體模型和管理8(轉)Linux作業系統記憶體模型
- MySQL記憶體管理MySql記憶體
- 作業系統——記憶體連續分配管理方式作業系統記憶體
- 作業系統的虛擬記憶體作業系統記憶體
- 記憶體管理 記憶體管理概述記憶體
- 作業系統思考 第六章 記憶體管理作業系統記憶體
- Linux作業系統記憶體淺析Linux作業系統記憶體
- HP-UX作業系統的記憶體UX作業系統記憶體
- windows作業系統支援的最大記憶體Windows作業系統記憶體
- 自動共享記憶體管理 自動記憶體管理 手工記憶體管理記憶體
- 【記憶體管理】記憶體佈局記憶體
- 記憶體管理篇——實體記憶體的管理記憶體
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- 核心早期記憶體分配器:memblock記憶體BloC
- Go:記憶體管理與記憶體清理Go記憶體
- Java的記憶體 -JVM 記憶體管理Java記憶體JVM
- MySQL InnoDB的記憶體管理MySql記憶體
- ucore作業系統學習筆記(二) ucore lab2實體記憶體管理分析作業系統筆記記憶體
- Linux作業系統記憶體管理的原始碼實現(轉)Linux作業系統記憶體原始碼
- 記憶體管理兩部曲之實體記憶體管理記憶體
- 記憶體管理記憶體
- 實體記憶體和虛擬記憶體記憶體
- Linux 記憶體管理:記憶體對映Linux記憶體
- 作業系統(八) -- 記憶體的分段與分頁作業系統記憶體
- Android 作業系統的記憶體回收機制Android作業系統記憶體