日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

作者:孫祚龍

愛(ài)可生南區(qū)分公司交付服務(wù)部成員,實(shí)習(xí)工程師。負(fù)責(zé)公司產(chǎn)品問(wèn)題排查及日常運(yùn)維工作。

本文來(lái)源:原創(chuàng)投稿

*愛(ài)可生開(kāi)源社區(qū)出品,原創(chuàng)內(nèi)容未經(jīng)授權(quán)不得隨意使用,轉(zhuǎn)載請(qǐng)聯(lián)系小編并注明來(lái)源。


引言

前陣子處理這樣一個(gè)案例,某客戶(hù)的實(shí)例 MySQLd 進(jìn)程內(nèi)存經(jīng)常持續(xù)增加導(dǎo)致最終被 OOM killer。作為 DBA 肯定想知道有哪些原因可能會(huì)導(dǎo)致 OOM(內(nèi)存溢出)。

此篇文章敘述個(gè)人的一些拙見(jiàn)~

 

先介紹下這位朋友:OOM-killer

OOM Killer(Out of Memory Killer) 是當(dāng)系統(tǒng)內(nèi)存嚴(yán)重不足時(shí) linux 內(nèi)核采用的殺掉進(jìn)程,釋放內(nèi)存的機(jī)制。

OOM Killer 通過(guò)檢查所有正在運(yùn)行的進(jìn)程,然后根據(jù)自己的算法給每個(gè)進(jìn)程一個(gè) badness 分?jǐn)?shù),擁有最高 badness 分?jǐn)?shù)的進(jìn)程將會(huì)在內(nèi)存不足時(shí)被殺掉。

它打分的算法如下:

  • 某一個(gè)進(jìn)程和它所有的子進(jìn)程都占用了很多內(nèi)存的將會(huì)打一個(gè)高分。
  • 為了釋放足夠的內(nèi)存來(lái)解決這種情況,將殺死最少數(shù)量的進(jìn)程(最好是一個(gè)進(jìn)程)。
  • 內(nèi)核進(jìn)程和其他較重要的進(jìn)程會(huì)被打成相對(duì)較低的分。

上面打分的標(biāo)準(zhǔn)意味著,當(dāng) OOM killer 選擇殺死的進(jìn)程時(shí),將選擇一個(gè)使用大量?jī)?nèi)存,有很多子進(jìn)程且不是系統(tǒng)進(jìn)程的進(jìn)程。

簡(jiǎn)單來(lái)講,oom-killer 的原則就是損失最小、收益最大,因此它會(huì)讓殺死的進(jìn)程數(shù)盡可能小、釋放的內(nèi)存盡可能大。在數(shù)據(jù)庫(kù)服務(wù)器上,MySQL 被分配的內(nèi)存一般不會(huì)小,因此容易成為 oom-killer 選擇的對(duì)象。

“既然發(fā)生了 OOM,那必然是內(nèi)存不足,內(nèi)存不足這個(gè)問(wèn)題產(chǎn)生原因很多。

首先第一個(gè)就是 MySQL 自身內(nèi)存的規(guī)劃有問(wèn)題,這就涉及到 mysql 相應(yīng)的配置參數(shù)。

另一個(gè)可以想到的原因就是一般部署 MySQL 的服務(wù)器,都會(huì)部署很多的監(jiān)控和定時(shí)任務(wù)腳本,而這些腳本往往缺少必要的內(nèi)存限制,導(dǎo)致在高峰期的時(shí)候占用大量的內(nèi)存,導(dǎo)致觸發(fā) Linux 的 oom-killer 機(jī)制,最終 MySQL 無(wú)辜躺槍犧牲。”

 

all-important:MySQL 自身內(nèi)存規(guī)劃

說(shuō)到 MySQL 自身的內(nèi)存規(guī)劃,最先想到的就是 MySQL 中各種 buffer 的大小,innodb buffer pool 就是最鶴立雞群的那個(gè)。innodb_buffer_pool_size 參數(shù)的大小究竟如何設(shè)置,才能保證 MySQL 的性能呢?在官網(wǎng)文檔中可以找到這個(gè)參數(shù)的一些描述:

A larger buffer pool requires less disk I/O to access the same table data more than once. On a dedicated database server, you might set the buffer pool size to 80% of the machine's physical memory size.

意思是在專(zhuān)用數(shù)據(jù)庫(kù)服務(wù)器上,可以將 innodb_buffer_pool_size 設(shè)置為計(jì)算機(jī)物理內(nèi)存大小的 80%。在許許多多前輩的的經(jīng)驗(yàn)中了解到,此參數(shù)的值設(shè)置為物理內(nèi)存的 50%~80% 頗為合理。

舉個(gè)栗子:

故障分析 | MySQL OOM 故障應(yīng)如何下手

 

innodb buffer pool 分配 76G,每個(gè)連接線(xiàn)程最大可用 160M,最大有 3000 連接數(shù),最大可能使用內(nèi)存總量 545G,但是這臺(tái)實(shí)例所在服務(wù)器的物理內(nèi)存僅僅有 97G,遠(yuǎn)超物理內(nèi)存總量。結(jié)果可想而知,這個(gè)實(shí)例在運(yùn)行中經(jīng)常被 oom-killer 殺死,想必原因之一即是因?yàn)橐婚_(kāi)始 MySQL 自身的內(nèi)存規(guī)劃欠妥。

innodb buffer pool 緩存數(shù)據(jù)的作用相信大家都懂,比如這個(gè) case 中,可以發(fā)現(xiàn)該實(shí)例為寫(xiě)密集,讀請(qǐng)求很少,innodb buffer 對(duì)性能改善作用不大,80% 的內(nèi)存沒(méi)必要,完全可以降低到物理內(nèi)存的50%。

“ 以上是對(duì) OOM 發(fā)生原因的一些見(jiàn)解,那思考一下還有沒(méi)有其他的原因會(huì)導(dǎo)致內(nèi)存溢出的情況呢?不知道大家對(duì)內(nèi)存泄漏是否了解,有沒(méi)有可能 MySQL 因?yàn)閮?nèi)存泄漏堆積演變?yōu)閮?nèi)存溢出,最終 oom-killer ... ”

 

知識(shí)補(bǔ)給站:內(nèi)存泄漏

內(nèi)存泄漏(Memory Leak)是指程序中己動(dòng)態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無(wú)法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。

內(nèi)存泄漏缺陷具有隱蔽性、積累性的特征,比其他內(nèi)存非法訪(fǎng)問(wèn)錯(cuò)誤更難檢測(cè)。因?yàn)閮?nèi)存泄漏的產(chǎn)生原因是內(nèi)存塊未被釋放,屬于遺漏型缺陷而不是過(guò)錯(cuò)型缺陷。此外,內(nèi)存泄漏通常不會(huì)直接產(chǎn)生可觀察的錯(cuò)誤癥狀,而是逐漸積累,降低系統(tǒng)整體性能,極端的情況下可能使系統(tǒng)崩潰。

上文說(shuō)到內(nèi)存泄漏具有隱蔽性,就是不容易被發(fā)現(xiàn)唄......為之奈何?

那咱們就去找一個(gè)可以檢測(cè)內(nèi)存泄漏的工具:valgrind

 

關(guān)于 valgrind 工具

Valgrind 是一個(gè)用于構(gòu)建動(dòng)態(tài)分析工具的工具框架。它提供了一組工具,每個(gè)工具都執(zhí)行某種調(diào)試、分析或類(lèi)似的任務(wù),以幫助您改進(jìn)程序。Valgrind 的體系結(jié)構(gòu)是模塊化的,因此可以輕松地創(chuàng)建新工具,而不會(huì)影響現(xiàn)有的結(jié)構(gòu)。

標(biāo)配了許多有用的工具:

  1. Memcheck 是內(nèi)存錯(cuò)誤檢測(cè)器。
  2. Cachegrind 是一個(gè)緩存和分支預(yù)測(cè)探查器。
  3. Callgrind 是一個(gè)生成調(diào)用圖的緩存分析器。
  4. Helgrind 是線(xiàn)程錯(cuò)誤檢測(cè)器。
  5. DRD 還是線(xiàn)程錯(cuò)誤檢測(cè)器。
  6. Massif 是堆分析器。
  7. DHAT 是另一種堆分析器。
  8. SGcheck 是一種實(shí)驗(yàn)性工具,可以檢測(cè)堆棧和全局陣列的溢出。
  9. BBV 是一個(gè)實(shí)驗(yàn)性 SimPoint 基本塊矢量生成器。

關(guān)于內(nèi)存泄漏,我們需要使用 valgrind 的默認(rèn)工具,也就是 memcheck 工具。

Memcheck 是內(nèi)存錯(cuò)誤檢測(cè)器。它可以檢測(cè)以下和內(nèi)存相關(guān)的問(wèn)題:

  • 使用未初始化的內(nèi)存
  • 讀取/寫(xiě)入已釋放的內(nèi)存
  • 讀取/寫(xiě)入 malloc 塊的末端
  • 內(nèi)存泄漏
  • 對(duì) malloc/new/new[]與free/delete/delete[] 的不匹配使用
  • 雙重釋放內(nèi)存

Valgrind Memcheck 工具的用法如下:

valgrind --tool=memcheck ./a.out

從上面的命令可以清楚地看到,主要的命令是“ Valgrind”,而我們要使用的工具由選項(xiàng)“ --tool”指定。上面的“ a.out ” 表示我們要在其上運(yùn)行 memcheck 的可執(zhí)行文件。此外還可以使用其他的命令行選項(xiàng),以滿(mǎn)足我們的需要。運(yùn)行的程序結(jié)束后,會(huì)生成這個(gè)進(jìn)程的內(nèi)存分析報(bào)告。

“ OK,工具有了,這就如同摸金校尉拿到了洛陽(yáng)鏟,寶藏還會(huì)遠(yuǎn)嗎~ 還不快找?guī)讐K地挖掘試試?”

 

搞個(gè)測(cè)試找找感覺(jué)

1. 使用 valgrind 的 memcheck 工具啟動(dòng) mysql:

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --log-file=/tmp/valgrind-mysql.log /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=root

2. 利用 sysbench 模擬負(fù)載;

3. 進(jìn)程結(jié)束后查看檢測(cè)報(bào)告:

==29326== LEAK SUMMARY:==29326==    definitely lost: 0 bytes in 0 blocks==29326==    indirectly lost: 0 bytes in 0 blocks==29326==      possibly lost: 549,072 bytes in 1,727 blocks==29326==    still reachable: 446,492,944 bytes in 54 blocks==29326==         suppressed: 0 bytes in 0 blocks==29326====29326== For counts of detected and suppressed errors, rerun with: -v==29326== ERROR SUMMARY: 339 errors from 339 contexts (suppressed: 0 from 0)

在報(bào)告的最后的總結(jié)中發(fā)現(xiàn)程序退出時(shí)有部分內(nèi)存未釋放,而且存在潛在的內(nèi)存泄漏。通過(guò)向上查看具體的信息,分析后發(fā)現(xiàn)主要集中在 performance_schema,偶然發(fā)現(xiàn)了一個(gè)疑點(diǎn),那我們完全禁用掉 performance_schema 呢?

==9954== LEAK SUMMARY:==9954==    definitely lost: 0 bytes in 0 blocks==9954==    indirectly lost: 0 bytes in 0 blocks==9954==    possibly lost: 0 bytes in 0 blocks==9954==    still reachable: 32 bytes in 1 blocks==9954==         suppressed: 0 bytes in 0 blocks==9954====9954== For counts of detected and suppressed errors, rerun with: -v==9954== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

發(fā)現(xiàn)程序退出時(shí)幾乎沒(méi)有內(nèi)存未釋放,也不存在潛在的內(nèi)存泄漏。三次測(cè)試過(guò)后,發(fā)現(xiàn)結(jié)果是一致的。這是什么原因?

“ 大家都知道 MySQL 的 performance schema 用于監(jiān)控 MySQL server 在一個(gè)較低級(jí)別的運(yùn)行過(guò)程中的資源消耗、資源等待等情況,但它為什么可能會(huì)導(dǎo)致內(nèi)存泄漏呢,看來(lái)關(guān)于 ps 還有不少待挖掘的寶藏哦~ ”

 

最后一個(gè)小總結(jié)

1. 注意 MySQL 自身的內(nèi)存規(guī)劃,為保證 MySQL 的性能,innodb buffer pool 大小設(shè)置要合理,可以根據(jù)實(shí)例讀寫(xiě)負(fù)載的情況適當(dāng)調(diào)整 buffer pool 的大小。并且 innodb buffer 與連接會(huì)話(huà)內(nèi)存的總和盡量不要超過(guò)系統(tǒng)物理內(nèi)存。

2. 調(diào)整 oom_score_adj 參數(shù)(/proc/<pid>/oom_score_adj),將 MySQL 被 oom-killer 鎖定的優(yōu)先級(jí)降低。這個(gè)參數(shù)值越小,越不容易被鎖定。

3. 加強(qiáng)內(nèi)存的監(jiān)控和報(bào)警,一旦報(bào)警,DBA 應(yīng)該迅速介入,選擇性 Kill 掉一些占用較多內(nèi)存的連接。

4. 在開(kāi)啟 performance_schema 時(shí),會(huì)有額外的內(nèi)存開(kāi)銷(xiāo),通過(guò) valgrind-memcheck 內(nèi)存分析工具發(fā)現(xiàn),較大概率發(fā)生內(nèi)存泄漏。它有可能也會(huì)導(dǎo)致 OOM,在場(chǎng)景中若不需要 performance_schema 可以完全禁用,或需要盡量只開(kāi)啟必要的 instrument。

分享到:
標(biāo)簽:MySQL OOM
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定