运维工程师监控工作之Mysql数据库监控

82 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情

目前互联网公司、金融公司信创建设最常用的数据库是Mysql,由于外部流量压力往往最终落到数据库层面,因此对Mysql数据库的监控几乎是运维工程师的看家本领。数据库监控通常分为业务监控、应用监控、组件监控、资源监控几个层面。

按照google对于监控工作的四个黄金指标论述,即延迟、流量、错误和饱和度设计数据库监控方案: (1)延迟:通常客户端应用程序向Mysql发起select、update等操作,运维工程师需要知道哪些SQL最慢,从而制定合理的调优方案,典型做法有三种:1、在客户端埋点,可以在应用程序层面记录每个SQL的请求耗时,再讲数据统一推送给监控系统,监控系统可以计算平均延迟等各种指标,但是这种做法对业务代码具有侵入性。2、慢查询,Mysql自身提供了慢查询数量指标,例如执行如下代码:

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries  | 6     |
+---------------+-------+
1 row in set (0.01 sec)
注意这个指标是Counter类型的,即单调递增,如果想知道最近五分钟有多少慢查询,需要使用相关函数进行二次计算。3、通过查询performance_schema库、sys_schema库中的统计数据,比如events_statements_summary_by_digest表中记录了延迟、错误量、查询量等很多关键信息,这个后续通过代码演示。
(2)流量:我们最容易想到的就是统计selectupdatedeleteinsert等语句执行的数量,如果流量超过了硬件承载能力,是需要监控和扩容的,上述四种语句指标在Mysql全局变量中可以轻松查到:    
mysql> show global status where Variable_name regexp 'Com_insert|Com_update|Com_delete|Com_select|Questions|Queries';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Com_delete        | 0     |
| Com_delete_multi  | 0     |
| Com_insert        | 0     |
| Com_insert_select | 0     |
| Com_select        | 10    |
| Com_update        | 0     |
| Com_update_multi  | 0     |
| Queries           | 156   |
| Questions         | 138   |
| Slow_queries      | 0     |
+-------------------+-------+
10 rows in set (0.00 sec)

上述指标都是单调递增的,监控mysql整体吞吐量一般看Questions,流量方面指标按照行为习惯,一般会统计写数量(Com_insert+Com_update+Com_delete)、读数量(Com_select)、语句总量(Questions)等。
(3)错误:错误类型非常多,常见的例如执行语句失败,需要有失败计数,典型的采集手段有两种,一是在客户端埋点,缺点是代码具有侵入性;二是从Mysql中采集错误,比如通过Aborted_connects和Connection_errors_max_connections查询数据库连接错误:
mysql> show global status where Variable_name regexp 'Connection_errors_max_connections|Aborted_connects';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Aborted_connects                  | 0     |
| Connection_errors_max_connections | 0     |
+-----------------------------------+-------+
2 rows in set (0.02 sec)

通常我们可以适当调整mysql数据库最大连接数,例如从151修改为2048:
mysql> set global max_connections=2048;
mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 2048  |
+-----------------+-------+
1 row in set (0.02 sec)

4)饱和度:除了部署mysql所在操作系统的CPU、内存、硬盘、I/O、网络流量等基础指标,Mysql自身的饱和度可以按照当前连接线程数除以最大连接数计算连接数使用率,其次还有innodb buffer pool的使用率、内存命中率,例如查询buffer使用情况:
mysql> show global status like '%buffer%';
+---------------------------------------+--------------------------------------------------+
| Variable_name                         | Value                                            |
+---------------------------------------+--------------------------------------------------+
| Error_log_buffered_bytes              | 80440                                            |
| Error_log_buffered_events             | 692                                              |
| Innodb_buffer_pool_dump_status        | Dumping of buffer pool not started               |
| Innodb_buffer_pool_load_status        | Buffer pool(s) load completed at 230208  4:55:37 |
| Innodb_buffer_pool_resize_status      |                                                  |
| Innodb_buffer_pool_pages_data         | 1061                                             |
| Innodb_buffer_pool_bytes_data         | 17383424                                         |
| Innodb_buffer_pool_pages_dirty        | 0                                                |
| Innodb_buffer_pool_bytes_dirty        | 0                                                |
| Innodb_buffer_pool_pages_flushed      | 161                                              |
| Innodb_buffer_pool_pages_free         | 7121                                             |
| Innodb_buffer_pool_pages_misc         | 10                                               |
| Innodb_buffer_pool_pages_total        | 8192                                             |
| Innodb_buffer_pool_read_ahead_rnd     | 0                                                |
| Innodb_buffer_pool_read_ahead         | 0                                                |
| Innodb_buffer_pool_read_ahead_evicted | 0                                                |
| Innodb_buffer_pool_read_requests      | 24504                                            |
| Innodb_buffer_pool_reads              | 920                                              |
| Innodb_buffer_pool_wait_free          | 0                                                |
| Innodb_buffer_pool_write_requests     | 1640                                             |
+---------------------------------------+--------------------------------------------------+
20 rows in set (0.01 sec)

其中4个关键指标需要重点关注:
Innodb_buffer_pool_pages_total:表示 InnoDB Buffer pool 的页总量
Innodb_buffer_pool_pages_free: 表示剩余页数量
Innodb_buffer_pool_read_requests:表示向buffer pool发起的查询总量,如果buffer pool缓存了数据,可以直接返回,如果没有数据,肯定需要穿透内存转到硬盘查询。
Innodb_buffer_pool_reads:表示不能从缓冲池满足的逻辑读取的数量,必须从硬盘读取。