MySQL 是一個很棒的 open source 數據庫引擎,大部分的網站和博客都是由 MySQL 驅動的。MySQL 的默認安裝占用的內存資源比較大(相對於一個只有 64MB 的 VPS來說),優化 MySQL 可以減少內存消耗,把更多的內存省下來留給其他程序。
MySQL 的配置文件在 /etc/mysql/my.cnf(Debian 5),為了方便調整配置,MySQL 為小資源系統提供了一個叫做 my-small.cnf 的配置文件,是給小於 32MB 內存的服務器設置的。我們可以在這個配置文件的基礎上作小部分的調整。
先找到 /usr/share/doc/mysql-server-5.0/examples/my-small.cnf,然後覆蓋 /etc/mysql/my.cnf(Debian)。如果是 CentOS 5 的話,路徑是:/usr/share/doc/mysql-server-5.0.45/my-small.cnf,覆蓋 /etc/my.cnf。
參數說明
如果不使用 BDB table 和 InnoDB table 的話,加入下面2行關閉不需要的表類型很有必要,關閉 innodb 可以省下大量內存,雖然 InnoDB 好處多多但是在一個64MB的 VPS 上並不能體現出來,並且很占內存。
skip-bdb
skip-innodb
key_buffer 是優化性能的重要參數,用來緩存 tables keys 和 indexes,增加這個值可以更好的處理索引,讀和寫都需要索引。這裡設設置成 16K 足夠了。table_cache 是所有線程打開的表的數量,增加值可以增大 MySQL 的文件描述符數量,避免頻繁的打開表,原始 my-small.cnf 中 table_cache 設置成4有點小,一個 wordpress 的頁面通常會涉及到10個左右的表,其他的程序比如 Drupal,MediaWiki 會涉及到更多,將table_cache改為8。
key_buffer = 16K
table_cache = 8
max_connections 是數據庫最大的連接數量,可以根據自己博客/網站的訪問量來定這個值。如果博客/網站經常出現:Too many connections 錯誤的信息說明需要增大 max_connections 的值。thread_concurrency 是最大並發線程數,通常設置為 CPU核數量×2,在 VPS 宿主機上如果服務器有2顆物理 CPU,而每顆物理 CPU 又支持 H.T 超線程(一個處理器上整合了兩個邏輯處理器單元),所以實際取值為4 × 2 = 8。
如果我們在優化 php.ini 的時候設置了同時只有2個 php-cgi 運行的話,那麼我們也應該只設置2個 MySQL 線程同時運行。
max_connections = 16
thread_concurrency = 2
對於博客/新聞網站來說,用得最多的就是查詢,所以需要加入 query cache 的設置。query_cache_size 是執行查詢所使用的緩沖大小。
query_cache_limit = 256K
query_cache_size = 4M
thread_stack 用來存放每個線程的標識信息,如線程 id,線程運行時環境等,可以通過設置 thread_stack 來決定給每個線程分配多大的內存。
sort_buffer_size 是每個需要排序的線程分配的緩沖區大小,增加該值可以加速 order by 和 group by 的操作。注意:該參數是以每個連接分配內存,也就是說,如果有16個連接,sort_buffer_size 為 64K,那麼實際分配的內存為:16 × 64K = 1MB。如果設置的緩存大小無法滿足需要,MySQL 會將數據寫入磁盤來完成排序。因為磁盤操作和內存操作不在一個數量級,所以 sort_buffer_size 對排序的性能影響很大。
read_buffer_size 是順序讀取數據時的緩沖區大小,與 sort_buffer_size 一樣,該參數分配的內存也是以每連接為單位的。read_buffer_size 是用來當需要順序讀取數據的時候,如無發使用索引的情況下的全表掃描,全索引掃描等。在這種時候,MySQL 按照數據的存儲順序依次讀取數據塊,每次讀取的數據快首先會暫存在 read_buffer_size 中,當 buffer 空間被寫滿或者全部數據讀取結束後,再將 buffer 中的數據返回給上層調用者,以提高效率。
read_rnd_buffer_size 是隨機讀取數據時的緩沖區大小,與順序讀相對應。
net_buffer_size 用來存放客戶端連接線程的連接信息和返回客戶端的結果集的緩存大小。當 MySQL 接到請求後,產生返回結果集時,會在返回給請求線程之前暫存在在這個緩存中,等積累到一定大小的時候才開始向客戶端發送,以提高網絡效率。不過,net_buffer_size 所設置的僅僅只是初始大小,MySQL 會根據實際需要自行申請更多的內存,但最大不會超過 max_allowed_packet。
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
skip-locking用來避免 MySQL 外部鎖定,減少出錯幾率,增強穩定性。
skip-locking
優化後配置
經優化後,my.cnf 的配置如下,top 查看 mysqld 保持在 5M 一下。
[mysqld]
port = 3306
socket = /var/run/mysqld/mysqld.sock
skip-locking
key_buffer = 16K
query_cache_limit = 256K
query_cache_size = 4M
max_allowed_packet = 1M
table_cache = 8
max_connections = 16
thread_concurrency = 2
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
skip-bdb
skip-innodb
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
#safe-updates
[isamchk]
key_buffer = 8M
sort_buffer_size = 8M
[myisamchk]
key_buffer = 8M
sort_buffer_size = 8M
[mysqlhotcopy]
interactive-timeout
內存計算公式
MySQL memory = key_buffer + max_connections *
(join_buffer + record_buffer + sort_buffer + thread_stack + tmp_table_size)