升級到MySQL 5.7 解決分區問題

來源:互聯網
上載者:User

升級到MySQL 5.7 解決分區問題

前言

經常有小夥伴問,MySQL的分區(partition)怎麼樣?能用不?是不是有很多bug?不知MySQL的分區為何會給普羅福士這樣的印象。但Inside君的印象中,分區影響比較大的bug就下面的一例(嚴格意義也很難說是bug),也是小夥伴們諮詢Inside君分區遇到最多的問題。不過,好在這個bug已在5.7版本中得到了修複(準確來說是5.7支援了Native Paritition)。看來又多了一個升級到5.7的理由。總結來說,生產環境有必要每天弄個分區嘛?

本文

一個月之前,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

......

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。

其實一開始Scott就發現,這台機器上有一個更早的問題,就是因為系統最大檔案開啟數不夠導致這台機器的xtrabackup備份總是不成功,具體是什麼原因請等Scott去整理xtrabackup備份的更詳細的過程。然後我去檢查了該機器上面的*.ibd檔案和*.frm檔案數量,嚇我一跳(話說Inside君也是嚇尿了):

[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/

上面是MySQLTeam Dev寫的關於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左右,這也表明確實是分區數量太多的原因。

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.