内容摘要Q用MySQL服务的一些经验,主要从以下几个方面考虑的MySQL服务规划设计。对于高负蝲站点来说PHP和MySQLq行在一P或者说M应用和数据库q行在一L规划Q都是性能最大的瓉Q这L设计有如让h一手画圆一手画方,q样2个h的工作效率肯定不如让一个h专门d一个h专门L效率高,让应用和数据库都跑在一台高性能服务器上说不定还不如跑在2台普通服务器上快?br>
以下是针对MySQL作ؓ专门的数据库服务器的优化Q?/p>
- MySQL服务的安?配置的通用性;
- pȝ的升U和数据q移方便性;
- 备䆾和系l快速恢复;
- 数据库应用的设计要点Q?
- 一ơ应用优化实战;
MySQL服务器的规划
=================
Z以后l护Q升U备份的方便和数据的安全性,最好将MySQLE序文g和数据分别安装在“不同的硬?#8221;上?br>
/ /
| /usr <== 操作pȝ
| /home/mysql <== mysqlȝ录,Z方便升Q这只是一个最新版本目录的链接
盘1==>| /home/mysql-3.23.54/ <== 最新版本的mysql /home/mysql链接到这?br> \ /home/mysql-old/ <== 以前q行的旧版本的mysql
/ /data/app_1/ <== 应用数据和启动脚本等
盘2==>| /data/app_2/
\ /data/app_3/
MySQL服务的安装和服务的启动:
MySQL一般用当前STABLE的版本:
量不?-with-charset=选项Q我感觉with-charset只在按字母排序的时候才有用Q这些选项会对数据的迁Ud来很多麻烦?br>量不用innodbQinnodb主要用于需要外键,事务{企业支持Q代h速度比MYISAM有数量的下降?br>./configure --prefix=/home/mysql --without-innodb
make
make install
服务的启动和停止
================
1 复制~省的mysql/var/mysql?/data/app_1/目录下,
2 MySQLD的启动脚本:start_mysql.sh
#!/bin/sh
rundir=`dirname "$0"`
echo "$rundir"
/home/mysql/bin/safe_mysqld --user=mysql --pid-file="$rundir"/mysql.pid --datadir="$rundir"/var "$@"\
-O max_connections=500 -O wait_timeout=600 -O key_buffer=32M --port=3402 --socket="$rundir"/mysql.sock &
注释Q?br>--pid-file="$rundir"/mysql.pid --socket="$rundir"/mysql.sock --datadir="$rundir"/var
目的都是相应数据和应用临时文g攑֜一P
-O 后面一般是服务器启动全局变量优化参数Q有时候需要根据具体应用调_
--port: 不同的应用用PORT参数分布C同的服务上去Q一个服务可以提供的q接C般是MySQL服务的主要瓶颈;
修改不同的服务到不同的端口后Q在rc.local文g中加入:
/data/app_1/start_mysql.sh
/data/app_2/start_mysql.sh
/data/app_3/start_mysql.sh
注意Q必d全\?br>
3 MySQLD的停止脚本:stop_mysql.sh
#!/bin/sh
rundir=`dirname "$0"`
echo "$rundir"
/home/mysql/bin/mysqladmin -u mysql -S"$rundir"/mysql.sock shutdown
使用q个脚本的好处在于:
1 多个服务启动Q对于不同服务只需要修改脚本中?-port[=端口号]参数。单个目录下的数据和服务脚本都是可以独立打包的?br>2 所有服务相应文仉位于/data/app_1/目录下:比如Qmysql.pid mysql.sockQ当一台服务器上启动多个服务时Q多个服务不会互相媄响。但都放到缺省的/tmp/下则有可能被其他应用误删?br>3 当硬?出问题以后,直接硬?攑ֈ一台装好MySQL的服务器上就可以立刻恢复服务Q如果放到my.cnf里则q需要备份相应的配置文gQ?
服务启动?data/app_1/下相应的文g和目录分布如下:
/data/app_1/
start_mysql.sh 服务启动脚本
stop_mysql.sh 服务停止脚本
mysql.pid 服务的进EID
mysql.sock 服务的SOCK
var/ 数据?br> mysql/ 用户?br> app_1_db_1/ 应用?br> app_1_db_2/
...
/data/app_2/
...
查看所有的应用q程IDQ?br>cat /data/*/mysql.pid
查看所有数据库的错误日志:
cat /data/*/var/*.err
个hQMySQL的主要瓶颈在PORT的连接数上,因此Q将表结构优化好以后Q相应单个MySQL服务的CPU占用仍然?0Q以上,p考虑服务拆分到多个PORT上运行了?/p>
服务的备?br>==========
量使用MySQL DUMP而不是直接备份数据文Ӟ以下是一个按weekday数据轮循备份的脚本Q备份的间隔和周期可以根据备份的需求确?br>/home/mysql/bin/mysqldump -S/data/app_1/mysql.sock -umysql db_name | gzip -f>/path/to/backup/db_name.`date +%w`.dump.gz
因此写在CRONTAB中一般是Q?br>15 4 * * * /home/mysql/bin/mysqldump -S/data/app_1/mysql.sock -umysql db_name | gzip -f>/path/to/backup/db_name.`date +\%w`.dump.gz
注意Q?br>1 在crontab?%'需要{义成'\%'
2 Ҏ日志l计Q应用负载最低的时候一般是在早?-6?br>
先备份在本地然后传到q程的备份服务器上,或者直接徏立一个数据库备䆾帐号Q直接在q程的服务器上备份,q程备䆾只需要将以上脚本中的-S /path/to/msyql.sockҎ-h IP.ADDRESS卛_?br>
数据的恢复和pȝ的升U?br>======================
日常l护和数据迁U:在数据盘没有被破坏的情况?br>盘一般是pȝ中寿命最低的g。而系l(包括操作pȝ和MySQL应用Q的升和硬件升U,都会遇到数据q移的问题?br>只要数据不变Q先装好服务器,然后直接数据盘Q硬?Q安装上Q只需要将启动脚本重新加入到rc.local文g中,pȝq是很好的恢复了?br>
N恢复Q数据库数据本n被破坏的情况?br>定破坏的时间点Q然后从备䆾数据中恢复?/p>
应用的设计要?br>==============
如果MySQL应用占用的CPU过10%应该考虑优化了?br>
- 如果q个服务可以被其他非数据库应用代替(比如很多Z数据库的计数器完全可以用WEB日志l计代替Q最好将其禁用:
非用数据库不可吗Q虽然数据库的确可以化很多应用的l构设计Q但本n也是一个系l资源消耗比较大的应用。在某些情况下文本,DBM比数据库是更好的选择Q比如:很多应用如果没有很高的实时统计需求的话,完全可以先记录到文g日志中,定期的导入到数据库中做后l统计分析。如果还是需要记录简单的2l键Q值对应结构的话可以用类gDBM的HEAPcd表。因为HEAP表全部在内存中存取,效率非常高,但服务器H然断电时有可能出现数据丢失Q所以非帔R合存储在线用户信息Q日志等临时数据。即佉K要用数据库的,应用如果没有太复杂的数据完整性需求的化,完全可以不用那些支持外键的商业数据库,比如MySQL。只有非帔R要完整的商业逻辑和事务完整性的时候才需要Oracleq样的大型数据库。对于高负蝲应用来说完全可以把日志文ӞDBMQMySQL{轻量方式做前端数据采集格式,然后用Oracle MSSQL DB2 Sybase{做数据库仓库以完成复杂的数据库挖掘分析工作?br>有朋友和我说用标准的MyISAM表代替了InnoDB表以后,数据库性能提高?0倍?br>
- 数据库服务的主要瓉Q单个服务的q接?br>对于一个应用来_如果数据库表l构的设计能够按照数据库原理的范式来设计的话Qƈ且已l用了最新版本的MySQLQƈ且按照比较优化的方式q行了,那么最后的主要瓉一般在于单个服务的q接敎ͼ即一个数据库可以支持q发500个连接,最好也不要把应用用到这个地步,因ؓq发q接数过多数据库服务本n用于调度的线E的开销也会非常大了。所以如果应用允许的话:让一台机器多跑几个MySQL服务分担。将服务均衡的规划到多个MySQL服务端口上:比如app_1 ==> 3301 app_2 ==> 3302...app_9 ==> 3309。一?G内存的机器跑?0个MySQL是很正常的。让10个MySQLD承担1000个ƈ发连接效率要比让2个MySQLD承担1000个效率高的多。当Ӟq样也会带来一些应用编E上的复杂度Q?br>
- 使用单独的数据库服务器(不要让数据库和前台WEB服务抢内存)QMySQL拥有更多的内存就可能能有效的q行l果集的~存Q在前面的启动脚本中有一?O key_buffer=32M参数是用于缺省的8M索引~存增加?2MQ当然对于)
- 应用量使用PCONNECT和polling机制Q用于节省MySQL服务建立q接的开销Q但也会造成MySQLq发链接数过多(每个HTTPD都会对应一个MySQLU程Q;
- 表的横向拆分Q让最常被讉K?0%的数据放在一个小表里Q?0%的历史数据放在一个归档表里(所谓:快慢表)Q数据中间通过定期“搬家”和定期删除无效数据来节省Q毕竟大部分应用Q比如论坛)讉K2个月前数据的几率会非常少Q而且价g不是很高。这样对于应用来说L在一个比较小的结果中进行数据选择Q比较有利于数据的缓存,不要指望MySQL中对单表记录条数?0万以上q有比较高的效率。而且有时候数据没有必要做那么_Q比如一个快表中查到了某个h发表的文章有60条结果,快表和慢表的比例?:20Q那么就可以单的估计q个Z共发表了1200。Google的搜索结果数也是一P对于很多上十万的l果敎ͼ后面很多的数字都是通过一定的法估计出来的?br>
- 数据库字D设计:表的U向拆分Q过渡范化)Q将所有的定长字段Qchar, int{)攑֜一个表里,所有的变长字段Qvarchar,text,blob{)攑֜另外一个表里,2个表之间通过主键兌Q这P定长字段表可以得到很大的优化Q这样可以用HEAP表类型,数据完全在内存中存取Q,q里也说明另外一个原则,对于我们来说Q尽量用定长字D可以通过I间的损失换取访问效率的提高。在MySQL4中也出现了支持外键和事务的InnoDBcd表,标准的MyISAM格式表和ZHASHl构的HEAP内存表,MySQL之所以支持多U表cdQ实际上是针对不同应用提供了不同的优化方式;
- 仔细的检查应用的索引设计Q可以在服务启动参数中加?--log-slow-queries[=file]用于跟踪分析应用瓉Q对于跟t服务瓶颈最单的Ҏ是用MySQL的status查看MySQL服务的运行统计和show processlist来查看当前服务中正在q行的SQLQ如果某个SQLl常出现在PROCESS LIST中,一。有可能被查询的此时非常多,二,里面有媄响查询的字段没有索引Q三Q返回的l果数过多数据库正在排序QSORTINGQ;所以做一个脚本:比如?U运行以下show processlist;把结果输出到文g中,看到底是什么查询在吃CPU?br>
- 全文索:如果相应字段没有做全文烦引的话,全文索将是一个非常消耗CPU的功能,因ؓ全文索是用不上一般数据库的烦引的Q所以要q行相应字段记录遍历。关于全文烦引可以参考一下基?a >Java的全文烦引引擎lucene的介l?/font>?br>
- 前台应用的记录缓存:比如一个经怋用数据库认证Q如果需要有更新用户最后登陆时间的操作Q最好记录更新后把用户攑ֈ一个缓存中Q设|?个小时后q期Q,q样如果用户?个小时内再次使用到登陆,q接从~存里认证,避免了过于频J的数据库操作?br>
- 查询优先的表应该可能ؓwhere和order by字句中的字段加上索引Q数据库更新插入优先的应用烦引越越好?br>
MQ对于Q何数据库单表记录过100万条优化都是比较困难的,关键是要把应用能够{化成数据库比较擅长的数据上限内。也是把复杂需求简化成比较成熟的解x案内?/p>
一ơ优化实?br>============
以下例子是对一个论坛应用进行的优化Q?br>
- 用Webalizer代替了原来的通过数据库的l计?br>
- 首先通过TOP命o查看MySQL服务的CPU占用左右80%和内存占用:10MQ说明数据库的烦引缓存已l用完了Q修改启动参敎ͼ增加?O key_buffer=32MQ过一D|间等数据库稳定后看的内存占用是否辑ֈ上限。最后将~存一直增加到64MQ数据库~存才基本能充分使用。对于一个数据库应用来说Q把内存l数据库比给WEB服务实用的多Q因为MySQL查询速度的提高能加快web应用从而节省ƈ发的WEB服务所占用的内存资源?br>
- 用show processlist;l计l常出现的SQLQ?br>
每分钟运行一ơshow processlistq记录日志:
* * * * * (/home/mysql/bin/mysql -uuser -ppassword < /home/chedong/show_processlist.sql >> /home/chedong/mysql_processlist.log)
show_processlist.sql里就一句:
show processlist;
比如可以从日志中包含where的字句过滤出来:
grep where mysql_processlist.log
如果发现有死锁,一定要重新审视一下数据库设计了,对于一般情况:查询速度很慢Q就SQL where字句中没有烦引的字段加上索引Q如果是排序慢就order by字句中没有烦引的字段加上。对于有%like%的查询,考虑以后用和用全文烦引加速?br>
- q是Ҏshow processlist;看经常有那些数据库被频繁使用Q考虑数据库拆分到其他服务端口上?
MSSQL到MySQL的数据迁U:ACCESSQMySQL ODBC Driver
在以前的几次数据q移实践q程中,我发现最便的数据q移q程q不是通过专业的数据库q移工具Q也不是MSSQL自n的DTSq行数据q移Q迁U过E中间会有很多表出错误警告)Q但通过MSSQL数据库通过ACCESS获取外部数据导入到数据库中,然后用ACCESS的表==>右键==>导出Q制定ODBCQ通过MySQL的DSN数据导出。这栯Ud部分数据都会非常利Q如果导出的表有索引问题Q还会出d索引提示QDTS׃行)Q然后剩余的工作是在MySQL中设计字D对应的SQL脚本了?/p>
参考文档:
MySQL的参考:
http://dev.mysql.com/doc/