MySQL運行內存不足時應採起的措施?

排除故障指南:MySQL運行內存不足時應採起的措施?

天一閣@ 老葉茶館 1周前

導讀php

排除故障指南:MySQL運行內存不足時應採起的措施?java

翻譯團隊:知數堂藏經閣項目 - 天一閣python

團隊成員:天一閣-冷鋒、 天一閣-Judy 、天一閣-神諭mysql

譯文校稿:葉師傅linux

原文出處:《What To Do When MySQL Runs Out of Memory: Troubleshooting Guide》web

https://www.percona.com/blog/2018/06/28/what-to-do-when-mysql-runs-out-of-memory-troubleshooting-guide/sql

原文做者:Alexander Rubin緩存

關鍵詞:memory、memory leaks、Memory Usage、MySQL server memory usage、MySQL Troubleshooting、Troubleshooting MySQL、troubleshooting tips服務器

Troubleshooting crashes is never a fun task, especially if MySQL does not report the cause of the crash. For example, when MySQL runs out of memory. Peter Zaitsev wrote a blog post in 2012: Troubleshooting MySQL Memory Usage with a lots of useful tips. With the new versions of MySQL (5.7+) and performance_schema we have the ability to troubleshoot MySQL memory allocation much more easily。
崩潰故障診斷毫不是一個有趣的任務,尤爲若是MySQL沒有報告崩潰的緣由時,例如MySQL運行時內存溢出。Peter Zaitsev 在2012年寫了一篇文章Troubleshooting MySQL Memory Usage 裏面有不少有用的提示,使用新版本MySQL(5.7+)結合performance_schema,咱們能夠更輕鬆地解決MySQL內存分配問題。app

In this blog post I will show you how to use it.

First of all, there are 3 major cases when MySQL will crash due to running out of memory:

  1. MySQL tries to allocate more memory than available because we specifically told it to do so. For example: you did not set innodb_buffer_pool_size correctly. This is very easy to fix

  2. There is some other process(es) on the server that allocates RAM. It can be the application (java, python, php), web server or even the backup (i.e. mysqldump). When the source of the problem is identified, it is straightforward to fix.

  3. Memory leaks in MySQL. This is a worst case scenario, and we need to troubleshoot.

在這篇博文中,我將向你展現如何使用它。

首先,MySQL由於內存溢出發生崩潰主要有如下三種狀況:

  1. MySQL試圖分配比可用內存更多的內存,由於咱們特地告訴它這樣作;好比你沒有正確的設置innodb_buffer_pool_size,那這種狀況很好解決。

  2. 服務器上有其餘一些進程分配了RAM內存,多是應用程序(java/python/php)、web服務器,或者甚至備份(好比mysqldump),肯定問題的根源後,能夠直接修復。

  3. MySQL內存泄漏,這是最糟糕的狀況,這時須要咱們進行故障診斷。

 

Where to start troubleshooting MySQL memory leaks

 

從哪裏開始診斷MySQL內存泄漏的問題

Here is what we can start with (assuming it is a Linux server):

假設是一個linux服務器,咱們能夠從如下開始:

Part 1: Linux OS and config check

  1. Identify the crash by checking mysql error log and Linux log file (i.e. /var/log/messages or /var/log/syslog). You may see an entry saying that OOM Killer killed MySQL. Whenever MySQL has been killed by OOM 「dmesg」 also shows details about the circumstances surrounding it.

  2. Check the available RAM:

    1. free -g

    2. cat /proc/meminfo

  3. Check what applications are using RAM: 「top」 or 「htop」 (see the resident vs virtual memory)

  4. Check mysql configuration: check /etc/my.cnf or in general /etc/my* (including /etc/mysql/* and other files). MySQL may be running with the different my.cnf (run ps ax| grep mysql )

  5. Run vmstat 5 5 to see if the system is reading/writing via virtual memory and if it is swapping

  6. For non-production environments we can use other tools (like Valgrind, gdb, etc) to examine MySQL usage

第一部分: Linux 系統和配置檢查

  1. 經過檢查mysql error日誌和linux日誌(好比,/var/log/messages 或者 /var/log/syslog)確認崩潰。你可能會看到一條條目說OOM Killer殺死了MySQL,每當MySQL被OOM殺死時,「dmesg」也會顯示有關它周圍狀況的詳細信息。

  2. 檢查可用的RAM內存:

    1. free -g

    2. cat /proc/meminfo

  3. 檢查什麼程序在使用內存:"top"或者htop(看resident和virtual列)

  4. 檢查mysql的配置:檢查/etc/my.cnf或者通常的/etc/my*(包括/etc/mysql/*和其餘文件);
    MySQL 可能跟着不一樣的my.cnf運行(用ps ax | grep mysql)

  5. 運行vmstat 5 5 查看系統是否經過虛擬內存進行讀寫以及是否正在進行swap交換

  6. 對於非生產環境,咱們可使用其餘工具(如Valgrind、gdb等)來檢查MySQL的使用狀況。

Part 2: Checks inside MySQL
Now we can check things inside MySQL to look for potential MySQL memory leaks.
MySQL allocates memory in tons of places. Especially:

  1. Table cache

  2. Performance_schema (run: show engine performance_schema status and look at the last line). That may be the cause for the systems with small amount of RAM, i.e. 1G or less

  3. InnoDB (run show engine innodb status and check the buffer pool section, memory allocated for buffer_pool and related caches)

  4. Temporary tables in RAM (find all in-memory tables by running: select * from information_schema.tables where engine='MEMORY' )

  5. Prepared statements, when it is not deallocated (check the number of prepared commands via deallocate command by running show global status like ‘ Com_prepare_sql';show global status like 'Com_dealloc_sql' )

第二部分: 檢查MySQL內部

如今咱們能夠檢查MySQL內部的東西來尋找潛在的MySQL內存泄漏狀況:
MySQL在不少地方分配內存,尤爲:

  1. 表緩存

  2. Performance_schema(運行:show engine performance_schema status 而後看最後一行),這可能在系統RAM比較少(1G或更少)時的可能緣由。

  3. InnoDB(運行show engine innodb status 檢查 buffer pool部分,爲buffer pool及相關緩存分配的內存)

  4. 內存中的臨時表(查看全部內存表:select * from information_schema.tables where engine='MEMORY')

  5. 預處理語句,當他們沒有被釋放時(經過運行show global status like 'Com_prepare_sql'和show global status like 'Com_dealloc_sql'來檢查經過deallocate命令釋放的預處理語句)

The good news is: starting with MySQL 5.7 we have memory allocation in performance_schema. Here is how we can use it.
好消息是,從5.7開始咱們能夠經過performance_schema查看內存的分配狀況。下面就展現如何使用它:

  • First, we need to enable collecting memory metrics. Run:

UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
  • Run the report from sys schema:

select event_name, current_alloc, high_alloc from sys.memory_global_by_current_bytes where current_count > 0;
  • Usually this will give you the place in code when memory is allocated. It is usually self-explanatory. In some cases we can search for bugs or we might need to check the MySQL source code.

  • 首先,咱們須要啓用收集內存指標,運行以下語句:

UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
  • 運行sys schema裏面的報告

select event_name,current_alloc,high_alloc from sys.memory_global_by_current_bytes where current_count > 0;
  • 一般,這將在分配內存時爲你提供代碼,它一般是不言自明的。在某些狀況下,咱們能夠搜索錯誤,或者咱們可能須要檢查MySQL源代碼。

For example, for the bug where memory was over-allocated in triggers (https://bugs.mysql.com/bug.php?id=86821) the select shows:

例如,有一個過分爲觸發器分配內存的bug:

https://bugs.mysql.com/bug.php?id=86821

查詢的顯示以下:

The largest chunk of RAM is usually the buffer pool but ~3G in stored procedures seems to be too high.
分配最大一塊內存一般是buffer pool,可是約3G的存儲過程彷佛有點過高了.

According to the MySQL source code documentation, sp_head represents one instance of a stored program which might be of any type (stored procedure, function, trigger, event). In the above case we have a potential memory leak.
根據MySQL source code documentation,sp_head表示存儲程序裏面的一個實例(好比存儲過程、函數、觸發器,及事件)。在上面的例子,咱們有潛在的內存泄漏的風險。

In addition we can get a total report for each higher level event if we want to see from the birds eye what is eating memory:
另外,咱們想要鳥瞰什麼吃掉了內存,咱們能夠得到每一個事件更高級別活動的整體報告。

I hope those simple steps can help troubleshoot MySQL crashes due to running out of memory.
我但願這些簡單的步驟能夠幫助解決因爲內存溢出致使的MySQL崩潰問題。

 

加入知數堂

挑戰40萬+年薪!

 

 

 

知數堂

葉金榮與吳炳錫聯合打造

領跑IT精英培訓

行業資深專家強強聯合,傾心定製

MySQL實戰/MySQL優化/MongoDB/

Python/ SQL優化/Hadoop+ELK

數門精品課程

「閱讀原文」可獲更多正課試聽視頻

密碼:hg3h

緊隨技術發展趨勢,按期優化培訓教案

融入大量生產案例,貼合企業一線需求

社羣陪伴學習,一次報名,可學1年

DBA、開發工程師必修課

上千位學員已華麗轉身,薪資翻番,職位提高

改變已悄然發生,你還在等什麼?

 

 

掃碼加入QQ技術交流羣

MySQL 8.0|MGR研究院-ZST

(QQ羣號:650149401)    

文章已於 2019-01-11修改
閱讀原文
閱讀  1376
 
精選留言

寫留言

  •  
    公司有幾臺用寶塔搭建的服務器,Mysql經常掛掉,後來升了內存就沒事了……打算對着文章找找緣由去 謝謝分享
相關文章
相關標籤/搜索