[Lnmpa] Mysql 5.6 內存配置&優化方案

MySQL介紹
MySQL是一個關係型數據庫管理系統,由瑞典MySQL AB 公司開發,目前屬於 Oracle 旗下產品。MySQL 是最流行的關係型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關係數據庫管理系統) 應用軟件。

MySQL內存計算方式
全局內存消耗(共享內存)[單純MYSQL服務(不計算連接佔用內存)單位 M]:

MYSQL_Service_Mem = key_buffer_size + innodb_buffer_pool_size + tmp_table_size + query_cache_size + innodb_additional_mem_pool_size + innodb_log_buffer_size

也可以用SQL命令:select (@@key_buffer_size +@@innodb_buffer_pool_size+ @@tmp_table_size +@@query_cache_size +@@innodb_additional_mem_pool_size +@@innodb_log_buffer_size )/1024/1024 as “MYSQL_Service_Mem”;

直接在MysQL命令提示符裏輸入就可以輸出結果。

MYSQL服務最大使用內存(包含連接訪問數據庫)單位 M:

MYSQL_Service_Max_Mem = key_buffer_size + innodb_buffer_pool_size + tmp_table_size + query_cache_size + innodb_additional_mem_pool_size + innodb_log_buffer_size + max_connections * ( read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size + binlog_cache_size + thread_stack )

也可以用SQL命令:select (@@key_buffer_size +@@innodb_buffer_pool_size+ @@tmp_table_size +@@query_cache_size +@@innodb_additional_mem_pool_size +@@innodb_log_buffer_size + @@max_connections*(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@binlog_cache_size + @@thread_stack) )/1024/1024 as “MYSQL_Service_Max_Mem”;

直接在MysQL命令提示符裏輸入就可以輸出結果。

會話級別的內存消耗(連接私有內存)[Mysql 單個連接最大佔內存,單位 M]:

MYSQL_Service_Connect_Mem = read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size + binlog_cache_size + thread_stack

也可以用SQL命令:select (@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@binlog_cache_size + @@thread_stack)/1024/1024 as “MYSQL_Service_Connect_Mem”;

直接在MysQL命令提示符裏輸入就可以輸出結果。

MYSQL優化舉例
例如一臺2G內存的服務器,安裝有Nginx、Apache、Php、Mysql等的環境,準備劃分128MB~512MB的內存區間給MySQL使用。

首先就可以配置 MYSQL_Service_Mem( key_buffer_size + innodb_buffer_pool_size + tmp_table_size + query_cache_size + innodb_additional_mem_pool_size + innodb_log_buffer_size )這三個參數,保持在128MB左右。

MYSQL_Service_Mem = key_buffer_size (32MB)+ innodb_buffer_pool_size(32MB)+ tmp_table_size(32MB)+ query_cache_size(8MB) + innodb_additional_mem_pool_size(0MB) + innodb_log_buffer_size(8MB)= 112MB

key_buffer_size 參數:(MyISAM)

對MyISAM表起作用。即使你不使用MyISAM表,但是內部的臨時磁盤表是MyISAM表,也要使用該值。可以使用檢查狀態值created_tmp_disk_tables得知詳情。

如果你使它太大,系統將開始換頁並且真的變慢了。嚴格說是它決定了數據庫索引處理的速度,尤其是索引讀的速度。

對於1G內存的機器,如果不使用MyISAM表,推薦值是16M(8-64M)

怎麼才能知道key_buffer_size的設置是否合理呢,一般可以檢查狀態值Key_read_requests和Key_reads ,比例key_reads / key_read_requests應該儘可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like ‘key_read%’;

比如查看系統當前key_read和key_read_request值爲:

+——————-+———————–+
| Variable_name | Value |
+——————-+———————–+
| Key_read_requests | 28535 |
| Key_reads | 269 |
+——————-+———————–+

可知道有28535個請求,有269個請求在內存中沒有找到直接從硬盤讀取索引。未命中緩存的概率爲:0.94%=269/28535*100%。一般未命中概率在0.1之下比較好,目前已遠遠大於0.1,證明效果不好。若命中率在0.01以下,則建議適當的修改key_buffer_size值。

innodb_buffer_pool_size 參數:(InnoDB)

主要針對InnoDB表性能影響最大的一個參數。功能與Key_buffer_size一樣。InnoDB佔用的內存,除innodb_buffer_pool_size用於存儲頁面緩存數據外,另外正常情況下還有大約8%的開銷,主要用在每個緩存頁幀的描述、adaptive hash等數據結構,如果不是安全關閉,啓動時還要恢復的話,還要另開大約12%的內存用於恢復,兩者相加就有差不多21%的開銷。假設:12G的innodb_buffer_pool_size,最多的時候InnoDB就可能佔用到14.5G的內存。若系統只有16G,而且只運行MySQL,且MySQL只用InnoDB,那麼爲MySQL開12G,是最大限度地利用內存了。

另外InnoDB和 MyISAM 存儲引擎不同, MyISAM 的 key_buffer_size 只能緩存索引鍵,而 innodb_buffer_pool_size 卻可以緩存數據塊和索引鍵。適當的增加這個參數的大小,可以有效的減少 InnoDB 類型的表的磁盤 I/O 。

怎麼才能知道innodb_buffer_pool_size的設置是否合理呢,可以通過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算緩存命中率,並根據命中率來調整 innodb_buffer_pool_size 參數大小進行優化。值可以用以下命令查得:show status like ‘Innodb_buffer_pool_read%’;

比如查看當前系統中系統中

+—————————————+———+
| Innodb_buffer_pool_read_requests | 1283826 |
| Innodb_buffer_pool_reads | 519 |
+—————————————+———+

其命中率99.959% =(1283826-519)/1283826*100% 命中率越高越好。

tmp_table_size 參數:

控制內存臨時表的最大值,超過限值後就往硬盤寫,寫的位置由變量 tmpdir 決定。

通過設置tmp_table_size選項來增加一張臨時表的大小,例如做高級分組排序操作生成的臨時表。如果調高該值,MySQL同時將增加heap表的大小,可達到提高聯接查詢速度的效果,建議儘量優化查詢,要確保查詢過程中生成的臨時表在內存中,避免臨時表過大導致生成基於硬盤的MyISAM表。

怎麼才能知道tmp_table_size的設置是否合理呢,可以通過 Created_tmp_disk_tables / Created_tmp_tables * 100% 計算緩存命中率,並根據命中率來調整 tmp_table_size 參數大小進行優化。值可以用以下命令查得:show global status like ‘created_tmp%’;

+——————————–+———+
| Variable_name   | Value |
+———————————-+———+
| Created_tmp_disk_tables | 21197 |
| Created_tmp_files   | 58  |
| Created_tmp_tables  | 1771587 |
+——————————–+———–+

未命中率爲:Created_tmp_disk_tables / Created_tmp_tables * 100% =1.20%,數字越低越好。

query_cache_size 參數:

MySQL對於查詢的結果會進行緩存來節省解析SQL、執行SQL的花銷,query_cache是按照SQL語句的Hash值進行緩存的,同時SQL語句涉及的表發生更新,該緩存就會失效,所以這個緩存對於特定的讀多更新少的庫比較有用,對於絕大多數更新較多的庫可能不是很適用,比較受限於應用場景,所以AWS也把這個緩存給關了。我覺得這個值默認應該關閉,根據需求調整。

Query Cache的使用需要多個參數配合,其中最爲關鍵的是query_cache_size和query_cache_type,前者設置用於緩存 ResultSet的內存大小,後者設置在何場景下使用Query Cache。query_cache_type可以設置爲0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩衝. 如果Qcache_hits的值也非常大,則表明查詢緩衝使用非常頻繁,此時需要增加緩衝大小;

怎麼才能知道query_cache_size的設置是否合理呢,命中率:(Qcache_hits/(Qcache_hits+Qcacheinserts)*100))進行調整,通過命令:show status like ‘Qcache%’;

+————————-+———–+
| Variable_name | Value |
+————————-+———–+
| Qcache_hits | 1892463 |
| Qcache_inserts | 35627 |
+————————-+———–+

命中率 98.17% = 1892463/(1892463 +35627 )*100,命中率越高越好。

innodb_additional_mem_pool_size 參數:

這個參數用來設置 InnoDB 存儲的數據目錄信息和其它內部數據結構的內存池大小。應用程序裏的表越多,你需要在這裏分配越多的內存。對於一個相對穩定的應用,這個參數的大小也是相對 穩定的,也沒有必要預留非常大的值。如果 InnoDB 用光了這個池內的內存, InnoDB 開始從操作系統分配內存,並且往 MySQL 錯誤日誌寫警告信息。默認值是 1MB ,當發現錯誤日誌中已經有相關的警告信息時,就應該適當的增加該參數的大小。

自從Msql 5.6.3 開始,就不需要這個參數。

innodb_log_buffer_size 參數:

這是InnoDB存儲引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer,InnoDB在寫事務日誌的時候,爲了提高性能,也是先將信息寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit參數所設置的相應條件(或者日誌緩衝區寫滿)之後,纔會將日誌寫到文件 (或者同步到磁盤)中。可以通過innodb_log_buffer_size 參數設置其可以使用的最大內存空間。

這個值的大小主要影響到刷磁盤的次數,設置的過小,Buffer容易滿,就會增加fsync的次數,設置過大,佔用內存。該值默認是8M,個人覺得目前每次提交都會刷buffer,所以除非有大事務的情況,一般buffer不太可能被佔滿,所以沒必要開的很大, 8M應該是滿足需求的。

然後再配置每個連接佔用內存大小:MYSQL_Service_Connect_Mem = read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size + binlog_cache_size + thread_stack,計劃512MB分配給Mysql使用,剛剛已經分配了112MB的內存,剩下384MB內存,這個時候就需要考慮最大的連接數,因爲這個參數對連接內存影響很大,計劃最大連接數爲128個,那麼每個連接的內存就佔用3MB左右。

MYSQL_Service_Connect_Mem = read_buffer_size (0.25MB) + read_rnd_buffer_size (0.5MB) + sort_buffer_size (0.5MB) + join_buffer_size (0.25MB) + binlog_cache_size (1MB) + thread_stack (0.25MB) = 2.75MB

那麼連接數max_connections可以設置爲:384/2.75=139個

read_buffer_size 參數:

是MySql讀入緩衝區大小,對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會爲它分配一段內存緩衝區,read_buffer_size變量控制這一緩衝區的大小,如果對錶的順序掃描請求非常頻繁,並且你認爲頻繁掃描進行得太慢,可以通過增加該變量值以及內存緩衝區大小提高其性能。

256K適用於512MB內存,1GB內存則可以設置成1M,依次類推即可。

read_rnd_buffer_size 參數:

當以任意順序讀取行時,可以分配隨機讀取緩衝區,通過該緩衝區讀取行,以避免磁盤尋找。read_rnd_buffer_size系統變量決定緩衝器大小。但MySql會爲每個客戶連接發放該緩衝空間,所以應儘量適當設置該值,以避免內存開銷過大。

512K使用於 512MB內存,1GB內存則可以設置成1MB,依次類推即可。

sort_buffer_size 參數:

每一個要做排序的請求,都會分到一個sort_buffer_size大的緩存,用於做order by和group by的排序,如果設置的緩存大小無法滿足需要,MySQL會將數據寫入磁盤來完成排序。因爲磁盤操作和內存操作不在一個數量級,所以sort_buffer_size對排序的性能影響很大。由於這部分緩存是即使不用這麼大,也會全部分配的,所以對系統內存分配開銷是比較大的,如果是希望擴大的話,建議在會話層設置,默認值2M。

512K使用於 512MB內存,1GB內存則可以設置成1MB,依次類推即可。

join_buffer_size 參數:

MySQL服務器用來作普通索引掃描、範圍索引掃描和不使用索引而執行全表掃描這些操作所用的緩存大小。通常,獲取最快連接的方法是增加索引。當不能增加索引的時候,使全連接變快的方法是增大join_buffer_size參數。對於執行全連接的兩張表,每張表都被分配一塊連接內存。對於沒有使用索引的多表複雜連接,需要多塊連接內存。通常來說,可以將此參數在全局上設置一個較小的值,而在需要執行大連接的會話中在會話級別進行設置。默認值是256KB。

binlog_cache_size 參數:

類似於innodb_log_buffer_size緩存事務日誌,binlog_cache_size緩存Binlog,不同的是這個是每個線程單獨一個,主要對於大事務有較大性能提升。默認32K。

如果設置太大的話,會比較消耗內存資源(Cache本質就是內存),更加需要注意的是:binlog_cache是不是全局的,是按SESSION爲單位獨享分配的,也就是說當一個線程開始一個事務的時候,Mysql就會爲這個SESSION分配一個binlog_cache。

設置太小的話,如果用戶提交一個“長事務(long_transaction)”,比如:批量導入數據。那麼該事務必然會產生很多binlog,這樣cache可能不夠用(默認binlog_cache_size是32K),不夠用的時候mysql會把uncommitted的部分寫入臨時文件(臨時文件cache的效率必然沒有內存cache高),等到committed的時候纔會寫入正式的持久化日誌文件。

如何查看設置的binlog_cachesize是否夠用,可以使用命令:show status like ‘binlog%’;

+———————–+———–+
| Variable_name | Value |
+———————–+———–+
| Binlog_cache_disk_use | 0 |
| Binlog_cache_use | 120402264 |
+———————–+———–+

運行情況Binlog_cache_use 表示binlog_cache內存方式被用上了多少次,Binlog_cache_disk_use表示binlog_cache臨時文件方式被用上了多少次。Binlog_cache_disk_use現在等於0,表示內存cache是夠用的,從來不需要使用到臨時文件。

thread_stack 參數:

默認256K,MySQL爲每個線程分配的堆棧大小,當線程堆棧太小時,這限制了服務器可以處理的SQL語句的複雜性。這個值一般認爲默認就可以應用於大部分場景了,除非必要非則不要動它。

互聯網也有類似計算MysqL佔用內存的網站:http://www.mysqlcalculator.com/

個人博客:https://blog.daobidao.com/lnmpa-mysql-5-6-mem-configure-optimize.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章