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的值總合:
- mysql> select 27828+240;
- +-----------+
- | 27828+240 |
- +-----------+
- | 28068 |
- +-----------+
- 1 row in set (0.00 sec)
- -- 總和28068與28069差了一個1,可能是-m四捨五入造成的。
- mysql>
shared 不同進程間用來進行數據交換的地方,一般都是0(多個進程共享的內存總額)。
cached:4568,經常被用在磁盤的I/O請求上,如果有多個進程都要訪問某個文件,於是該文件便被做成cache以方便下次被訪問,這樣可提供系統性能。
我們監控的是-/+ buffers/cache:中的useed一項22820, 總內存大小是 28069,因此一計算,確實爲81%
- mysql>
- mysql> SELECT 22828/28069;
- +-------------+
- | 22828/28069 |
- +-------------+
- | 0.8133 |
- +-------------+
- 1 row in set (0.00 sec)
- mysql>
而且-/+ buffers/cache中的後面的used+free的總合也與第一行的Mem的total值相等:
- mysql> SELECT 22820+5249;
- +------------+
- | 22820+5249 |
- +------------+
- | 28069 |
- +------------+
- 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 參數大小進行優化。
7 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從庫,用來做備份恢復所用的,沒有應用業務在使用。