配置mysql 正確使用的內存量對於高性能是至關重要的,需要進行定制需求來定制內存的使用。
mysql內存消耗可以分為兩類:可控制內存和不可控制內存。
無法控制
mysql 服務器運行、查詢解析、以及內部管理所消耗的內存,但是為特定目的而使用的內存有很多參數可以進行控制,比如關聯使用join buffer、排序使用sort buffer等。
可控制
用好mysql可控制的內存則需要對配置的含義非常清楚
下面的步驟是來配置內存的
1、確定可以使用的內存上限
2、確定每個連接mysql 需要多少內存,例如排序緩沖和臨時表
3、確認操作系統需要多少內存才夠用。包括同一台機器上其他程序所使用的內存,比如定時任務等……
4、把剩下的內存交給mysql 緩存,例如innodb的緩沖池,這樣做很有意義
每個mysql 連接需要的內存
mysql保持一個連接(線程)只需要少量的內存,它還要求一個基本的內存來執行任何給定的查詢。需要在高峰期大量的查詢時預留好足夠的內存,否則查詢的執行可能會因為缺乏內存而執行效率不佳
或者執行失敗。
知道mysql 在高峰期消耗多少內存是非常有用的,但是一些習慣的用法可能會導致意外的消耗了大量的內存,這對內存的使用量的預測變得比較困難,例如綁定變量和innodb數據字典。
當預測內存峰值消耗時,沒必要假設一個最壞的情況,例如配置mysql 允許最多100個連接,在理論上可能出現100個連接同時在運行很大的查詢,在現實情況下可能不會發生,例如:
設置myisam_sort_buffer_size為256MB,最差的情況下至少需要使用25GB內存,但是這種最差的情況實際幾乎是不可能發生的,使用了許多大的臨時表或者復雜存儲過程的查詢,通常是
導致內存高消耗的最可能的原因。
相對於最壞情況的開銷,更好的方法是觀察服務器在真實工作壓力下使用了多少內存,可以在進程的虛擬內存大小那里看到,許多類unix系統里,可以觀察top命令中virt列,或者ps命令中VSZ
的值。
為操作系統保留內存
和查詢一樣,操作系統也需要足夠的內存給它工作。如果沒有虛擬內存正在交換(paging)到硬盤,就是表明了系統內存足夠用的最佳跡象。至少應該為操作系統保留1~2G的內存,如果機器內存多
就多預留一些,我們建議2GB獲取總內存的5%作為基准,以較大者為准,為了安全再額外增加一些預留,並且如果機器還在運行內存密集任務(如備份),則可以再多增加一些預留,不要為操作系統緩存
增加任何內存,因為他們可能變得非常大,操作系統通常會利用所有剩下的內存來做文件系統緩存,我們認為,這應該從操作系統自身的需求分離出來。
為緩存分配內存
如果服務器只運行mysql,所有不需要為操作系統以及查詢處理保留的內存都可以用來做mysql緩存。
相比其他,mysql需要為緩存分配更多的內存,它使用緩存來避免磁盤訪問,磁盤訪問比內存訪問要慢得多,操作系統可能會緩存一些數據,這對mysql有些好處,但是mysql自身也需要大量的內存。
下面是我們認為大部分情況最重要的緩存
innodb 緩存池
innodb 日志文件和myisam 數據的操作系統緩存
myisam 鍵緩存
查詢緩存
無法手工配置的緩存,例如二進制日志和表定義文件的操作系統緩存
還有其他緩存通常不會使用太多內存
如果使用單一的存儲引擎,配置服務器就簡單許多了。如果只使用myisam 就可以完全關閉innodb,如果只使用innoDb,就只需要分配最少的資源給myisam(mysql 內部系統表用myisam),但是
如果正混用各種存儲引擎,就很難在他們之間找到恰當的平衡,我們發現最好的辦法是做一個有根據的猜測,然后在運行中觀察服務器(再進行調整)
innoDB緩沖池
如果大部分都是innodb表,那么innodb緩存池或許比任何東西都需要內存,innodb緩存池並不僅僅是緩存索引,它還會緩存行的數據,自適應hash索引,插入緩沖(insert buffer)、鎖以及其他內部的
數據結構。innodb還是用緩沖池來幫助延遲寫入,這樣就能合並多個寫入操作,然后順序一起寫回。總之innodb嚴重依賴緩沖池,你必須確認為他分配了足夠的內存,可以使用show 命令得到變量,或
使用例如innotop的工具監控innoDB的緩沖池內存利用的情況。
如果數據量不大,並且不會快速的增長,就沒必要為緩沖池分配過多的內存,把緩沖池配置的比需要緩存的表和索引還要大很多實際沒有什么意義,當然,對於一個快速增長的數據庫做超前的規划沒有
錯,但有時候我們也會看到一個巨大的緩沖池之緩存了一點數據,就沒必要了。
很大的緩沖池也會帶來一些挑戰,例如,預熱和關閉都會花費很長的時間,如果有很多臟數據在緩沖池里,innodb關閉時可能會花費比較長的時間因為關閉之前需要把臟頁寫回數據文件,也可以強制關閉
,但是重啟的時候需要做很多恢復工作,也就是說無法加快關閉和重啟,如果事先知道需要關閉innodb,可以在運行的時候修改innodb_max_dirty_pages_pct 變量,將值進行改小,等待數據刷新線程進行
清理緩沖池,然后在臟頁數量較小的時候關閉,可以監控the innodb_buffer_pool_pages_dirty狀態的變量或者使用innotop來監控show innodb status來觀察臟頁的刷新量。
