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

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

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

作者:孫祚龍

愛可生南區分公司交付服務部成員,實習工程師。負責公司產品問題排查及日常運維工作。

本文來源:原創投稿

*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯系小編并注明來源。


引言

前陣子處理這樣一個案例,某客戶的實例 MySQLd 進程內存經常持續增加導致最終被 OOM killer。作為 DBA 肯定想知道有哪些原因可能會導致 OOM(內存溢出)。

此篇文章敘述個人的一些拙見~

 

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

OOM Killer(Out of Memory Killer) 是當系統內存嚴重不足時 linux 內核采用的殺掉進程,釋放內存的機制。

OOM Killer 通過檢查所有正在運行的進程,然后根據自己的算法給每個進程一個 badness 分數,擁有最高 badness 分數的進程將會在內存不足時被殺掉。

它打分的算法如下:

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

上面打分的標準意味著,當 OOM killer 選擇殺死的進程時,將選擇一個使用大量內存,有很多子進程且不是系統進程的進程。

簡單來講,oom-killer 的原則就是損失最小、收益最大,因此它會讓殺死的進程數盡可能小、釋放的內存盡可能大。在數據庫服務器上,MySQL 被分配的內存一般不會小,因此容易成為 oom-killer 選擇的對象。

“既然發生了 OOM,那必然是內存不足,內存不足這個問題產生原因很多。

首先第一個就是 MySQL 自身內存的規劃有問題,這就涉及到 mysql 相應的配置參數。

另一個可以想到的原因就是一般部署 MySQL 的服務器,都會部署很多的監控和定時任務腳本,而這些腳本往往缺少必要的內存限制,導致在高峰期的時候占用大量的內存,導致觸發 Linux 的 oom-killer 機制,最終 MySQL 無辜躺槍犧牲。”

 

all-important:MySQL 自身內存規劃

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

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.

意思是在專用數據庫服務器上,可以將 innodb_buffer_pool_size 設置為計算機物理內存大小的 80%。在許許多多前輩的的經驗中了解到,此參數的值設置為物理內存的 50%~80% 頗為合理。

舉個栗子:

故障分析 | MySQL OOM 故障應如何下手

 

innodb buffer pool 分配 76G,每個連接線程最大可用 160M,最大有 3000 連接數,最大可能使用內存總量 545G,但是這臺實例所在服務器的物理內存僅僅有 97G,遠超物理內存總量。結果可想而知,這個實例在運行中經常被 oom-killer 殺死,想必原因之一即是因為一開始 MySQL 自身的內存規劃欠妥。

innodb buffer pool 緩存數據的作用相信大家都懂,比如這個 case 中,可以發現該實例為寫密集,讀請求很少,innodb buffer 對性能改善作用不大,80% 的內存沒必要,完全可以降低到物理內存的50%。

“ 以上是對 OOM 發生原因的一些見解,那思考一下還有沒有其他的原因會導致內存溢出的情況呢?不知道大家對內存泄漏是否了解,有沒有可能 MySQL 因為內存泄漏堆積演變為內存溢出,最終 oom-killer ... ”

 

知識補給站:內存泄漏

內存泄漏(Memory Leak)是指程序中己動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。

內存泄漏缺陷具有隱蔽性、積累性的特征,比其他內存非法訪問錯誤更難檢測。因為內存泄漏的產生原因是內存塊未被釋放,屬于遺漏型缺陷而不是過錯型缺陷。此外,內存泄漏通常不會直接產生可觀察的錯誤癥狀,而是逐漸積累,降低系統整體性能,極端的情況下可能使系統崩潰。

上文說到內存泄漏具有隱蔽性,就是不容易被發現唄......為之奈何?

那咱們就去找一個可以檢測內存泄漏的工具:valgrind

 

關于 valgrind 工具

Valgrind 是一個用于構建動態分析工具的工具框架。它提供了一組工具,每個工具都執行某種調試、分析或類似的任務,以幫助您改進程序。Valgrind 的體系結構是模塊化的,因此可以輕松地創建新工具,而不會影響現有的結構。

標配了許多有用的工具:

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

關于內存泄漏,我們需要使用 valgrind 的默認工具,也就是 memcheck 工具。

Memcheck 是內存錯誤檢測器。它可以檢測以下和內存相關的問題:

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

Valgrind Memcheck 工具的用法如下:

valgrind --tool=memcheck ./a.out

從上面的命令可以清楚地看到,主要的命令是“ Valgrind”,而我們要使用的工具由選項“ --tool”指定。上面的“ a.out ” 表示我們要在其上運行 memcheck 的可執行文件。此外還可以使用其他的命令行選項,以滿足我們的需要。運行的程序結束后,會生成這個進程的內存分析報告。

“ OK,工具有了,這就如同摸金校尉拿到了洛陽鏟,寶藏還會遠嗎~ 還不快找幾塊地挖掘試試?”

 

搞個測試找找感覺

1. 使用 valgrind 的 memcheck 工具啟動 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 模擬負載;

3. 進程結束后查看檢測報告:

==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)

在報告的最后的總結中發現程序退出時有部分內存未釋放,而且存在潛在的內存泄漏。通過向上查看具體的信息,分析后發現主要集中在 performance_schema,偶然發現了一個疑點,那我們完全禁用掉 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)

發現程序退出時幾乎沒有內存未釋放,也不存在潛在的內存泄漏。三次測試過后,發現結果是一致的。這是什么原因?

“ 大家都知道 MySQL 的 performance schema 用于監控 MySQL server 在一個較低級別的運行過程中的資源消耗、資源等待等情況,但它為什么可能會導致內存泄漏呢,看來關于 ps 還有不少待挖掘的寶藏哦~ ”

 

最后一個小總結

1. 注意 MySQL 自身的內存規劃,為保證 MySQL 的性能,innodb buffer pool 大小設置要合理,可以根據實例讀寫負載的情況適當調整 buffer pool 的大小。并且 innodb buffer 與連接會話內存的總和盡量不要超過系統物理內存。

2. 調整 oom_score_adj 參數(/proc/<pid>/oom_score_adj),將 MySQL 被 oom-killer 鎖定的優先級降低。這個參數值越小,越不容易被鎖定。

3. 加強內存的監控和報警,一旦報警,DBA 應該迅速介入,選擇性 Kill 掉一些占用較多內存的連接。

4. 在開啟 performance_schema 時,會有額外的內存開銷,通過 valgrind-memcheck 內存分析工具發現,較大概率發生內存泄漏。它有可能也會導致 OOM,在場景中若不需要 performance_schema 可以完全禁用,或需要盡量只開啟必要的 instrument。

分享到:
標簽:MySQL OOM
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定