導讀
做者:Sveta Smirnova
翻譯:鄭志江
校對:徐晨亮
原文 :MySQL Memory Management, Memory Allocators and Operating System
本文涉及連接在文末展現html
當用戶使用任何軟件(包括MySQL)碰到內存問題時,咱們第一反應就是內存泄漏。正如這篇文章所示,其實並不老是這樣。mysql
這篇文章闡述一個關於內存的bug。git
全部percona所支持的客戶都有得到bug修復的資格,但他們也有不一樣的選擇。好比,vip客戶在軟件補丁正式發佈以前就能夠得到hotfiix版本,高級客戶甚至不須要使用percona的軟件,咱們也能夠爲他們把補丁推到上游。但對於與percona產品來講,全部支持等級都有權獲得bug修復。github
即使如此,這並不意味着咱們會修復全部的意外狀況,即便咱們接受這種狀況爲一個有效bug。作出這樣的決定的緣由之一多是這個意外狀況雖然很明確是錯誤的,但對於percona產品自己來講確實一個產品需求sql
做爲學習案例的一個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...
實現WL #5538 InnoDB全文搜索支持與合併 - https://github.com/mysql/mysq... - 也存在一樣的問題問題
修復方法
咱們有兩種方法來修復這個問題:
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:https://www.percona.com/servi...
連接2:https://www.percona.com/servi...
連接3:https://jira.percona.com/brow...
連接4:https://www.percona.com/blog/...
連接5:https://jira.percona.com/brow...
連接6:https://dev.mysql.com/doc/ref...
連接7:https://dev.mysql.com/doc/mys...