日期:2014-05-16  浏览次数:20921 次

mysql性能监控和优化(摘录)
本文出自 “邹可见” 博客,请务必保留此出处http://zoukejian.blog.51cto.com/131276/58876

三. 性能监控和优化
对于各种不同的数据库来说,不管是数据库性能监控方式还是数据库性能优化方式,在原理和试图达到的目的上都是大同小异,存在很多的共性。当然,具体的监控和调整方法,过程及相关工具会因为不同的数据库而差别很大。比如Oracle性能优化,可以从三个方面入手:硬件升级,内存调优,应用调优。MySQL与之类似,也可以从三个方面下手:硬件升级,进程和内存调优,SQL优化(也就是应用优化)。下面详述。
(一)MySQL性能监控
首先,我们要清楚,哪些指标可以反映出数据库的性能。
就MySQL而言,这些指标可以用来测量数据库性能:
1)CPU,内存和IO在操作系统层面的使用情况;
2)查询响应时间;
3)吞吐量;
4)各种 Cache 命中率;

其次,我们要知道,哪些手段可以用来获得这些指标。
1)配置 sysstat 来收集数据库服务器操作系统层面的CPU,内存,IO 等指标;
2)启用 MySQL 慢查询记录功能来记录下响应时间较长的查询,这些查询往往就是需要做MySQL调整的对象。一旦启用了慢查询记录功能后,超过你设置的查询响应时间的查询就会被记录在你指定的日志文件中,然后,你就可以用mysqldumpslow命令来查看慢查询了。这样启用MySQL慢查询记录功能:
# cat /etc/my.cnf
[mysqld]
; enable the slow query log, default 10 seconds
log-slow-queries
; log queries taking longer than 5 seconds
long_query_time = 5
; log queries that don't use indexes even if they take less than long_query_time
; MySQL 4.1 and newer only
log-queries-not-using-indexes
; long query log file
log-slow-queries = /path/to/file

这样查看慢查询:
# mysqldumpslow /path/to/file
3)收集各种吞吐量和缓存相关信息
      a. 查询Cache:执行SQL语句 show status like 'qcache%' 收集指标值。
      b. 表缓存:MySQL 表对应于磁盘上的文件,表缓存就是文件缓存。执行SQL语句 show status like 'open%tables' 来收集指标值。
      c. 线程缓存:启用了线程缓存后,一个线程在其生命周期中就可以服务多个连接,从而加速MySQL初始连接速度。执行SQL语句 show status like 'threads%' 来收集相关指标值。
      d. 关键字段(key)缓存:跟缓存表一样,缓存关键字段同样可以提高查询效率。执行SQL语句 show status like '%key_read%' 来收集相关指标值。
     e. 临时表:这里的临时表,指的是MySQL内部临时存放需要进一步处理的数据所使用的表,不是我们在存储过程中自定义的临时表。如果临时表放不下需要临时存放的数据,MySQL会使用磁盘来存放,从而降低性能。执行SQL语句 show status like 'created_tmp%' 来收集相关指标值。
     f. 排序区: 当MySQL要执行排序操作的时候,它会使用排序区,如果指定的内存排序区放不下需要排序的数据,MySQL会使用磁盘来存放,从而降低性能。执行SQL语句 show status like 'sort%' 来收集相关指标值。
     g. 全表扫描情况:通常情况下,对大表执行全表扫描很低效,应该尽量避免。执行SQL语句 show status like 'com_select%' 和 show status like handler_read_rnd_next%' 来收集相关指标值。

再次,我们要知道,这些指标的基准值(也即是在数据库正常情况下的值)。
为了判读我们的数据库运行状况是否正常,等待用户反映异常情况是一种方法,通常情况下这种方法不是我们所希望的,因为等待用户反映数据库异常的时候,往往问题都已经很严重了,这时候我们所能做的就是所谓的“应急反应”。更好的更有效的方式是,记录下正常情况下的基准值,然后实时将当前值跟基准值做对比,一旦当前值开始偏移基准值,就应该预警,这样,我们就可以做到所谓的“前馈控制”,在问题刚出现时就解决了。
我们应该收集数据库在各个具有代表性的时间段的基准值,在各种具有代表性的负载时的基准值,尤其是在峰值期间的基准值。收集基准值的方法就是前面讲述的用来获得性能指标值的方法。
对于MySQL性能监控,有几个工具值得一提,mytop, mysqlard 和 mysqlreport,这些工具的安装和使用都很简单,但却是很有用,读者可以试试。

最后,我们要明白,这些指标异常时,我们应该采取什么样的手段,使其恢复到正常的能够接受的值。这是下面MySQL优化的内容。
(二)MySQL 性能优化
正如前面所说的那样,MySQL的优化涉及到三个方面:
1)硬件升级:这种方法很简单,系统负载过高了,好啊,加多CPU;内存不够用了,没问题,再加2G内存,等等。“那如果磁盘IO慢了怎么办呢?”读者可能会问。通常情况下,我们不太可能提高磁盘IO的速度(尽管使用合理的RAID级别,比如1+0,可以在一定程度上提高IO性能,但这往往是一锤子的买卖,试想如果数据库都已经投产了,谁还会轻易去重做RAID。)。实际上磁盘IO跟不上,往往并不是由于磁盘本身IO速度低,而是我们的数据库过度读写磁盘造成的。也就是说,本来可以不用读磁盘就可以搞定的操作,由于我们没有配置好,导致数据库也要去读磁盘。这种方式往往是一种权宜之计,只能解决燃眉之急。随着业务量的继续上升,对数据库处理能力的要求越来越高,升级后硬件的处理能力很快就不能满足要求了。因为数据库的性能问题,往往是由于数据库缺乏可伸缩性引起的。所以,解决数据库性能问题的上策,是提高数据库的可伸缩性。而这种方法,出发点不是解决可伸缩性问题,当然其作用就有限了。而下面的两种方法,是以提高数据库的可伸缩性作为出发点的。
2)优化MySQL进程和内存:
     a. 启用查询缓存: 通过在/etc/my.cnf 文件添加 query_cache_size = < 期望缓存的查询数 > 来启用;
     b. 调整表缓存:通过在/etc/my.cnf文件里面加入 table_cache = <期望缓存的表的数量> 来调整;
     c. 调整MySQL线程缓存:通过在 /etc/my.cnf 文件添加 thread_cache = <期望缓存的进程数> 来调整;
     d. 调整关键字段(key)缓存:通过在/etc/my.cnf文件添加 key_buffer = <期望的关键字段缓存大小>来调整;
     e. 使用临时表:通过在/etc/my.cnf文件添加 tmp_table_size 和max_heap_table_size 来调整;
     f. 设置合适的排序区大小:通过在/etc/my.cnf文件添加 sort_buffer_size = <期望的排序区大小>来调整;
     g. 设置合适的read_buffer_size减少全表扫描次数:通过在/etc/my.cnf文件添加read_buffer_size= <期望的读缓冲区大小>来调整;
     h. 在大表上建索引:
3)优化SQL语句:那些需要调整的SQL语句,往往都被记录在了慢查询日志文件里面了,所以,MySQL会告诉我