本文將討論MySQL內存相關的一些選項,包括:html
單位都是b,不是kb,即1B=1/(1024*1024*1024)Gmysql
咱們只討論內存相關的選項,其餘一些如innodb_open_files
、thread_cache_size
、table_definition_cache
、table_open_cache
這類限制文件描述符合線程數量的選項不在討論之列sql
最近咱們在作的一個項目,須要檢查MySQL的理論內存上限,同事在http://www.mysqlcalculator.com/找到一個內存計算公式,以下所示:緩存
key_buffer_size
+ query_cache_size
+ tmp_table_size
+ innodb_buffer_pool_size
+ innodb_additional_mem_pool_size
+ innodb_log_buffer_size
+ max_connections
* (sort_buffer_size
+ read_buffer_size
+ read_rnd_buffer_size
+ join_buffer_size
+ thread_stack
+ binlog_cache_size
)服務器
show variables where variable_name in ( 'key_buffer_size', 'query_cache_size', 'tmp_table_size', 'innodb_buffer_pool_size', 'innodb_additional_mem_pool_size', 'innodb_log_buffer_size' ); show variables like 'max_connections'; show variables where variable_name in ( 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size' );
這個公式能夠說是錯的,由於,這個公式並不能很是準確的描述MySQL的實際內存使用狀況,實際內存使用狀況遠比這個公式要複雜,隨着具體的應用場景不一樣而存在差別。這個公式也能夠說是對的,由於,該公式大體估算了一個MySQL實例可能須要的內存,能夠做爲一個參考值。session
那麼,在實際應用中,咱們怎麼判斷具體的內存使用狀況?根據什麼條件來調整這些參數?調整爲多少比較合適呢?要回答這些問題,還得從原理講起。數據結構
在這一節,咱們首先對內存參數進行了一個分類,而後對各個參數的含義進行了詳細的討論。性能
服務器級別的buffer是全局且惟一的,影響全部的鏈接和查詢,須要注意的是,服務器級別的buffer中,大部分是服務器啓動的時候分配的,小部分是後來分配的。如query_cache,初始值是0,後續不斷增加,直至最大。線程
sql查詢語句日誌
show variables where variable_name in ( 'innodb_buffer_pool_size', 'innodb_log_buffer_size', 'innodb_additional_mem_pool_size', 'key_buffer_size', 'query_cache_size' );
這些buffer是線程級別的,對於每一個線程都會分配,所以,佔用的內存狀況爲max_connection * (thread_options),線程級別的選項有:
sql查詢語句
show variables where variable_name in ( 'net_buffer_length', 'thread_stack', 'query_prealloc_size', 'binlog_cache_size', 'binlog_stmt_cache_size' );
當服務器執行特殊操做時,根據須要分配緩衝區。所以,很難計算緩衝區的具體大小。好在這些緩衝區都是session級別的,咱們能夠保持全局較小的取值,若是須要,再修改session級別的緩衝區大小。
a.對每一個線程分配一次
sql查詢語句
show variables where variable_name in ( 'read_rnd_buffer_size', 'myisam_mmap_size', 'myisam_sort_buffer_size', 'bulk_insert_buffer_size', 'preload_buffer_size' );
b.對每一個線程分配屢次(可能)
show variables where variable_name in ( 'join_buffer_size', 'read_buffer_size', 'tmp_table_size' );
各個變量的含義比較好掌握,官方參考手冊上都有,可是,何時應該修改,修改成多少纔是合適的值?手冊上並無給出,本文將回答這個問題。
query_cache_size 這是MySQL的查詢緩存,用以緩衝SQL語句的結果,若是下次有相同的SQL語句,而且,結果尚未invalid掉,則直接返回查詢緩存中的結果便可。這是理想狀況,實際狀況query_cache可能致使激烈的鎖競爭,使得性能反而降低,MySQL 5.7已經能夠關閉query_cache了。
innodb_additional_mem_pool_size # (沒有查到mysql5.7_aliyun_RDS) 該緩存用以存放數據字典和內部數據結構的信息,通常狀況下,表越多,該選項也應該越大,該選項太小時,Innodb會在錯誤日誌中打印錯誤信息,能夠等到有錯誤日誌之後再調整。
innodb_buffer_pool_size Innodb爲存儲數據、索引、undo、自適應索引等分配的內存大小,影響innodb性能最重要的選項,通常設置爲物理內存的80%。
innodb_log_buffer_size Innodb重作日誌(redo)的大小,通常取默認值便可。
key_buffer_size MyISAM表緩存索引的緩存,建議不用MyISAM表。
net_buffer_length 服務器在客戶端鏈接創建之後建立的緩存大小,用來保持請求和結果。根據須要,這個大小能夠增加至max_allowed_packet。
thread_stack 每一個線程的棧大小,若是該變量設置太小,將會限制SQL語句的複雜性、存儲過程的遞歸深度,以及服務器上其餘內存消耗型的操做。對於大部分安裝來講,默認取值便可。若是有相似」Thread stack overrun」,則須要增大該值。
query_prealloc_size 此緩存爲語句解析和執行而分配,若是運行復雜查詢,增長緩存是合理的,這樣mysqld不會在執行查詢的時候在分配內存上耗時。
binlog_cache_size 緩存binlog的緩衝區,若是大於該值,緩存中的binlog將寫到磁盤的臨時文件中。
binlog_stmt_cache_size 緩存非事務表的binlog。
read_rnd_buffer_size 存放排序和發送結果至客戶端之間,讀取結果的大小,大的值能提升order by的性能
sort_buffer_size 每一個線程須要排序的時候會分配此緩存,經過檢查sort_merge_passes狀態變量來判斷是否須要增長該緩存的大小。sort_buffer_size緩存常常會分配,因此,大的GLOBAL值會下降性能而不是增長性能。所以,最好不要設置得太大,在須要的時候經過set session增長便可。
join_buffer_size 鏈接操做分配的緩衝區,爲了檢查是否須要增長join_buffer_size的取值,能夠檢查Select_sacn狀態變量,它包括第一張表執行完整掃描的鏈接次數,一樣,select_full_range_join,它包含使用範圍搜索的鏈接次數。
read_buffer_size 爲表順序掃描分配的緩存
tmp_table_size 臨時表的最大值,服務器默認設置爲max_heap_table_size和tmp_table_size二者中較小的一個,若是有足夠的內存,而且created_tmp_disk_tables狀態變量再增大,則能夠適當調大,把須要臨時表的全部結果保持在內存中,以提升性能。
原文摘自 http://mingxinglai.com/cn/2016/04/mysql-memory-usage-formula/