【MySQL】15個有用的MySQL/MariaDB效能調整和優化技巧
MySQL 是一個強大的開源關係資料庫管理系統(簡稱 RDBMS)。它釋出於 1995 年(20年前)。它採用結構化查詢語言(SQL),這可能是資料庫內容管理中最流行的選擇。最新的 MySQL 版本是 5.6.25,於 2015 年 5 月 29 日釋出。
關於 MySQL 一個有趣的事實是它的名字來自於 Michael Widenius(MySQL 的創始人)的女兒“ My”。儘管有許多關於 MySQL 有趣的傳聞,不過本文主要是向你展示一些有用的實踐,以幫助你管理你的 MySQL 伺服器。
2009 年 4 月,MySQL 被 Oracle 收購。其結果是MySQL 社群分裂,建立了一個叫 MariaDB 的分支 。建立該分支的主要原因是為了保持這個專案可以在 GPL 下的自由。
今天,MySQL 和 MariaDB 是用於類似 WordPress、Joomla、Magento 和其他web 應用程式的最流行的 RDMS 之一(如果不是最多的)。
這篇文章將告訴你一些基本的,但非常有用的關於如何優化 MySQL/MariaDB 效能的技巧。注意,本文假定您已經安裝了 MySQL 或 MariaDB。如果你仍然不知道如何在系統上安裝它們,你可以按照以下說明去安裝:
在 RHEL/CentOS 7 上安裝 LAMP
在 Fedora 22 上安裝 LAMP
在 Ubuntu 15.04 安裝 LAMP
在 Debian 8 上安裝 MariaDB
在 Gentoo Linux
在 Arch Linux 上安裝 MariaDB
重要提示: 在開始之前,不要盲目的接受這些建議。每個MySQL 設定都是不同的,在進行任何更改之前需要慎重考慮。
你需要明白這些:
MySQL/MariaDB 配置檔案位於 /etc/my.cnf
。 每次更改此檔案後你需要重啟 MySQL 服務,以使更改生效。
這篇文章使用 MySQL 5.6 版本。
1. 啟用 InnoDB 的每張表一個數據檔案設定
首先,有一個重要的解釋, InnoDB 是一個儲存引擎。MySQL 和 MariaDB 使用InnoDB 作為預設儲存引擎。以前,MySQL 使用系統表空間來儲存資料庫中的表和索引。這意味著伺服器唯一的目的就是資料庫處理,它們的儲存盤不用於其它目的。
InnoDB 提供了更靈活的方式,它把每個資料庫的資訊儲存在一個 .ibd
資料檔案中。每個 .idb 檔案代表它自己的表空間。通過這樣的方式可以更快地完成類似 “TRUNCATE” 的資料庫操作,當刪除或截斷一個數據庫表時,你也可以回收未使用的空間。
這樣配置的另一個好處是你可以將某些資料庫表放在一個單獨的儲存裝置。這可以大大提升你磁碟的 I/O 負載。
MySQL 5.6及以上的版本預設啟用 innodb_file_per_table
。你可以在 /etc/my.cnf 檔案中看到。該指令看起來是這樣的:
innodb_file_per_table=1
2. 將 MySQL 資料庫資料儲存到獨立分割槽上
注意:此設定只在 MySQL 上有效, 在 MariaDB 上無效。
有時候作業系統的讀/寫會降低你 MySQL 伺服器的效能,尤其是如果作業系統和資料庫的資料位於同一塊磁碟上。因此,我建議你使用單獨的磁碟(最好是 SSD)用於 MySQL 服務。
要完成這步,你需要將新的磁碟連線到你的計算機/伺服器上。對於這篇文章,我假定磁碟掛在到 /dev/sdb。
下一步是準備新的分割槽:
#fdisk /dev/sdb
現在按 “N” 來建立新的分割槽。接著按 “P”,使其建立為主分割槽。在此之後,從 1-4 設定分割槽號。之後,你可以選擇分割槽大小。這裡按 enter。在下一步,你需要配置分割槽的大小。
如果你希望使用全部的磁碟,再按一次 enter。否則,你可以手動設定新分割槽的大小。準備就緒後按“w” 儲存更改。現在,我們需要為我們的新分割槽建立一個檔案系統。這可以用下面命令輕鬆地完成:
#mkfs.ext4 /dev/sdb1
現在我們會掛載新分割槽到一個目錄。我在根目錄下建立了一個名為 “ssd” 的目錄:
#mkdir /ssd/
掛載新分割槽到剛才建立的目錄下:
#mount /dev/sdb1 /ssd/
你可以在 /etc/fstab 檔案中新增如下行設定為開機自動掛載:
/dev/sdb1 /ssd ext3 defaults 00
現在我們將MySQL 移動到新磁碟中
首先停止 MySQL 服務:
# service mysqld stop
我建議你同時停止 Apache/nginx,以防止任何試圖寫入資料庫的操作:
-
# service httpd stop
-
-
# service nginx stop
現在複製整個 MySQL 目錄到新分割槽中:
#cp /var/lib/mysql /ssd/ -Rp
這可能需要一段時間,具體取決於你的 MySQL 資料庫的大小。一旦這個過程完成後重新命名 MySQL 目錄:
#mv /var/lib/mysql /var/lib/mysql-backup
然後建立一個符號連結:
#ln -s /ssd/mysql /var/lib/mysql
現在啟動你的 MySQL 和 web 服務:
-
# service mysqld start
-
-
# service httpd start
-
-
# service nginx start
以後你的資料庫將使用新的磁碟訪問。
3. 優化使用 InnoDB 的緩衝池
InnoDB 引擎在記憶體中有一個緩衝池用於快取資料和索引。這當然有助於你更快地執行MySQL/MariaDB 查詢語句。選擇合適的記憶體大小需要一些重要的決策並對系統的記憶體消耗有較多的認識。
下面是你需要考慮的:
其它的程序需要消耗多少記憶體。這包括你的系統程序,頁表,套接字緩衝。
你的伺服器是否專門用於 MySQL 還是你執行著其它非常消耗記憶體的服務。
在一個專用的機器上,你可能會把 60-70%的記憶體分配給 innodb_buffer_pool_size
。如果你打算在一個機器上執行更多的服務,你應該重新考慮專門用於 innodb_buffer_pool_size
的記憶體大小。
你需要設定 my.cnf 中的此項:
innodb_buffer_pool_size
4. 在 MySQL 中避免使用 Swappiness
“交換”是一個當系統移動部分記憶體到一個稱為“交換空間” 的特殊磁碟空間時的過程。通常當你的系統用完實體記憶體後就會出現這種情況,系統將資訊寫入磁碟而不是釋放一些記憶體。正如你猜測的磁碟比你的記憶體要慢得多。
該選項預設情況下是啟用的:
-
#sysctl vm.swappiness
-
-
vm.swappiness=
60
執行以下命令關閉 swappiness:
#sysctl -w vm.swappiness=0
5. 設定 MySQL 的最大連線數
max_connections
指令告訴你當前你的伺服器允許多少併發連線。MySQL/MariaDB 伺服器允許有 SUPER 許可權的使用者在最大連線之外再建立一個連線。只有當執行 MySQL 請求的時候才會建立連線,執行完成後會關閉連線並被新的連線取代。
請記住,太多的連線會導致記憶體的使用量過高並且會鎖住你的 MySQL 伺服器。一般小網站需要 100-200 的連線數,而較大可能需要 500-800 甚至更多。這裡的值很大程度上取決於你 MySQL/MariaDB 的使用情況。
你可以動態地改變 max_connections
的值而無需重啟MySQL伺服器:
-
# mysql -u root -p
-
-
mysql>setglobal max_connections =
300;
6. 配置 MySQL 的執行緒快取數量
thread_cache_size
指令用來設定你伺服器快取的執行緒數量。當客戶端斷開連線時,如果當前執行緒數小於thread_cache_size
,它的執行緒將被放入快取中。下一個請求通過使用快取池中的執行緒來完成。
要提高伺服器的效能,你可以設定 thread_cache_size
的值相對高一些。你可以通過以下方法來檢視執行緒快取命中率:
-
mysql>show status
like
'Threads_created';
-
-
mysql>show status
like
'Connections';
你可以用以下公式來計算執行緒池的命中率:
100 - ((Threads_created / Connections) * 100)
如果你得到一個較低的數字,這意味著大多數mysql 連線使用新的執行緒,而不是從快取載入。在這種情況下,你需要增加thread_cache_size
。
這裡有一個好處是可以動態地改變 thread_cache_size
而無需重啟 MySQL 服務。你可以通過以下方式來實現:
mysql>setglobal thread_cache_size = 16;
7. 禁用 MySQL 的 DNS 反向查詢
預設情況下當新的連接出現時,MySQL/MariaDB會進行 DNS 查詢解析使用者的 IP 地址/主機名。對於每個客戶端連線,它的 IP 都會被解析為主機名。然後,主機名又被反解析為 IP 來驗證兩者是否一致。
當 DNS 配置錯誤或伺服器出現問題時,這很可能會導致延遲。這就是為什麼要關閉 DNS 的反向查詢的原因,你可以在你的配置檔案中新增以下選項去設定:
-
[mysqld]
-
-
#Skip
reverse
DNS
lookup
of
clients
-
-
skip-name-resolve
更改後你需要重啟 MySQL 服務。
8. 配置 MySQL 的查詢快取容量
如果你有很多重複的查詢並且資料不經常改變 – 請使用快取查詢。人們常常不理解 query_cache_size
的實際含義而將此值設定為 GB 級,這實際上會降低伺服器的效能。
背後的原因是,在更新過程中執行緒需要鎖定快取。通常設定為 200-300 MB應該足夠了。如果你的網站比較小的,你可以嘗試給 64M 並在以後及時去增加。
在你的 MySQL 配置檔案中新增以下設定:
-
query_cache_type= 1
-
-
query_cache_limit= 256K
-
-
query_cache_min_res_unit= 2k
-
-
query_cache_size= 80M
9. 配置臨時表容量和記憶體表最大容量
tmp_table_size
和 max_heap_table_size
這兩個變數的大小應該相同,它們可以讓你避免磁碟寫入。tmp_table_size
是內建記憶體表的最大空間。如果表的大小超出限值將會被轉換為磁碟上的 MyISAM 表。
這會影響資料庫的效能。管理員通常建議在伺服器上設定這兩個值為每 GB 記憶體給 64M。
-
[
mysqld]
-
-
tmp_table_size=
64M
-
-
max_heap_table_size=
64M
10. 啟用 MySQL 慢查詢日誌
記錄慢查詢可以幫助你定位資料庫中的問題並幫助你除錯。這可以通過在你的 MySQL 配置檔案中新增以下值來啟用:
-
slow-query-
log=
1
-
-
slow-query-
log-file = /var/lib/mysql/mysql-slow.
log
-
-
long_query_time=
1
第一個變數啟用慢查詢日誌,第二個告訴 MySQL 實際的日誌檔案儲存位置。使用 long_query_time
來定義完成 MySQL 查詢多少用時算長。
11. 檢查 MySQL 的空閒連線
空閒連線會消耗資源,可以的話應該被終止或者重新整理。空閒連線是指處於 “sleep” 狀態並且保持了很長一段時間的連線。你可以通過執行以下命令檢視空閒連線:
# mysqladmin processlist -u root -p | grep “Sleep”
這會顯示處於睡眠狀態的程序列表。當代碼使用持久連線到資料庫時會出現這種情況。使用 PHP 呼叫 mysql_pconnect 可以開啟這個連線,執行完查詢之後,刪除認證資訊並保持連線為開啟狀態。這會導致每個執行緒的緩衝都被儲存在記憶體中,直到該執行緒結束。
首先你要做的就是檢查程式碼問題並修復它。如果你不能訪問正在執行的程式碼,你可以修改 wait_timeout
變數。預設值是 28800 秒,而你可以安全地將其降低到 60 :
wait_timeout=60
12. 為 MySQL 選擇正確的檔案系統
選擇正確的檔案系統對資料庫至關重要。在這裡你需要考慮的最重要的事情是 - 資料的完整性,效能和易管理性。
按照 MariaDB 的建議,最好的檔案系統是XFS、ext4 和 Btrfs。它們都是可以使用超大檔案和大容量儲存卷的企業級日誌型檔案系統。
下面你可以找到一些關於這三個檔案系統的有用資訊:
檔案系統 |
XFS |
Ext4 |
Btrfs |
檔案系統最大容量 |
8EB |
1EB |
16EB |
最大檔案大小 |
8EB |
16TB |
16EB |
我們的這篇文章詳細介紹了 Linux 檔案系統的利與弊: Linux 檔案系統解析。
13. 設定 MySQL 允許的最大資料包
MySQL 把資料拆分成包。通常一個包就是傳送到客戶端的一行資料。max_allowed_packet
變數定義了可以被髮送的最大的包。
此值設定得過低可能會導致查詢速度變得非常慢,然後你會在 MySQL 的錯誤日誌看到一個錯誤。建議將該值設定為最大包的大小。
14. 測試 MySQL 的效能優化
你應該定期檢查 MySQL/MariaDB 的效能。這將幫助你瞭解資源的使用情況是否發生了改變或需要進行改進。
有大量的測試工具可用,但我推薦你一個簡單易用的。該工具被稱為 mysqltuner。
使用下面的命令下載並執行它:
-
#wget https://github.com/major/MySQLTuner-perl/tarball/master
-
-
#tar xf master
-
-
#cd major-MySQLTuner-perl-993bc18/
-
-
# ./mysqltuner.pl
你將收到有關 MySQL 使用的詳細報告和推薦提示。下面是預設 MariaDB 安裝的輸出樣例:
15. 優化和修復 MySQL 資料庫
有時候 MySQL/MariaDB 資料庫中的表很容易崩潰,尤其是伺服器意外關機、檔案系統突然崩潰或複製過程中仍然訪問資料庫。幸運的是,有一個稱為 'mysqlcheck' 的免費開源工具,它會自動檢查、修復和優化 Linux 中資料庫的所有表。
-
# mysqlcheck -u root -p --auto-repair --check --optimize--all-databases
-
-
# mysqlcheck -u root -p --auto-repair --check --optimizedatabasename
就是這些!我希望上述文章對你有用,並幫助你優化你的MySQL 伺服器。一如往常,如果你有任何疑問或評論,請在下面的評論部分提交。