經常有人問配置mysql時該如何估算內存的消耗。那么該使用什么公式來計算呢?
關心內存怎么使用的原因是可以理解的。如果配置mysql服務器使用太少的內存會導致性能不是最優的;如果配置了太多的內存則會導致崩潰,無法執行查詢或者導致交換操作嚴重變慢。在現在的32位平台下,仍有可能把所有的地址空間都用完了,因此需要監視着。
話雖如此,但我並不覺得找到什么可以計算內存使用的秘訣公式就能很好地解決這個問題。原因有--如今這個公式已經很復雜了,更重要的是,通過它計算得到的值只是“理論可能”並不是真正消耗的值。事實上,有8gb內存的常規服務器經常能運行到最大的理論值--100gb甚至更高。此外,你輕易不會使用到“超額因素”--它實際上依賴於應用以及配置。一些應用可能需要理論內存的10%而有些僅需1%。
那么,我們可以做什么呢?首先,來看看那些在啟動時就需要分配並且總是存在的全局緩沖--key_buffer_size,innodb_buffer_pool_size,innodb_additional_memory_pool_size,innodb_log_buffer_size,query_cache_size。如果你大量地使用myisam表,那么你也可以增加操作系統的緩存空間使得mysql也能用得着。把這些也都加到操作系統和應用程序所需的內存值之中,可能需要增加32mb甚至更多的內存給mysql服務器代碼以及各種不同的小靜態緩沖。這些就是你需要考慮的在mysql服務器啟動時所需的內存。其他剩下的內存用於連接。例如有8gb內存的服務器,可能監聽所有的服務就用了6gb的內存,剩下的2gb內存則留下來給線程使用。
和"mysql服務器內存使用"有關的數據庫編程小帖士:
strong>SUBSTRB
SUBSTRB返回一字符串的指定部分。2881064151該函數與SUBSTR極為類似,只是該函數的start和length兩參數均以字節為單位,而不是根據字符。這種區別只有在使用多種不同的字符集時才有意義。
每個連接到mysql服務器的線程都需要有自己的緩沖。大概需要立刻分配256k,甚至在線程空閑時--它們使用默認的線程堆棧,網絡緩存等。事務開始之后,則需要增加更多的空間。運行較小的查詢可能僅給指定的線程增加少量的內存消耗,然而如果對數據表做復雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,sort_buffer_size,read_rnd_buffer_size,tmp_table_size大小的內存空間。不過它們只是在需要的時候才分配,並且在那些操作做完之后就釋放了。有的是立刻分配成單獨的組塊,例如tmp_table_size可能高達mysql所能分配給這個操作的最大內存空間了。注意,這里需要考慮的不只有一點--可能會分配多個同一種類型的緩存,例如用來處理子查詢。一些特殊的查詢的內存使用量可能更大--如果在myisam表上做成批的插入時需要分配bulk_insert_buffer_size大小的內存。執行alter table,optimize table,repair table命令時需要分配myisam_sort_buffer_size大小的內存。
只有簡單查詢oltp應用的內存消耗經常是使用默認緩沖的每個線程小於1mb,除非需要使用復雜的查詢否則無需增加每個線程的緩沖大小。使用1mb的緩沖來對10行記錄進行排序和用16mb的緩沖基本是一樣快的(實際上16mb可能會更慢,不過這是其他方面的事了)。
另外,就是找出mysql服務器內存消耗的峰值。這很容易就能計算出操作系統所需的內存、文件緩存以及其他應用。在32位環境下,還需要考慮到32位的限制,限制“mysqld”的值大約為2.5g(實際上還要考慮到很多其他因素)。2881064151現在運行“ps aux”命令來查看vsz的值--mysql進程分配的虛擬內存。也可以查看“resident memory”的值,不過我想它可能沒多大用處,因為它會由於交換而變小--這並不是你想看到的。監視着內存變化的值,就能知道是需要增加/減少當前的內存值了。
可能有的人想說,我們想要讓服務器能保證100%不會耗盡內存,不管決定用什么樣的查詢、什么樣的用戶。很不幸,這其實很不明智也不可能,因為:
以下是很少考慮的mysql服務器內存需求
每個線程可能會不止一次需要分配緩沖。考慮到例如子查詢--每層都需要有自己的read_buffer,sort_buffer,tmp_table_size等。
在每個連接中很多變量都可能需要重新設置。如果開發者想設定自己的變量值來運行某些查詢就不能繼續使用全局值。
可能有多個索引緩存。為了配合執行查詢可能會創建多個索引緩存。
解析查詢和優化都需要內存。這些內存通常比較小,可以忽略,不過如果是某些查詢在這個步驟中則需要大量內存,尤其是那些設計的比較特別的查詢。
存儲過程。復雜的存儲過程可能會需要大量內存。
准備查詢語句以及游標。單次鏈接可能會有很多的准備好的語句以及游標。它們的數量最后可以限定,但是仍然會消耗大量的內存。
innodb表緩存。innnodb表有自己的緩存,它保存了從一開始訪問每個表的元數據。它們從未被清除過,如果有很多innodb表的話,那么這個量就很大了。這也就意味着擁有create table權限的用戶就可能把mysql服務器的內存耗盡。
老張交流QQ:2881064151