MySQL 数据库的性能状态监控点非常之多,其中很多量都是我们不能忽视的必须监控的
量,且90% 以上的内容可以在连接上MySQL Server 后执行“SHOW /*!50000 GLOBAL */
STATUS” 以及“SHOW /*!50000 GLOBAL */ VARIABLES” 的输出值获得。需要注意的是上
述命令所获得状态值实际上是累计值,所以如果要计算(单位/某个)时间段内的变化量还需
要稍加处理,可以在附录中找到两个命令输出值的详细说明。下面看看几项需要重点关注的
性能状态:
● QPS(每秒Query 量):这里的QPS 实际上是指MySQL Server 每秒执行的Query
总量,在MySQL 5.1.30 及以下版本可以通过Questions 状态值每秒内的变化量
来近似表示,而从MySQL 5.1.31 开始,则可以通过Queries 来表示。Queries 是
在MySQL 5.1.31 才新增的状态变量。主要解决的问题就是Questions 状态变量
并没有记录存储过程中所执行的Query(当然,在无存储过程的老版本MySQL 中
则不存在这个区别),而Queries 状态变量则会记录。二者获取方式:
QPS = Questions(or Queries) / Seconds
获取所需状态变量值:
SHOW /*!50000 GLOBAL */ STATUS LIKE 'Questions'
SHOW /*!50000 GLOBAL */ STATUS LIKE 'Queries'
这里的Seconds 是指累计出上述两个状态变量值的时间长度,后面用到的地方也
代表同样的意思。
● TPS(每秒事务量): 在MySQL Server 中并没有直接事务计数器,我们只能通过
回滚和提交计数器来计算出系统的事务量。所以,我们需要通过以下方式来得到客
户端应用程序所请求的TPS 值:
TPS = (Com_commit + Com_rollback) / Seconds
如果我们还使用了分布式事务,那么还需要将Com_xa_commit 和
Com_xa_rollback 两个状态变量的值加上。
● Key Buffer 命中率:Key Buffer 命中率代表了MyISAM 类型表的索引的Cache
命中率。该命中率的大小将直接影响MyISAM 类型表的读写性能。Key Buffer 命
中率实际上包括读命中率和写命中率两种,MySQL 中并没有直接给出这两个命中率
的值,但是可以通过如下方式计算出来:
key_buffer_read_hits = (1 - Key_reads / Key_read_requests) * 100%
key_buffer_write_hits= (1 - Key_writes / Key_write_requests) * 100%
获取所需状态变量值:
sky@localhost : (none) 07:44:10> SHOW /*!50000 GLOBAL */ STATUS
-> LIKE 'Key%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
... ...
| Key_read_requests | 10 |
| Key_reads | 4 |
| Key_write_requests | 0 |
| Key_writes | 0 |
+------------------------+-------+
通过这两个计算公式,我们很容易就可以得出系统当前Key Buffer 的使用情况
● Innodb Buffer 命中率:这里Innodb Buffer 所指的是innodb_buffer_pool,也
就是用来缓存Innodb 类型表的数据和索引的内存空间。类似Key buffer,我们
同样可以根据MySQL Server 提供的相应状态值计算出其命中率:
innodb_buffer_read_hits=(1-
Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests) * 100%
获取所需状态变量值:
sky@localhost : (none) 08:25:14> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Innodb_buffer_pool_read%';
+-----------------------------------+-------+
| Variable_name | Value |
+-----------------------------------+-------+
... ...
| Innodb_buffer_pool_read_requests | 5367 |
| Innodb_buffer_pool_reads | 507 |
+-----------------------------------+-------+
● Query Cache 命中率:如果我们使用了Query Cache,那么对Query Cache 命中
率进行监控也是有必要的,因为他可能告诉我们是否在正确的使用Query Cache。
Query Cache 命中率的计算方式如下:
Query_cache_hits= (Qcache_hits / (Qcache_hits + Qcache_inserts)) * 100%
获取所需状态变量值:
sky@localhost : (none) 08:32:01> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Qcache%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
... ...
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
... ...
+-------------------------+-------+
● Table Cache 状态量:Table Cache 的当前状态量可以帮助我们判断系统参数
table_open_cache 的设置是否合理。如果状态变量Open_tables 与
Opened_tables 之间的比率过低,则代表Table Cache 设置过小,个人认为该值
处于80% 左右比较合适。注意,这个值并不是准确的Table Cache 命中率。
获取所需状态变量值:
sky@localhost : (none) 08:52:00> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Open%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
... ...
| Open_tables | 51 |
... ...
| Opened_tables | 61 |
+--------------------------+-------+
● Thread Cache 命中率:Thread Cache 命中率能够直接反应出我们的系统参数
thread_cache_size 设置的是否合理。一个合理的thread_cache_size 参数能够
节约大量创建新连接时所需要消耗的资源。Thread Cache 命中率计算方式如下:
Thread_cache_hits = (1 - Threads_created / Connections) * 100%
获取所需状态变量值:
sky@localhost : (none) 08:57:16> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Thread%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
... ...
| Threads_created | 3 |
... ...
+-------------------+-------+
4 rows in set (0.01 sec)
sky@localhost : (none) 09:01:33> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Connections';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Connections | 11 |
+---------------+-------+
正常来说,Thread Cache 命中率要在90% 以上才算比较合理。
● 锁定状态:锁定状态包括表锁和行锁两种,我们可以通过系统状态变量获得锁定总
次数,锁定造成其他线程等待的次数,以及锁定等待时间信息。
sky@localhost : (none) 09:01:44> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE '%lock%';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
... ...
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 0 |
| Innodb_row_lock_time_avg | 0 |
| Innodb_row_lock_time_max | 0 |
| Innodb_row_lock_waits | 0 |
... ...
| Table_locks_immediate | 44 |
| Table_locks_waited | 0 |
+-------------------------------+-------+
通过上述系统变量,我们可以得出表锁总次数,其中造成其他现线程等待的次数。
同时还可以得到非常详细的行锁信息,如行锁总次数,行锁总时间,每次行锁等待
时间,行锁造成最大等待时间以及当前等待行锁的线程数。通过对这些量的监控,
我们可以清晰的了解到系统整体的锁定是否严重。如当Table_locks_waited 与
Table_locks_immediate 的比值较大,则说明我们的表锁造成的阻塞比较严重,可
能需要调整Query 语句,或者更改存储引擎,亦或者需要调整业务逻辑。当然,
具体改善方式必须根据实际场景来判断。而Innodb_row_lock_waits 较大,则说
明Innodb 的行锁也比较严重,且影响了其他线程的正常处理。同样需要查找出原
因并解决。造成Innodb 行锁严重的原因可能是Query 语句所利用的索引不够合
理(Innodb 行锁是基于索引来锁定的),造成间隙锁过大。也可能是系统本身处理
能力有限,则需要从其他方面(如硬件设备)来考虑解决。
● 复制延时量:复制延时量将直接影响了Slave 数据库处于不一致状态的时间长短。
如果我们是通过Slave 来提供读服务,就不得不重视这个延时量。我们可以通过
在Slave 节点上执行“SHOW SLAVE STATUS”命令,取Seconds_Behind_Master 项
的值来了解Slave 当前的延时量(单位:秒)。当然,该值的准确性依赖于复制是
否处于正常状态。每个环境下的Slave 所允许的延时长短与具体环境有关,所以
复制延时多长时间是合理的,只能由读者朋友根据各自实际的应用环境来判断。
● Tmp table 状况:Tmp Table 的状况主要是用于监控MySQL 使用临时表的量是否
过多,是否有临时表过大而不得不从内存中换出到磁盘文件上。临时表使用状态信
息可以通过如下方式获得:
sky@localhost : (none) 09:27:28> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Created_tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 1 |
... ...
| Created_tmp_tables | 46 |
+-------------------------+-------+
从上面的状态信息可以了解到系统使用了46 次临时表,其中有1 次临时表比较大,
无法在内存中完成,而不得不使用到磁盘文件。如果Created_tmp_tables 非常大,
则可能是系统中排序操作过多,或者是表连接方式不是很优化。而如果是
Created_tmp_disk_tables 与Created_tmp_tables 的比率过高,如超过10%,则
我们需要考虑是否tmp_table_size 这个系统参数所设置的足够大。当然,如果系
统内存有限,也就没有太多好的解决办法了。
● Binlog Cache 使用状况:Binlog Cache 用于存放还未写入磁盘的Binlog 信息。
相关状态变量如下:
sky@localhost : (none) 09:40:38> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Binlog_cache%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Binlog_cache_disk_use | 0 |
| Binlog_cache_use | 0 |
+-----------------------+-------+
如果Binlog_cache_disk_use 值不为0,则说明Binlog Cache 大小可能不够,
建议增加binlog_cache_size 系统参数大小。
● Innodb_log_waits 量:Innodb_log_waits 状态变量直接反应出Innodb Log
Buffer 空间不足造成等待的次数。
sky@localhost : (none) 09:43:53> SHOW /*!50000 GLOBAL*/ STATUS
-> LIKE 'Innodb_log_waits';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Innodb_log_waits | 0 |
+------------------+-------+
该变量值发生的频率将直接影响系统的写入性能,所以当该值达到每秒1 次时就该
增加系统参数innodb_log_buffer_size 的值,毕竟这是一个系统共用的缓存,适
当增加并不会造成内存不足的问题。
上面这些监控量只是我个人认为比较重要的一些MySQL 性能监控量,各位读者朋友还
可以根据各自的需要,通过MySQL 所提供的系统状态变量增加其他监控内容。


【摘自《MySQL性能调优与架构设计》】