author:skate
time:2012/02/16
mysql內存使用分析
2.全局共享內存
全局共享內則主要是MySQL Instance(mysqld進程)以及底層存儲引擎用來暫存各種全局運算及可共享的暫存信息,如存儲查詢緩存的Query Cache,緩存連接線程的Thread Cache,緩存表文件句柄信息的Table Cache,緩存二進制日志的BinLog Buffer, 緩存MyISAM 存儲引擎索引鍵的Key Buffer以及存儲InnoDB 數據和索引的InnoDB Buffer Pool 等等。下面針對MySQL 主要的共享內存進行一個簡單的分析。
查詢緩存(Query Cache):
查詢緩存是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。當query_cache_type 設置為0(或者OFF)的時候不使用Query Cache,當設置為1(或者ON)的時候,當且僅當Query 中使用了SQL_NO_CACHE 的時候MySQL 會忽略Query Cache,當query_cache_type 設置為2(或者DEMAND)的時候,當且僅當Query 中使用了SQL_CACHE 提示之後,MySQL 才會針對該Query 使用Query Cache。可以通過query_cache_size 來設置可以使用的最大內存空間。
連接線程緩存(Thread Cache):
連接線程是MySQL 為了提高創建連接線程的效率,將部分空閒的連接線程保持在一個緩存區以備新進連接請求的時候使用,這尤其對那些使用短連接的應用程序來說可以極大的提高創建連接的效率。當我們通過thread_cache_size 設置了連接線程緩存池可以緩存的連接線程的大小之後,可以通過(Connections - Threads_created) / Connections * 100% 計算出連接線程緩存的命中率。注意,這裡設置的是可以緩存的連接線程的數目,而不是內存空間的大小。
表緩存(Table Cache):
表緩存區主要用來緩存表文件的文件句柄信息,在MySQL5.1.3之前的版本通過table_cache 參數設置,但從MySQL5.1.3開始改為table_open_cache 來設置其大小。當我們的客戶端程序提交Query 給MySQL 的時候,MySQL 需要對Query 所涉及到的每一個表都取得一個表文件句柄信息,如果沒有Table Cache,那麼MySQL 就不得不頻繁的進行打開關閉文件操作,無疑會對系統性能產生一定的影響,Table Cache 正是為了解決這一問題而產生的。在有了Table Cache 之後,MySQL 每次需要獲取某個表文件的句柄信息的時候,首先會到Table Cache 中查找是否存在空閒狀態的表文件句柄。如果有,則取出直接使用,沒有的話就只能進行打開文件操作獲得文件句柄信息。在使用完之後,MySQL 會將該文件句柄信息再放回Table Cache 池中,以供其他線程使用。注意,這裡設置的是可以緩存的表文件句柄信息的數目,而不是內存空間的大小。
表定義信息緩存(Table definition Cache):
表定義信息緩存是從MySQL5.1.3 版本才開始引入的一個新的緩存區,用來存放表定義信息。當我們的MySQL 中使用了較多的表的時候,此緩存無疑會提高對表定義信息的訪問效率。MySQL 提供了table_definition_cache 參數給我們設置可以緩存的表的數量。在MySQL5.1.25 之前的版本中,默認值為128,從MySQL5.1.25 版本開始,則將默認值調整為256 了,最大設置值為524288。注意,這裡設置的是可以緩存的表定義信息的數目,而不是內存空間的大小。
二進制日志緩沖區(Binlog Buffer):
二進制日志緩沖區主要用來緩存由於各種數據變更操做所產生的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”。
MyISAM索引緩存(Key Buffer):
MyISAM 索引緩存將MyISAM 表的索引信息緩存在內存中,以提高其訪問性能。這個緩存可以說是影響MyISAM 存儲引擎性能的最重要因素之一了,通過key_buffere_size 設置可以使用的最大內存空間。
InnoDB 日志緩沖區(InnoDB Log Buffer):
這是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,解釋如下:
0:log buffer中的數據將以每秒一次的頻率寫入到log file中,且同時會進行文件系統到磁盤的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的刷新或者文件系統到磁盤的刷新操作;
1:在每次事務提交的時候將log buffer 中的數據都會寫入到log file,同時也會觸發文件系統到磁盤的同步;
2:事務提交會觸發log buffer 到log file的刷新,但並不會觸發磁盤文件系統到磁盤的同步。此外,每秒會有一次文件系統到磁盤同步操作。
此外,MySQL文檔中還提到,這幾種設置中的每秒同步一次的機制,可能並不會完全確保非常准確的每秒就一定會發生同步,還取決於進程調度的問題。實際上,InnoDB 能否真正滿足此參數所設置值代表的意義正常Recovery 還是受到了不同OS 下文件系統以及磁盤本身的限制,可能有些時候在並沒有真正完成磁盤同步的情況下也會告訴mysqld 已經完成了磁盤同步。
InnoDB 數據和索引緩存(InnoDB Buffer Pool):
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 字典信息緩存(InnoDB Additional Memory Pool):
InnoDB 字典信息緩存主要用來存放InnoDB 存儲引擎的字典信息以及一些internal 的共享數據結構信息。所以其大小也與系統中所使用的InnoDB 存儲引擎表的數量有較大關系。不過,如果我們通過innodb_additional_mem_pool_size 參數所設置的內存大小不夠,InnoDB 會自動申請更多的內存,並在MySQL 的Error Log 中記錄警告信息。
這裡所列舉的各種共享內存,是對MySQL 性能有較大影響的集中主要的共享內存。實際上,除了這些共享內存之外,MySQL 還存在很多其他的共享內存信息,如當同時請求連接過多的時候用來存放連接請求信息的back_log隊列等。
------end-----