MySQL5.6分區數量太多引發的血案【轉】


一個月之前,Scott和同事們發現公司有一個MySQL MHA集群的master(假設master機器名為hostA)每隔一周左右就會掛一次(指MySQL掛掉),在幾周內,MHA來回切了好幾次。

按照國際慣例,Scott按照如下順序去查問題到底出在哪里:
(1)先翻MySQL error log,沒有發現異常
(2)再翻Linux系統日志文件,果然,翻到了下面的內容:

Nov 26 13:05:38 hostA kernel: mysql invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
...此處內容省略N行...
Nov 26 13:05:38 hostA kernel: Out of memory: Kill process 32271 (mysqld) score 976 or sacrifice child
Nov 26 13:05:38 hostA kernel: Killed process 32271, UID 496, (mysqld) total-vm:83064212kB, anon-rss:64204132kB, file-rss:4544kB

該機器的物理內存大小為62G,從上面的日志看,MySQL確實已經把它用滿了。該機器上MySQL的innodb_buffer_pool=31G,Scott認為這已經相當保守了,而且各種buffer_size我們都使用的是默認值,MySQL OOM時的用戶連接數是100+,

這些目測都沒有什么問題,但是居然還是發生了OOM,實在是不可思議。當時覺得就是內存不夠用了唄,沒有查出具體原因,后來62G的內存加到了125G(innodb_buffer_pool_size增大到64G,這值確實很保守),還是發生了OOM。(OOM指的是在系統物理內存被用完時,Linux內核為了保證系統的正常運行,根據一定的算法殺掉占用內存較大的進程,基本上可以認為是殺掉占用內存最大的進程以釋放內存資源。)

其實一開始Scott就發現,這台機器上有一個更早的問題,就是因為系統最大文件打開數不夠導致這台機器的xtrabackup備份總是不成功,具體是什么原因請等Scott去整理xtrabackup備份的更詳細的過程。然后我去檢查了該機器上面的*.ibd文件和*.frm文件數量,嚇我一跳:

[userA@hostA mysql]$ sudo find . -name '*.ibd' | wc -l
169577
[userA@hostA mysql]$ sudo find . -name '*.frm' | wc -l
2534

也就是說,該機器上面竟然有17萬個ibd文件,但是只有2534張表,很明顯是分區表中的分區數量非常多。

[userA@hostA mysql]$ sudo find . -name '*par*' | wc -l
1882

Scott仔細比較了這台機器和其他沒有問題的機器的不同,發現這台機器上面分區數量太多是唯一的一個不同,這讓Scott沒有辦法不懷疑是分區導致的問題。

Scott仍然按照國際慣例,第一時間去查MySQL 5.6的官方文檔,無果。。。(官方文檔雖然不是萬能的,但是仍然是出現問題的第一參考資料)

去MySQL的bugs頁面搜索關於partition的bug,無果。。。

去google了下,發現有的比較雜的網站上面寫道MySQL分區數量太多引發內存耗盡的問題,但是文章講的內容感覺不是很正確。

最后在姜老師的指點下,看了這篇文章:

http://mysqlserverteam.com/innodb-native-partitioning-early-access/

上面是MySQL開發團隊寫的關於InnoDB Native Partitioning的文章。文章中大概講的內容是,在5.6里面,分區的信息是在MySQL Server層維護的(在.par文件里面),InnoDB引擎層是不知道有分區這個概念的,InnoDB引擎層把每一個分區都當成一張普通的InnoDB表。在打開一個分區表時,會打開很多個分區,打開這些分區表就相當於打開了同等數量的InnoDB表,這需要更多內存存放InnoDB表的元數據和各種與ibd文件打開相關的各種cache與handler的信息。在5.7里面,InnoDB引入了Native Partitioning,它把分區的信息從Server層移到了InnoDB層,打開一個分區表和打開一個InnoDB表的內存開銷基本是一樣的。

 

If we compare the amount of memory used when opening a single instance of this table, first using the old generic non-native partitioning, and then with InnoDB Native Partitioning we see the following:

One open instance of the table takes 49% less memory (111MB vs 218MB) with the current state of Native Partitioning support. With ten open instances of the table, we take up 90% less memory (113MB vs 1166MB)!


由於升級到5.7還需要一些時日,目前已經將分區數量減少到25000,125G剩余內存在20天里一直穩定在20G左右,這也表明確實是分區數量太多的原因。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM