Innodb存儲引擎內存報警問題處理過程

1 不停的收到email報警,內存值超過閥值80%了。


2 top下,mysqld進程確實佔據了77.5%,再加上一些其他的輔助進程,內存usage到了81%也可以理解。

[xxx@00903 5.5.25a]$ top
top - 03:48:55 up 51 days, 17:11,  2 users,  load average: 0.09, 0.09, 0.11
Tasks: 202 total,   1 running, 201 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.1%sy,  0.0%ni, 98.8%id,  0.8%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  28743468k total, 28452540k used,   290928k free,   467048k buffers
Swap:  4194296k total,        0k used,  4194296k free,  4589332k cached


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
23956 mysql     20   0 24.1g  21g 5408 S  1.0 77.5 390:56.59 mysqld                                                                                                                            
    9 root      20   0     0    0    0 S  0.3  0.0 203:16.51 ksoftirqd/1                                                                                                                       
23971 mmmd      20   0  687m  64m 1960 S  0.3  0.2  73:53.23 perl                                                                                                                              
    1 root      20   0 21444 1232  928 S  0.0  0.0   1:29.37 init                                                                                                                              
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.44 kthreadd                                                                                                                          


3 看看free -m吧
[xxx@00903 ~]$ free -m
             total       used       free     shared    buffers     cached
Mem:         28069      27828        240          0        440       
-/+ buffers/cache:      22820       5249
Swap:         4095          0       4095
[xxx@00903 ~]$ 


4 簡要分析理解free -m參數值意義
total: 28069,總內存大小。
used: 27828,已經使用過的內存大小。
free:240,剩餘的內存大小。
total值是used+free的值總合:
  1. mysql> select 27828+240;  
  2. +-----------+  
  3. | 27828+240 |  
  4. +-----------+  
  5. |     28068 |  
  6. +-----------+  
  7. 1 row in set (0.00 sec)  
  8. -- 總和28068與28069差了一個1,可能是-m四捨五入造成的。  
  9. mysql>   


shared 不同進程間用來進行數據交換的地方,一般都是0(多個進程共享的內存總額)。
cached:4568,經常被用在磁盤的I/O請求上,如果有多個進程都要訪問某個文件,於是該文件便被做成cache以方便下次被訪問,這樣可提供系統性能。



我們監控的是-/+ buffers/cache:中的useed一項22820, 總內存大小是 28069,因此一計算,確實爲81%

  1. mysql>   
  2. mysql> SELECT 22828/28069;  
  3. +-------------+  
  4. | 22828/28069 |  
  5. +-------------+  
  6. |      0.8133 |  
  7. +-------------+  
  8. 1 row in set (0.00 sec)  
  9.   
  10. mysql>   


而且-/+ buffers/cache中的後面的used+free的總合也與第一行的Mem的total值相等:
  1. mysql> SELECT 22820+5249;  
  2. +------------+  
  3. | 22820+5249 |  
  4. +------------+  
  5. |      28069 |  
  6. +------------+  
  7. 1 row in set (0.00 sec)  


目前沒有找到問題所在,去查閱一些基礎文檔,有很多東西時間一長不用,都快要遺忘了

5 buffers與cached的分析

對操作系統來講是Mem的參數buffers和cached 都是屬於被使用,它認爲free只有752M。
        對應用程序來講是(-/+ buffers/cach),buffers和cached 是等同可用的,buffer和cached是爲了提高程序執行的性能,當程序使用內存時,buffer和cached會很快地被使用。
        以應用來看看,以(-/+ buffers/cache)的free和used爲主.我們看這個就好了.Linux爲了提高磁盤和內存存取效率, 開發人員做了很多精心的設計, 除了對dentry進行緩存(用於VFS,加速文件路徑名到inode的轉換), 還採取了兩種主要Cache方式:Buffer Cache和Page Cache.前者針對磁盤塊的讀寫,後者針對文件inode的讀寫.這些Cache能有效縮短了 I/O系統調用(比如read,write,getdents)的時間.


6 innodb_buffer_pool_size(global)

當我們使用InnoDB存儲引擎的時候,innodb_buffer_pool_size 參數可能是影響我們性能的最爲關鍵的一個參數了,他用來設置用於緩存 InnoDB 索引及數據塊的內存區域大小,類似於 MyISAM 存儲引擎的 key_buffer_size 參數,當然,可能更像是 Oracle 的 db_cache_size。簡單來說,當我們操作一個 InnoDB 表的時候,返回的所有數據或者去數據過程中用到的任何一個索引塊,都會在這個內存區域中走一遭。

和key_buffer_size 對於 MyISAM 引擎一樣,innodb_buffer_pool_size 設置了 InnoDB 存儲引擎需求最大的一塊內存區域的大小,直接關係到 InnoDB存儲引擎的性能,所以如果我們有足夠的內存,儘可將該參數設置到足夠打,將儘可能多的 InnoDB 的索引及數據都放入到該緩存區域中,直至全部。

我們可以通過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算緩存命中率,並根據命中率來調整 innodb_buffer_pool_size 參數大小進行優化。


MySQL Query Cache

在大部分的 MySQL 分發版本中,Query Cache 功能默認都是打開的,我們可以通過調整 MySQL Server 的參數選項打開該功能。主要由以下5個參數構成:

  • query_cache_limit:允許 Cache 的單條 Query 結果集的最大容量,默認是1MB,超過此參數設置的 Query 結果集將不會被 Cache
  • query_cache_min_res_unit:設置 Query Cache 中每次分配內存的最小空間大小,也就是每個 Query 的 Cache 最小佔用的內存空間大小
  • query_cache_size:設置 Query Cache 所使用的內存大小,默認值爲0,大小必須是1024的整數倍,如果不是整數倍,MySQL 會自動調整降低最小量以達到1024的倍數
  • query_cache_type:控制 Query Cache 功能的開關,可以設置爲0(OFF),1(ON)和2(DEMAND)三種,意義分別如下:
    • 0(OFF):關閉 Query Cache 功能,任何情況下都不會使用 Query Cache
    • 1(ON):開啓 Query Cache 功能,但是當 SELECT 語句中使用的 SQL_NO_CACHE 提示後,將不使用Query Cache
    • 2(DEMAND):開啓 Query Cache 功能,但是隻有當 SELECT 語句中使用了 SQL_CACHE 提示後,才使用 Query Cache
  • query_cache_wlock_invalidate:控制當有寫鎖定發生在表上的時刻是否先失效該表相關的 Query Cache,如果設置爲 1(TRUE),則在寫鎖定的同時將失效該表相關的所有 Query Cache,如果設置爲0(FALSE)則在鎖定時刻仍然允許讀取該表相關的 Query Cache。

重新補充了mysql的緩存基礎知識,然後根據slow log查到了有一些慢sql,可是如何釋放已經的緩存呢? 用了flush query cache; 沒有效果,內存使用率仍然在81%。


知道mysql在執行查詢的時候,特別是需要table scan的時候,數據是一點點進入內存的,在mysql的buffer pool中有鏈表結構的存在,page是io的基本單位,一個個的page讀進去,即使只訪問一條記錄,也要讀一個page,這是沒辦法的事情,table scan的表記錄數越多,讀到內存的page就越多,這樣內存就慢慢漲到了81%了。正常處理流程是:當內存漲的時候首先是swap,在swap加警告,然後告警後關掉swap,之後就是排查問題,沒必要內存到90%就搞掉。


記得Mysql不都是會自動釋放內存資源的嗎?爲什麼線上的db沒有釋放,這只是一臺replication從庫,用來做備份恢復所用的,沒有應用業務在使用。

發佈了37 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章