msyql的記憶體計算
本文將討論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_files
、thread_cache_size
、table_definition_cache
、table_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 記憶體引數的含義
各個變數的含義比較好掌握,官方參考手冊上都有,但是,什麼時候應該修改,修改為多少才是合適的值?手冊上並沒有給出,本文將回答這個問題。
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/