在Apache, PHP,
MySQL的體系架構中,MySQL對於效能的影響最大,也是關鍵的核心部分。對於Discuz!論壇程式也是如此,MySQL的設定是否合理最佳化,直接
影響到論壇的速度和承載量!同時,MySQL也是最佳化難度最大的一個部分,不但需要理解一些MySQL專業知識,同時還需要長時間的觀察統計並且根據經驗
進行判斷,然後設定合理的參數。
下面我們瞭解一下MySQL最佳化的一些基礎,MySQL的最佳化我分為兩個部分,一是伺服器物理硬體的最佳化;二是MySQL自身(my.cnf)的最佳化。
(1) 伺服器硬體對MySQL效能的影響
a)
磁碟尋道能力(磁碟I/O),以目前高轉速SCSI硬碟(7200轉/秒)為例,這種硬碟理論上每秒尋道7200次,這是物理特性決定的,沒有辦法改變。
MySQL每秒鐘都在進行大量、複雜的查詢操作,對磁碟的讀寫量可想而知。所以,通常認為磁碟I/O是制約MySQL效能的最大因素之一,對於日均訪問量
在100萬PV以上的Discuz!論壇,由於磁碟I/O的制約,MySQL的效能會非常低下!解決這一制約因素可以考慮以下幾種解決方案:
使用RAID-0+1磁碟陣列,注意不要嘗試使用RAID-5,MySQL在RAID-5磁碟陣列上的效率不會像你期待的那樣快;
拋棄傳統的硬碟,使用速度更快的快閃記憶體式存放裝置。經過Discuz!公司技術工程的測試,使用快閃記憶體式存放裝置可比傳統硬碟速度高出6-10倍左右。
b) CPU 對於MySQL應用,推薦使用S.M.P.架構的多路對稱CPU,例如:可以使用兩顆Intel Xeon 3.6GHz的CPU。
c) 實體記憶體對於一台使用MySQL的Database Server來說,伺服器記憶體建議不要小於2GB,推薦使用4GB以上的實體記憶體。
(2) MySQL自身因素當解決了上述伺服器硬體制約因素後,讓我們看看MySQL自身的最佳化是如何操作的。對MySQL自身的最佳化主要是對其設定檔my.cnf中的各項參數進行最佳化調整。下面我們介紹一些對效能影響較大的參數。
由於my.cnf檔案的最佳化設定是與伺服器硬體設定息息相關的,因而我們指定一個假想的伺服器硬體環境:
CPU: 2顆Intel Xeon 2.4GHz
記憶體: 4GB DDR
硬碟: SCSI 73GB
下面,我們根據以上硬體設定結合一份已經最佳化好的my.cnf進行說明:
# vi /etc/my.cnf
以下只列出my.cnf檔案中[mysqld]段落中的內容,其他段落內容對MySQL運行效能影響甚微,因而姑且忽略。
[mysqld] port = 3306 serverid = 1 socket = /tmp/mysql.sock skip-locking # 避免MySQL的外部鎖定,減少出錯幾率增強穩定性。 skip-name-resolve
禁止MySQL對外部串連進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。但需要注意,如果開啟該選項,則所有遠程主機串連授權都要使用IP地址方式,否則MySQL將無法正常處理串連請求!
back_log = 384
指定MySQL可能的串連數量。當MySQL主線程在很短的時間內接收到非常多的串連請求,該參數生效,主線程花費很短的時間檢查串連並且啟動一個新線程。
back_log參數的值指出在MySQL暫時停止回應新請求之前的短時間內多少個請求可以被存在堆棧中。
如果系統在一個短時間內有很多串連,則需要增大該參數的值,該參數值指定到來的TCP/IP串連的偵聽隊列的大小。不同的作業系統在這個隊列大小上有它自
己的限制。
試圖設定back_log高於你的作業系統的限制將是無效的。預設值為50。對於Linux系統推薦設定為小於512的整數。
key_buffer_size = 256M # key_buffer_size指定用於索引的緩衝區大小,增加它可得到更好的索引處理效能。 對於記憶體在4GB左右的伺服器該參數可設定為256M或384M。 注意:該參數值設定的過大反而會是伺服器整體效率降低! max_allowed_packet = 4M thread_stack = 256K table_cache = 128K sort_buffer_size = 6M
查詢排序時所能使用的緩衝區大小。注意:該參數對應的分配記憶體是每串連獨佔!如果有100個串連,那麼實際分配的總共排序緩衝區大小為100 × 6 = 600MB。所以,對於記憶體在4GB左右的伺服器推薦設定為6-8M。
read_buffer_size = 4M
讀查詢操作所能使用的緩衝區大小。和sort_buffer_size一樣,該參數對應的分配記憶體也是每串連獨享!
join_buffer_size = 8M
聯集查詢操作所能使用的緩衝區大小,和sort_buffer_size一樣,該參數對應的分配記憶體也是每串連獨享!
myisam_sort_buffer_size = 64M table_cache = 512 thread_cache_size = 64 query_cache_size = 64M
指定MySQL查詢緩衝區的大小。可以通過在MySQL控制台執行以下命令觀察:
# > SHOW VARIABLES LIKE '%query_cache%'; # > SHOW STATUS LIKE 'Qcache%'; # 如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩衝不夠的情況;
如果Qcache_hits的值非常大,則表明查詢緩衝使用非常頻繁,如果該值較小反而會影響效率,那麼可以考慮不用查詢緩衝;Qcache_free_blocks,如果該值非常大,則表明緩衝區中片段很多。
tmp_table_size = 256M max_connections = 768
指定MySQL允許的最大串連進程數。如果在訪問論壇時經常出現Too Many Connections的錯誤提 示,則需要增大該參數值。
max_connect_errors = 10000000 wait_timeout = 10
指定一個請求的最大連線時間,對於4GB左右記憶體的伺服器可以設定為5-10。
thread_concurrency = 8
該參數取值為伺服器邏輯CPU數量×2,在本例中,伺服器有2顆物理CPU,而每顆物理CPU又支援H.T超執行緒,所以實際取值為4 × 2 = 8
skip-networking
開啟該選項可以徹底關閉MySQL的TCP/IP串連方式,如果WEB伺服器是以遠端連線的方式訪問MySQL資料庫伺服器則不要開啟該選項!否則將無法正常串連!
================================================
thread_concurrency
數量設定為CPU核心數量的兩倍.
thread_cache_size
按照記憶體大小來設定, 1G=8, 2G=16, 3G=32, >3G=64
wait_timeout
逾時時間,如果串連數比較大,可以減少此參數的值,我使用的是10
max_connections
最大串連數,mysql實際允許串連數的值是max_connections+1,按照系統庫不同而有不同效能.一般是500~1000,MySQL AB提供的linux靜態庫可以達到4000.
query_cache_size
查詢緩衝,預設是0,所以必須開啟以提高mysql效能,其本身需要40K來儲存結構資料.所以不能設定的太小,初期可以設定成32M,然後根據實際運行情況另行調整
query_cache_type
指定查詢緩衝的類型,0是關閉,1是緩衝除了使用SELECT SQL_NO_CACHE語句指明了不需要緩衝的資料意外的所有查詢,2是只緩衝SELECT SQL_CACHE指定的查詢.一般設定為1.
query_cache_limit
允許進入查詢緩衝區的最小資料大小,預設值是1MB,可以修改的小一點以滿足更多查詢的需求.但是如果設定的過於小,則會導致很多新的小查詢的結果將原有的查詢結果交換出去.增加系統的顛簸.
相關命令
查詢mysql伺服器相關狀態資料
>SHOW STATUS;
查詢mysql伺服器相關配置選項
>SHOW VARIABLES;
整理查詢緩衝區裡的片段
>flush query cache;
刪除查詢緩衝區裡的所有內容
>reset query cache;
設定mysql參數
>SET GLOBAL;
查詢mysql當前執行的sql語句
>show processlist;
變數 含義
Qcache_queries_in_cache
在緩衝中登入的查詢數目
Qcache_inserts
被加入到緩衝中的查詢數目
Qcache_hits
緩衝採樣數數目
Qcache_lowmem_prunes
因為缺少記憶體而被從緩衝中刪除的查詢數目
Qcache_not_cached
沒有被緩衝的查詢數目 (不能被緩衝的,或由於 QUERY_CACHE_TYPE)
Qcache_free_memory
查詢快取的空閑記憶體總數
Qcache_free_blocks
查詢快取中的空閑記憶體塊的數目
Qcache_total_blocks
查詢快取中的塊的總數目
MySQL查詢最佳化
>SHOW STATUS LIKE ‘Qcache%’;
查詢出Cache狀態
如果Qcache_lowmem_prunes非常大,說明因為記憶體不足而被交換出cache的資料很多.如果增加記憶體.可以保證較小的交換次數以及較高的命中率
例如現在我們查詢的結果如下
| Qcache_free_blocks | 1234 |
| Qcache_free_memory | 25957504 |
| Qcache_hits | 55771119 |
| Qcache_inserts | 7441153 |
| Qcache_lowmem_prunes | 28332 |
| Qcache_not_cached | 1233788 |
| Qcache_queries_in_cache | 4810 |
| Qcache_total_blocks | 11038 |
設定為64M cache記憶體後
>set global query_cache_size=67108864;
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 66623616 |
| Qcache_hits | 55788258 |
| Qcache_inserts | 7445445 |
| Qcache_lowmem_prunes | 28332 |
| Qcache_not_cached | 1234057 |
| Qcache_queries_in_cache | 183 |
| Qcache_total_blocks | 392 |
自由記憶體塊看起來變小了
是因為現在自由記憶體塊.是一個整塊.而以前的記憶體塊都是分散的小塊
而因為重建了cache區
Qcache_queries_in_cache變數變小了.因為此操作重建立立了cache記憶體區.所有資料重新緩衝
在運行一兩天后我們再看此資料.如果變大了.說明增大cache記憶體地區是有效.如果和以前資料差不多
說明增加的記憶體並沒有實際起到多大的作用.
有人會覺得如果我將cache記憶體設定的非常大
然後將cache_limit設定成0
那麼所有查詢都會被緩衝了
理論上是這樣.但是一台資料庫伺服器的查詢非常多.
如果連查詢單條資料都要緩衝.
那麼記憶體再大也會不夠的.到時候老的內容就會被交換出去
當cache記憶體使用量滿的時候,就會不停的有新查詢進來將老查詢替換出去.
這樣導致兩個結果.一個是記憶體顛簸.效率反而下降.
第二個是cache記憶體的小碎塊增多,記憶體利用率降低
如果是只有內容很少的小庫,並且查詢率不高.是可以使用這種方法提高響應速度
但是如果是實際生產環境,資料量會比較大.還是需要按照最佳比例來配置.
而不同的應用不同的資料量會有不同的搭配,這點大家不要看網上的最佳化配置隨便的填寫
還是要時時的查看mysql的狀態進行調整.即便是這個月調整好的最佳化參數
到了下個月業務不同,資料量增加,也會需要調整的.