2010年5月26日 星期三

MySQL 編譯安裝及優化

注意: 由於我是作為數據庫服務器,所以安裝系統時,只需要基本的,其餘的都可以不安裝。

新建一個名為 mysql 的用戶組
# groupadd mysql
在mysql用戶組下新建一個名為mysql的用戶
# useradd -g mysql mysql
# tar xzf mysql-5.0.70.tar.gz
# cd mysql-5.0.70

源碼編譯 MYSQL (環境 CentOS 5.2 + Intel Pentium 4 630 3.00GHz + 4G RAM ,根據具體環境做相應的變更)
# CHOST="i686-pc-linux-gnu" CFLAGS="-O3 -msse -msse2 -msse3 -mmmx -mfpmath=sse,387 -mtune=prescott -march=prescott -pipe -fomit-frame-pointer -Wa, -march=prescott -finline-limit=400 -fforce-addr" CC="gcc" CXX="gcc" CXXFLAGS="${CFLAGS} -fvisibility-inlines-hidden -felide-constructors -fno-exceptions -fno-rtti " LDFLAGS="-Wl,-O2 -s" ./configure --prefix=/usr/local/mysql --localstatedir=/var/lib/mysql --enable-assembler --enable-thread-safe-client - -with-big-tables --with-charset=utf8 --with-collation=utf8_general_ci --without-debug --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static - -with-comment=Source --with-server-suffix=-enterprise-gpl --with-mysqld-user=mysql --with-extra-charsets=gbk,latin1 --with-pthread --with-innodb -- without-isam

至於具體的優化參數就懶得解釋了,因為每個人的具體環境不一樣。

GCC 編譯優化可以參考

1. 英文好的看官方最新文檔
http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options

2. 英文不好的看
http://lamp.linux.gov.cn/Linux/optimize_guide.html

至於 MySQL 的編譯優化可參與 MySQL 5.1 Reference Manual 中編譯指南。

# make
編譯的時間可能會比較長
# make install

編譯安裝完成後執行後續操作:
# cd /usr/local/mysql
# bin/mysql_install_db --user=mysql
# chown -R root . //設置權限,注意後面有一個"."
# chown -R mysql /var/lib/mysql //設置mysql目錄權限
# chgrp -R mysql . //注意後面有一個".",同時讓mysql組用戶有同root的權限
# cp share/mysql/my-innodb-heavy-4G.cnf /etc/my.cnf
# cp share/mysql/mysql.server /etc/init.d/mysqld //開機自動啟動mysql
# chmod 755 /etc/init.d/mysqld
# chkconfig --add mysqld //讓 MySQL 隨機啟動
# /etc/init.d/mysqld start //啟動 MySQL
# bin/mysqladmin -u root password "password_for_root"
# service mysqld stop //關閉 MySQL

由於我是把它作為獨立的數據服務器,為了數據庫系統時間的準確性,最好裝 NTP 服務。
# yum install –y ntp
# crontab -e
0 03 * * * /usr/sbin/ntpdate 1.cn.pool.ntp.org

中國及亞洲 NTP 服務器
server 1.cn.pool.ntp.org
server 1.asia.pool.ntp.org
server 3.asia.pool.ntp.org

以上命令設置好後存盤。
# /sbin/service crond reload

MySQL 的優化分為兩部分,一是服務器物理硬件的優化;二是 MySQL 自身( my.cnf )的優化。

1.服務器硬件對 MySQL 性能的影響
a.磁盤尋道能力,以目前高轉速SATA硬盤(7200轉/秒)為例,這種硬盤理論上每秒尋道7200次,這是物理特性決定的,沒有辦法改變。 MySQL每秒鐘都在進行大量、複雜的查詢操作,對磁盤的讀寫量可想而知。所以,通常認為磁盤I/O是製約MySQL性能的最大因素之一,對於日均訪問量在100萬 PV 以上的應用,由於磁盤I/O的製約,MySQL的性能會非常低下!解決這一制約因素可以考慮以下幾種解決方案。

使用 RAID-0+1 磁盤陣列 ,注意不要嘗試使用 RAID-5 , MySQL 在 RAID-5 磁盤陣列上的效率不會像你期待的那樣快;拋棄傳統的硬盤,使用速度更快的閃存式存儲設備。經過一些測試,使用閃存式存儲設備可比傳統硬盤速度高出6-10倍左右。

b. CPU對於MySQL應用,推薦使用SMP架構的多路對稱CPU。

c. 物理內存對於一台使用 MySQL 的 Database Server 來說非常重要,服務器內存建議不要小於2GB,推薦使用4GB以上的物理內存。

2.MySQL自身因素
當解決了上述服務器硬件製約因素後,看看 MySQL 自身的優化是如何操作的。對 MySQL 自身的優化主要是對其配置文件 my.cnf 中的各項參數進行優化調整。下面介紹一些對性能影響較大的參數。

由於 my.cnf 文件的優化設置是與服務器硬件配置息息相關的,下面服務器硬件環境:
CPU: Pentium 4 630 3.00GHz Threads:2
內存: 4GB DDR2 667
硬盤: SATA 160GB

我們根據以上硬件配置結合一份已經優化好的 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 將無法正常處理連接請求!
注意: 如果從數據庫服務器以外的 PC 連接到 DB Server 很慢時,很可能就是這個參數未打開。

# back_log
這個值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆棧中。只有如果期望在一個短時間內有很多連接,你需要增加它,換句話說,這值對到來的TCP/IP連接的偵聽隊列的大小。你的操作系統在這個隊列大小上有它自己的限制。試圖設定back_log高於你的操作系統的限制將是無效的。 當你觀察你的主機進程列表,發現大量
264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL
的待連接進程時,就要加大 back_log 的值了。默認數值是50,一般384就夠了。

# key_buffer_size
這對 MyISAM 表來說非常重要。如果只是使用 MyISAM 表,可以把它設置為可用內存的30-40% 。合理的值取決於索引大小,數據量以及負載-- 記住: MyISAM 表會使用操作系統的緩存來緩存數據,因此需要留出部分內存給它們,很多情況下數據比索引大多了。儘管如此,需要總是檢查是否所有的 key_buffer 都被利用了 。 -- .MYI 文件只有1GB,而 key_buffer 卻設置為4GB的情況是非常少的,這麼做太浪費了。如果你很少使用 MyISAM 表,那麼也保留不低於16-32MB的 key_buffer_size 以適應給予磁盤的臨時表索引所需。

# sort_buffer_size
查詢排序時所能使用的緩衝區大小。 注意 :該參數對應的分配內存是每連接獨占!如果有100個連接,那麼實際分配的總共排序緩衝區大小為100 × 6 = 600MB 。所以,對於內存在4GB左右的服務器推薦設置為6-8M 。

# read_buffer_size
讀查詢操作所能使用的緩衝區大小。和 sort_buffer_size 一樣,該參數對應的分配內存也是每連接獨享!

# join_buffer_size
聯合查詢操作所能使用的緩衝區大小,和 sort_buffer_size 一樣,該參數對應的分配內存也是每連接獨享!

# query_cache_size
指定 MySQL 查詢緩衝區的大小。可以通過在 MySQL 控制台執行以下命令觀察:
# > SHOW VARIABLES LIKE '%query_cache%';
# > SHOW STATUS LIKE 'Qcache%';
如果 Qcache_lowmem_prunes 的值非常大,則表明經常出現緩沖不夠的情況;
如果 Qcache_hits 的值非常大,則表明查詢緩衝使用非常頻繁,如果該值較小反而會影響效率,那麼可以考慮不用查詢緩衝; Qcache_free_blocks ,如果該值非常大,則表明緩衝區中碎片很多。

# max_connections
指定 MySQL 允許的最大連接進程數。如果在訪問時經常出現 Too Many Connections 的錯誤提示,則需要增大該參數值。

# wait_timeout
指定一個請求的最大連接時間,對於4GB 左右內存的服務器可以設置為5-10 。

# thread_concurrency
該參數取值為服務器邏輯CPU數量×2,在本例中,如果服務器有2顆邏輯CPU,而CPU又支持 HT 超線程,所以實際取值為4 × 2 = 8

# skip-networking
開啟該選項可以徹底關閉 MySQL 的 TCP/IP 連接方式,如果 WEB 服務器是以遠程連接的方式訪問 MySQL 數據庫服務器則不要開啟該選項!否則將無法正常連接!

# innodb_buffer_pool_size
這對 Innodb 表來說非常重要。 Innodb 相比 MyISAM 表對緩衝更為敏感。 MyISAM 可以在默認的 key_buffer_size 設置下運行的可以,然而 Innodb 在默認的 innodb_buffer_pool_size 設置下卻跟蝸牛似的。由於 Innodb 把數據和索引都緩存起來,無需留給操作系統太多的內存,因此如果只需要用 Innodb 的話則可以設置它高達70-80%的可用內存。如果你的數據量不大,並且不會暴增,那麼無需把 innodb_buffer_pool_size 設置的太大了。

# innodb_additional_pool_size
這個選項對性能影響並不太多,至少在有差不多足夠內存可分配的操作系統上是這樣。不過如果你仍然想設置為20MB( 或者更大) ,就需要看一下Innodb 其他需要分配的內存有多少。

# innodb_log_file_size
在高寫入負載尤其是大數據集的情況下很重要。這個值越大則性能相對越高,但是要注意到可能會增加恢復時間。我經常設置為64-512MB ,跟據服務器大小而異。

# innodb_log_buffer_size
默認的設置在中等強度寫入負載以及較短事務的情況下服務器性能還可以。如果存在更新操作峰值或者負載較大,就應該考慮加大它的值了。如果它的值設置太高了,可能會浪費內存(它每秒都會刷新一次),因此無需設置超過1 秒所需的內存空間。通常8-16MB 就足夠了。越小的系統它的值越小。

# innodb_flush_logs_at_trx_commit
Crying about Innodb being 100 times slower than MyISAM ? You probably forgot to adjust this value. Default value of 1 will mean each update transaction commit (or each statement outside of transaction) will need to flush log to the disk which is rather expensive, especially if you do not have Battery backed up cache. Many applications, especially those moved from MyISAM tables are OK with value 2 which means do not flush log to the disk but only flush it to OS cache. The log is still flushed to the disk each second so you normally would not loose more than 1-2 sec worth of updates. Value 0 is a bit faster but is a bit less secure as you can lose transactions even in case MySQL Server crashes. Value 2 only cause data loss with full OS crash.

# table_cache
Opening tables can be expensive. For example MyISAM tables mark MYI header to mark table as currently in use. You do not want this to happen so frequently and it is typically best to size your cache so it is large enough to keep most of your tables open. It uses some OS resources and some memory but for modern hardware it is typically not the problem. 1024 is good value for applications with couple hundreds tables (remember each connection needs its own entry) if you have many connections or many tables increase it larger. I've seen values over 100.000 used.

# thread_cache
Thread creation/destructions can be expensive, which happen at each connect/disconnect. I normally set this value to at least 16. If application has large jumps in amount of concurrent connections and I see fast growth of
Threads_Created variable I boost it higher. The goal is not to have threads created in normal operation.

# query_cache
If your application is read intensive and you do not have application level caches this can be great help. Do not set it too large as it may slow things down as its maintenance may get expensive. Values from 32M to 512M normally make sense. Check it however after a while and see if it is well used. For certain workloads cache hit ratio is lower than would justify having it enabled.

Note: as you can see all of these are global variables. These variables depend on hardware and mix of storage engines, while per session variables are typically workload specific. If you have simple queries there is no reason to increase sort_buffer_size even if you have 64GB of memory to waste. Furthermore doing so may decrease performance.
I normally leave per session variable tuning to second step after I can analyze workload.

注意: 就像你看到的上面這些全局表量,它們都是依據硬件配置以及不同的存儲引擎而不同,但是會話變量通常是根據不同的負載來設定的。如果你只有一些簡單的查詢,那麼就無需增加 sort_buffer_size 的值了,儘管你有64GB的內存。搞不好也許會降低性能。
通常在分析系統負載後才來設置會話變量。

另附:如果發現你的應用日誌裡會有 too many open files 時,應修改 linux 系統的 open file 數量,也可通過以下命令來查看那個程序打開的文件數最多。
# lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more

可能出現的結果如下:
131 24204
57 24244
57 24231
56 24264
其中第一行是打開的文件句柄數量,第二行是進程號。得到進程號後,我們可以通過 ps 命令得到進程的詳細內容。
# ps -aef|grep 24204
mysql 24204 24162 99 16:15 ? 00:24:25 /usr/sbin/mysqld

修改系統默認值 ulimit -HSn 4096
以上命令中,H指定了硬性大小,S指定了軟性大小,n表示設定單個進程最大的打開文件句柄數量可以修改 /etc/profile 把上面命令加到最後,然後 source /etc/profile 再通過 ulimit -a 就可以看到修改後的結果了。

關於lsof命令的用法,詳細可參考IBM技術社區中的一篇關於 lsof 的文章。

摘自:http://janwer.javaeye.com/blog/210952

沒有留言:

wibiya widget