MySQL的內存計算

本文將討論MySQL內存相關的一些選項,包括:

單位都是b,不是kb,即1B=1/(1024*1024*1024)G

  • 1)全局的buffer,如innodb_buffer_pool_size;
  • 2)線程級的選項,如binlog_cache_size;
  • 3)爲特定操作分配的緩衝區,如sort_buffer_size。

我們只討論內存相關的選項,其他一些如innodb_open_filesthread_cache_sizetable_definition_cachetable_open_cache這類限制文件描述符合線程數量的選項不在討論之列

1. MySQL的理論內存上限

最近我們在做的一個項目,需要檢查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實例可能需要的內存,可以作爲一個參考值。

那麼,在實際應用中,我們怎麼判斷具體的內存使用情況?根據什麼條件來調整這些參數?調整爲多少比較合適呢?要回答這些問題,還得從原理講起。

2. MySQL內存參數的含義

在這一節,我們首先對內存參數進行了一個分類,然後對各個參數的含義進行了詳細的討論。

2.1 內存參數分類

2.1.1 服務器級別

服務器級別的buffer是全局且唯一的,影響所有的連接和查詢,需要注意的是,服務器級別的buffer中,大部分是服務器啓動的時候分配的,小部分是後來分配的。如query_cache,初始值是0,後續不斷增長,直至最大。

  • innodb_additional_mem_pool_size # 該參數查不到
  • innodb_buffer_pool_size
  • innodb_log_buffer_size
  • key_buffer_size
  • query_cache_size

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'
);
2.1.2 線程級別

這些buffer是線程級別的,對於每個線程都會分配,因此,佔用的內存情況爲max_connection * (thread_options),線程級別的選項有:

  • binlog_cache_size
  • binlog_stmt_cache_size
  • net_buffer_length
  • query_prealloc_size
  • thread_stack

sql查詢語句

show variables where variable_name in (
'net_buffer_length',
'thread_stack',
'query_prealloc_size',
'binlog_cache_size',
'binlog_stmt_cache_size'
);
2.1.3 爲特定操作分配的緩衝區

當服務器執行特殊操作時,根據需要分配緩衝區。因此,很難計算緩衝區的具體大小。好在這些緩衝區都是session級別的,我們可以保持全局較小的取值,如果需要,再修改session級別的緩衝區大小。

a.對每個線程分配一次

  • read_rnd_buffer_size
  • sort_buffer_size
  • myisam_mmap_size
  • myisam_sort_buffer_size
  • bulk_insert_buffer_size
  • preload_buffer_size

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.對每個線程分配多次(可能)

  • join_buffer_size
  • read_buffer_size
  • tmp_table_size
show variables where variable_name in (
'join_buffer_size',
'read_buffer_size',
'tmp_table_size'
);

2.2 內存參數的含義

各個變量的含義比較好掌握,官方參考手冊上都有,但是,什麼時候應該修改,修改爲多少纔是合適的值?手冊上並沒有給出,本文將回答這個問題。

  1. query_cache_size 這是MySQL的查詢緩存,用以緩衝SQL語句的結果,如果下次有相同的SQL語句,並且,結果還沒有invalid掉,則直接返回查詢緩存中的結果即可。這是理想情況,實際情況query_cache可能導致激烈的鎖競爭,使得性能反而下降,MySQL 5.7已經可以關閉query_cache了。

  2. innodb_additional_mem_pool_size # (沒有查到mysql5.7_aliyun_RDS) 該緩存用以存放數據字典和內部數據結構的信息,一般情況下,表越多,該選項也應該越大,該選項過小時,Innodb會在錯誤日誌中打印錯誤信息,可以等到有錯誤日誌以後再調整。

  3. innodb_buffer_pool_size Innodb爲存儲數據、索引、undo、自適應索引等分配的內存大小,影響innodb性能最重要的選項,一般設置爲物理內存的80%。

  4. innodb_log_buffer_size Innodb重做日誌(redo)的大小,一般取默認值即可。

  5. key_buffer_size MyISAM表緩存索引的緩存,建議不用MyISAM表。

  6. net_buffer_length 服務器在客戶端連接建立以後創建的緩存大小,用來保持請求和結果。根據需要,這個大小可以增長至max_allowed_packet。

  7. thread_stack 每個線程的棧大小,如果該變量設置過小,將會限制SQL語句的複雜性、存儲過程的遞歸深度,以及服務器上其他內存消耗型的操作。對於大部分安裝來說,默認取值即可。如果有類似”Thread stack overrun”,則需要增大該值。

  8. query_prealloc_size 此緩存爲語句解析和執行而分配,如果運行復雜查詢,增加緩存是合理的,這樣mysqld不會在執行查詢的時候在分配內存上耗時。

  9. binlog_cache_size 緩存binlog的緩衝區,如果大於該值,緩存中的binlog將寫到磁盤的臨時文件中。

  10. binlog_stmt_cache_size 緩存非事務表的binlog。

  11. read_rnd_buffer_size 存放排序和發送結果至客戶端之間,讀取結果的大小,大的值能提高order by的性能

  12. sort_buffer_size 每個線程需要排序的時候會分配此緩存,通過檢查sort_merge_passes狀態變量來判斷是否需要增加該緩存的大小。sort_buffer_size緩存經常會分配,所以,大的GLOBAL值會降低性能而不是增加性能。因此,最好不要設置得太大,在需要的時候通過set session增加即可。

  13. join_buffer_size 連接操作分配的緩衝區,爲了檢查是否需要增加join_buffer_size的取值,可以檢查Select_sacn狀態變量,它包括第一張表執行完整掃描的連接次數,同樣,select_full_range_join,它包含使用範圍搜索的連接次數。

  14. read_buffer_size 爲表順序掃描分配的緩存

  15. tmp_table_size 臨時表的最大值,服務器默認設置爲max_heap_table_size和tmp_table_size兩者中較小的一個,如果有足夠的內存,並且created_tmp_disk_tables狀態變量再增大,則可以適當調大,把需要臨時表的所有結果保持在內存中,以提高性能。

原文摘自 http://mingxinglai.com/cn/2016/04/mysql-memory-usage-formula/

http://blog.51cto.com/11819159/2129769

https://help.aliyun.com/document_detail/26316.html

本文將討論MySQL內存相關的一些選項,包括:

單位都是b,不是kb,即1B=1/(102410241024)G

  • 1)全局的buffer,如innodb_buffer_pool_size;
  • 2)線程級的選項,如binlog_cache_size;
  • 3)爲特定操作分配的緩衝區,如sort_buffer_size。

我們只討論內存相關的選項,其他一些如innodb_open_filesthread_cache_sizetable_definition_cachetable_open_cache這類限制文件描述符合線程數量的選項不在討論之列

1. MySQL的理論內存上限

最近我們在做的一個項目,需要檢查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實例可能需要的內存,可以作爲一個參考值。

那麼,在實際應用中,我們怎麼判斷具體的內存使用情況?根據什麼條件來調整這些參數?調整爲多少比較合適呢?要回答這些問題,還得從原理講起。

2. MySQL內存參數的含義

在這一節,我們首先對內存參數進行了一個分類,然後對各個參數的含義進行了詳細的討論。

2.1 內存參數分類

2.1.1 服務器級別

服務器級別的buffer是全局且唯一的,影響所有的連接和查詢,需要注意的是,服務器級別的buffer中,大部分是服務器啓動的時候分配的,小部分是後來分配的。如query_cache,初始值是0,後續不斷增長,直至最大。

  • innodb_additional_mem_pool_size # 該參數查不到
  • innodb_buffer_pool_size
  • innodb_log_buffer_size
  • key_buffer_size
  • query_cache_size

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'
);
2.1.2 線程級別

這些buffer是線程級別的,對於每個線程都會分配,因此,佔用的內存情況爲max_connection * (thread_options),線程級別的選項有:

  • binlog_cache_size
  • binlog_stmt_cache_size
  • net_buffer_length
  • query_prealloc_size
  • thread_stack

sql查詢語句

show variables where variable_name in (
'net_buffer_length',
'thread_stack',
'query_prealloc_size',
'binlog_cache_size',
'binlog_stmt_cache_size'
);
2.1.3 爲特定操作分配的緩衝區

當服務器執行特殊操作時,根據需要分配緩衝區。因此,很難計算緩衝區的具體大小。好在這些緩衝區都是session級別的,我們可以保持全局較小的取值,如果需要,再修改session級別的緩衝區大小。

a.對每個線程分配一次

  • read_rnd_buffer_size
  • sort_buffer_size
  • myisam_mmap_size
  • myisam_sort_buffer_size
  • bulk_insert_buffer_size
  • preload_buffer_size

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.對每個線程分配多次(可能)

  • join_buffer_size
  • read_buffer_size
  • tmp_table_size
show variables where variable_name in (
'join_buffer_size',
'read_buffer_size',
'tmp_table_size'
);

2.2 內存參數的含義

各個變量的含義比較好掌握,官方參考手冊上都有,但是,什麼時候應該修改,修改爲多少纔是合適的值?手冊上並沒有給出,本文將回答這個問題。

  1. query_cache_size 這是MySQL的查詢緩存,用以緩衝SQL語句的結果,如果下次有相同的SQL語句,並且,結果還沒有invalid掉,則直接返回查詢緩存中的結果即可。這是理想情況,實際情況query_cache可能導致激烈的鎖競爭,使得性能反而下降,MySQL 5.7已經可以關閉query_cache了。

  2. innodb_additional_mem_pool_size # (沒有查到mysql5.7_aliyun_RDS) 該緩存用以存放數據字典和內部數據結構的信息,一般情況下,表越多,該選項也應該越大,該選項過小時,Innodb會在錯誤日誌中打印錯誤信息,可以等到有錯誤日誌以後再調整。

  3. innodb_buffer_pool_size Innodb爲存儲數據、索引、undo、自適應索引等分配的內存大小,影響innodb性能最重要的選項,一般設置爲物理內存的80%。

  4. innodb_log_buffer_size Innodb重做日誌(redo)的大小,一般取默認值即可。

  5. key_buffer_size MyISAM表緩存索引的緩存,建議不用MyISAM表。

  6. net_buffer_length 服務器在客戶端連接建立以後創建的緩存大小,用來保持請求和結果。根據需要,這個大小可以增長至max_allowed_packet。

  7. thread_stack 每個線程的棧大小,如果該變量設置過小,將會限制SQL語句的複雜性、存儲過程的遞歸深度,以及服務器上其他內存消耗型的操作。對於大部分安裝來說,默認取值即可。如果有類似”Thread stack overrun”,則需要增大該值。

  8. query_prealloc_size 此緩存爲語句解析和執行而分配,如果運行復雜查詢,增加緩存是合理的,這樣mysqld不會在執行查詢的時候在分配內存上耗時。

  9. binlog_cache_size 緩存binlog的緩衝區,如果大於該值,緩存中的binlog將寫到磁盤的臨時文件中。

  10. binlog_stmt_cache_size 緩存非事務表的binlog。

  11. read_rnd_buffer_size 存放排序和發送結果至客戶端之間,讀取結果的大小,大的值能提高order by的性能

  12. sort_buffer_size 每個線程需要排序的時候會分配此緩存,通過檢查sort_merge_passes狀態變量來判斷是否需要增加該緩存的大小。sort_buffer_size緩存經常會分配,所以,大的GLOBAL值會降低性能而不是增加性能。因此,最好不要設置得太大,在需要的時候通過set session增加即可。

  13. join_buffer_size 連接操作分配的緩衝區,爲了檢查是否需要增加join_buffer_size的取值,可以檢查Select_sacn狀態變量,它包括第一張表執行完整掃描的連接次數,同樣,select_full_range_join,它包含使用範圍搜索的連接次數。

  14. read_buffer_size 爲表順序掃描分配的緩存

  15. tmp_table_size 臨時表的最大值,服務器默認設置爲max_heap_table_size和tmp_table_size兩者中較小的一個,如果有足夠的內存,並且created_tmp_disk_tables狀態變量再增大,則可以適當調大,把需要臨時表的所有結果保持在內存中,以提高性能。

原文摘自 http://mingxinglai.com/cn/2016/04/mysql-memory-usage-formula/

http://blog.51cto.com/11819159/2129769

https://help.aliyun.com/document_detail/26316.html

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