监控MySQL状态是否正常
# 监控MySQL状态是否正常
innodb_thread_concurrency:控制InnoDB并发线程上限,一旦超过这个阈值,InnoDB接收到新的请求时就会进入等待状态。一般情况下设置为64~128之间某个值。
想要检测当前MySQL状态是否正常,实际上相当于检测当前并发线程数是否过多超出了阈值,导致系统不可用。
# select 1判断
如果通过select 1成功返回,只能说明这个库的进程还在(即使当前并发线程数已经达到上限也能够正常返回),但是对某个数据表的查询依然会继续阻塞。因此通过select 1并不能检查当前数据库的状态是否可用。
并发连接:执行show processlist结果看到的连接数,一般情况下并发连接数会大于并发线程数,
并发查询/并发线程:真正消耗CPU资源,正在执行查询事务的线程数量。
某个线程进入查询事务时,如果遇到锁等待,那么该线程就不会算入当前MySQL的并发线程数当中,“并发线程”计数减一。因为进入锁等待后,该线程并不会吃CPU资源,最多也就占用内存。MySQL这么设计的原因主要有两个:
- 提高数据库的并发能力
- 避免整个系统锁住。防止出现CPU利用率为0而整个数据库处于不可用的状态。
# 查表判断
在系统库创建一个表,里面随便放入一行数据,并定期执行。相比于上面一种方法,因为这里是具体对某个表的查询,因此超过并发线程数时会被阻塞。
select * from mysql.health_check;
💣存在的问题:磁盘空间占用率占满后就不能正常写binlog,后续所有更新语句和事务提交都会被阻塞住。而此时系统是可以正常读数据的,感受不到磁盘的情况。
# 更新判断
在外部表上将查询语句改为执行更新语句,因为更新语句会提交事务并且写binlog,所以如果磁盘空间不足就会超时不返回,从而确认“当前系统不可用”。
而对于一主多从的结构,因为主备库都会执行更新检测,执行时机存在先后差异,并且存在行冲突。因此系统活性表需要以每个主备库的server_id作为主键来更新插入行记录(主备库的server_id是不同且唯一的),每个库各自维护自己的检测时间。
insert into mysql.health_check(id,t_modified) values(@@server_id,now()) on duplicate key update t_modified=now();
💣存在的问题:“判定慢”。具体来说,上述更新语句需要的IO资源少,执行比较快且能立刻返回。可能下一时刻系统上的SQL就已经执行的很慢了,而前一时刻DBA拿到更新语句的返回结果,还认为“当前数据库系统正常”。
外部检测的缺陷在于,检测查询的时机是随机的,可能系统在当前时刻就已经出现问题,却需要等到下一次检测才能发现。
# 内部统计
performance_schema库中的file_summary_by_event_name表统计了每次IO请求的时间,通过内部每次IO请求的时间(比如单次IO耗时超过阈值),判断出当前数据库是否因为磁盘利用率导致系统不可用。
因为每次操作数据库,performance_schema都会统计IO的时间戳信息,是有损的。因此只需要打开用到的统计功能。
binlog对应的行数据是event_name="wait/io/file/sql/binlog"
执行以下语句打开redo log的时间监控
update setup_instruments set ENABLED='YES', Timed='YES' where name like '%wait/io/file/innodb/innodb_log_file%';1根据IO统计信息的MAX_TIMER的值来判断,如果单次IO请求时间超过某个阈值,则判断系统异常。
select event_name,MAX_TIMER_WAIT FROM performance_schema.file_summary_by_event_name where event_name in ('wait/io/file/innodb/innodb_log_file','wait/io/file/sql/binlog') and MAX_TIMER_WAIT>200*1000000000;1把先前的统计信息清空,方便后续的监控
truncate table performance_schema.file_summary_by_event_name;1
# 其它监控指标
服务状态监控:外部系统和第三方中间件。
服务质量监控:接口响应时间来判断。
基础监控:硬盘、CPU、网络、内存