mysql的內存分配,是調優的重中之重,因此必須搞清楚內存是怎麼分配的mysql
mysql> show global variables like '%buffer%'; +-------------------------+------------+ | Variable_name | Value | +-------------------------+------------+ | bulk_insert_buffer_size | 4194304 | | innodb_buffer_pool_size | 2013265920 | | innodb_change_buffering | inserts | | innodb_log_buffer_size | 8388608 | | join_buffer_size | 1048576 | | key_buffer_size | 16777216 | | myisam_sort_buffer_size | 262144 | | net_buffer_length | 16384 | | preload_buffer_size | 32768 | | read_buffer_size | 1048576 | | read_rnd_buffer_size | 1048576 | | sort_buffer_size | 1048576 | | sql_buffer_result | OFF | +-------------------------+------------+ 13 rows in set (0.01 sec) mysql> show global variables like '%cache%'; +------------------------------+----------------------+ | Variable_name | Value | +------------------------------+----------------------+ | binlog_cache_size | 1048576 | | have_query_cache | YES | | key_cache_age_threshold | 300 | | key_cache_block_size | 1024 | | key_cache_division_limit | 100 | | max_binlog_cache_size | 18446744073709547520 | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 0 | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | | table_definition_cache | 256 | | table_open_cache | 100 | | thread_cache_size | 100 | +------------------------------+----------------------+ 14 rows in set (0.00 sec)
能夠看到部分配置信息算法
內存的組成sql
一、線程共享內存 二、線程獨享內存數據庫
used_Mem = + key_buffer_size + query_cache_size + innodb_buffer_pool_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 + tmp_table_size + bulk_insert_buffer_size )
線程獨享內存緩存
一、read_buffer_size: 順序讀取數據緩衝區使用內存安全
這部份內存主要用於當須要順序讀取數據的時候,如無發使用索引的狀況下的全表掃描,全索引掃描等。在這種時候,MySQL 按照數據的存儲順序依次讀取數據塊,每次讀取的數據快首先會暫存在read_buffer_size中,當 buffer 空間被寫滿或者所有數據讀取結束後,再將buffer中的數據返回給上層調用者,以提升效率。數據結構
二、read_rnd_buffer_size:隨機讀取數據緩衝區使用內存less
和順序讀取相對應,當 MySQL 進行非順序讀取(隨機讀取)數據塊的時候,會利用這個緩衝區暫存讀取的數據。如根據索引信息讀取表數據,根據排序後的結果集與表進行Join等等。總的來講,就是當數據塊的讀取須要知足必定的順序的狀況下,MySQL 就須要產生隨機讀取,進而使用到 read_rnd_buffer_size 參數所設置的內存緩衝區。async
三、sort_buffer_size:排序使用內存函數
MySQL 用此內存區域進行排序操做(filesort),完成客戶端的排序請求。當咱們設置的排序區緩存大小沒法知足排序實際所需內存的時候,MySQL 會將數據寫入磁盤文件來完成排序。因爲磁盤和內存的讀寫性能徹底不在一個數量級,因此sort_buffer_size參數對排序操做的性能影響絕對不可 小視
四、join_buffer_size:鏈接使用內存
應用程序常常會出現一些兩表(或多表)Join的操做需求,MySQL在完成某些 Join 需求的時候(all/index join),爲了減小參與Join的「被驅動表」的讀取次數以提升性能,須要使用到 Join Buffer 來協助完成 Join操做。 當 Join Buffer 過小,MySQL 不會將該 Buffer 存入磁盤文件,而是先將Join Buffer中的結果集與須要 Join 的表進行 Join 操做,而後清空 Join Buffer 中的數據,繼續將剩餘的結果集寫入此 Buffer 中,如此往復。這勢必會形成被驅動表須要被屢次讀取,成倍增長 IO 訪問,下降效率。
五、thread_stack:線程棧信息使用內存
主要用來存放每個線程自身的標識信息,如線程id,線程運行時基本信息等等,咱們能夠經過 thread_stack 參數來設置爲每個線程棧分配多大的內存
六、tmp_table_size:臨時表使用內存
當咱們進行一些特殊操做如須要使用臨時表才能完成的 Order By,Group By 等等,MySQL 可能須要使用到臨時表。當咱們的臨時表較小(小於 tmp_table_size 參數所設置的大小)的時候,MySQL 會將臨時表建立成內存臨時表,只有當 tmp_table_size 所設置的大小沒法裝下整個臨時表的時候,MySQL 纔會將該表建立成 MyISAM 存儲引擎的表存放在磁盤上。不過,當另外一個系統參數 max_heap_table_size 的大小還小於 tmp_table_size 的時候,MySQL 將使用 max_heap_table_size 參數所設置大小做爲最大的內存臨時表大小,而忽略 tmp_table_size 所設置的值。並且 tmp_table_size 參數從 MySQL 5.1.2 纔開始有,以前一直使用 max_heap_table_size。
七、bulk_insert_buffer_size:批量插入暫存使用內存
當咱們使用如 insert … values(…),(…),(…)… 的方式進行批量插入的時候,MySQL 會先將提交的數據放如一個緩存空間中,當該緩存空間被寫滿或者提交完全部數據以後,MySQL 纔會一次性將該緩存空間中的數據寫入數據庫並清空緩存。此外,當咱們進行 LOAD DATA INFILE 操做來將文本文件中的數據 Load 進數據庫的時候,一樣會使用到此緩衝區
八、binlog_cache_size:二進制日誌緩衝使用內存
咱們知道InnoDB存儲引擎是支持事務的,實現事務須要依賴於日誌技術,爲了性能,日誌編碼採用二進制格式。那麼,咱們如何記日誌呢?有日誌的時候,就 直接寫磁盤?但是磁盤的效率是很低的,若是你用過Nginx,通常Nginx輸出access log都是要緩衝輸出的。所以,記錄二進制日誌的時候,咱們是否也須要考慮Cache呢?答案是確定的,可是Cache不是直接持久化,因而面臨安全性的 問題——由於系統宕機時,Cache中可能有殘餘的數據沒來得及寫入磁盤。所以,Cache要權衡,要恰到好處:既減小磁盤I/O,知足性能要求;又保證 Cache無殘留,及時持久化,知足安全要求
設置太大的話,會比較消耗內存資源;設置過小的話,若是用戶提交一個「長事務(long_transaction)」,好比:批量導入數據。那麼該事務必然會產生不少binlog,這樣 cache可能不夠用(默認binlog_cache_size是32K),不夠用的時候mysql會把uncommitted的部分寫入臨時文件(臨時 文件cache的效率必然沒有內存cache高),等到committed的時候纔會寫入正式的持久化日誌文件。
線程共享內存
一、query_cache_size:查詢緩存
查詢緩存是 MySQL 比較獨特的一個緩存區域,用來緩存特定 Query 的結果集(Result Set)信息,共享給全部客戶端。
經過對 Query 語句進行特定的 Hash 計算以後與結果集對應存放在 Query Cache 中,以提升徹底相同的 Query 語句的相應速度。
當咱們打開 MySQL 的 Query Cache 以後,MySQL 接收到每個 SELECT 類型的 Query 以後都會首先經過固定的 Hash 算法獲得該 Query 的 Hash 值,而後到 Query Cache 中查找是否有對應的 Query Cache。若是有,則直接將 Cache 的結果集返回給客戶端。若是沒有,再進行後續操做,獲得對應的結果集以後將該結果集緩存到 Query Cache 中,再返回給客戶端。
當任何一個表的數據發生任何變化以後,與該表相關的全部 Query Cache 所有會失效,因此 Query Cache 對變動比較頻繁的表並非很是適用,但對那些變動較少的表是很是合適的,能夠極大程度的提升查詢效率,如那些靜態資源表,配置表等等。爲了儘量高效的利 用 Query Cache,MySQL 針對 Query Cache 設計了多個 query_cache_type 值和兩個 Query Hint:SQL_CACHE 和 SQL_NO_CACHE。
a、當query_cache_type 設置爲0(或者 OFF)的時候 不使用 Query Cache
b、當query_cache_type設置爲1(或者 ON)的時候,當且僅當 Query 中使用了 SQL_NO_CACHE 的時候 MySQL 會忽略 Query Cache
c、query_cache_type 設置爲2(或者DEMAND)的時候,當且僅當Query 中使用了 SQL_CACHE 提示以後,MySQL 纔會針對該 Query 使用 Query Cache。
能夠經過 query_cache_size 來設置可使用的最大內存空間
二、binlog_cache_size:二進制日誌緩衝區
二進制日誌緩衝區主要用來緩存因爲各類數據變動操作所產生的 Binary Log 信息。
爲了提升系統的性能,MySQL 並非每次都是將二進制日誌直接寫入 Log File,而是先將信息寫入 Binlog Buffer 中,當知足某些特定的條件(如 sync_binlog參數設置)以後再一次寫入 Log File 中。咱們能夠經過 binlog_cache_size 來設置其可使用的內存大小,同時經過 max_binlog_cache_size 限制其最大大小(當單個事務過大的時候 MySQL 會申請更多的內存)。當所需內存大於 max_binlog_cache_size 參數設置的時候,MySQL 會報錯:「Multi-statement transaction required more than ‘max_binlog_cache_size’ bytes of storage」。
三、key_buffer_size:MyISAM索引緩存
The key_buffer_size indicates the size of the key cache that MySQL uses to store indexes in memory. The cache stores index blocks in memory to avoid reading the disk repeatedly. The key_buffer_size is one of the most important variables to tune to improve MySQL database performance. The index blocks of MyISAM tables are stored in the key cache and are accessible to all processes which use MySQL globally.
The maximum size of the key_buffer_size variable is 4 GB on 32 bit machines, and larger for 64 bit machines. MySQL recommends that you keep the key_buffer_size less than or equal to 25% of the RAM on your machine. This also depends on the other processes that use memory on the machine and it is wise to check if you consistently have 25% of free memory using the Linux command free. More on this later.
四、innodb_log_buffer_size:InnoDB 日誌緩衝區
這是 InnoDB 存儲引擎的事務日誌所使用的緩衝區。相似於 Binlog Buffer,InnoDB 在寫事務日誌的時候,爲了提升性能,也是先將信息寫入 Innofb Log Buffer 中,當知足 innodb_flush_log_trx_commit 參數所設置的相應條件(或者日誌緩衝區寫滿)以後,纔會將日誌寫到文件(或者同步到磁盤)中。能夠經過 innodb_log_buffer_size 參數設置其可使用的最大內存空間。
注:innodb_flush_log_trx_commit 參數對 InnoDB Log 的寫入性能有很是關鍵的影響。該參數能夠設置爲0,1,2,解釋以下:
mysql日誌操做步驟 :log_buffer ---mysql寫 (write)---> log_file ---OS刷新 (flush)---> disk
具體的展現
0(延遲寫): log_buffer --每隔1秒--> log_file —實時—> disk
1(實時寫,實時刷): log_buffer —實時—> log_file —實時—> disk
2(實時寫,延遲刷): log_buffer —實時—> log_file --每隔1秒--> disk
推薦的作法是 innodb_flush_log_at_trx_commit=2 ,sync_binlog=N (N爲500 或1000) 且使用帶蓄電池後備電源的緩存cache,防止系統斷電異常
注:sync_binlog =N (N>0) ,MySQL 在每寫 N次 二進制日誌binary log時,會使用fdatasync()函數將它的寫二進制日誌binary log同步到磁盤中去
此外,MySQL文檔中還提到,這幾種設置中的每秒同步一次的機制,可能並不會徹底確保很是準確的每秒就必定會發生同步,還取決於進程調度 的問題。實際上,InnoDB 可否真正知足此參數所設置值表明的意義正常 Recovery 仍是受到了不一樣 OS 下文件系統以及磁盤自己的限制,可能有些時候在並無真正完成磁盤同步的狀況下也會告訴 mysqld 已經完成了磁盤同步。
五、innodb_buffer_pool_size:InnoDB 數據和索引緩存
InnoDB Buffer Pool 對 InnoDB 存儲引擎的做用相似於 Key Buffer Cache 對 MyISAM 存儲引擎的影響,主要的不一樣在於 InnoDB Buffer Pool 不只僅緩存索引數據,還會緩存表的數據,並且徹底按照數據文件中的數據快結構信息來緩存,這一點和 Oracle SGA 中的 database buffer cache 很是相似。因此,InnoDB Buffer Pool 對 InnoDB 存儲引擎的性能影響之大就可想而知了。能夠經過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算獲得 InnoDB Buffer Pool 的命中率。
六、innodb_additional_mem_pool_size:InnoDB 字典信息緩存
InnoDB 字典信息緩存主要用來存放 InnoDB 存儲引擎的字典信息以及一些 internal 的共享數據結構信息。因此其大小也與系統中所使用的 InnoDB 存儲引擎表的數量有較大關係。不過,若是咱們經過 innodb_additional_mem_pool_size 參數所設置的內存大小不夠,InnoDB 會自動申請更多的內存,並在 MySQL 的 Error Log 中記錄警告信息。
這裏所列舉的各類共享內存,是我我的認爲對 MySQL 性能有較大影響的集中主要的共享內存。實際上,除了這些共享內存以外,MySQL 還存在不少其餘的共享內存信息,如當同時請求鏈接過多的時候用來存放鏈接請求信息的back_log隊列等。