MySQL如何判断一个数据库是否出问题

文章字数:,阅读全文大约需要9分钟

原文《MySQL实战45讲》

前言

我第一次使用select1,是在项目里面引入Druid时看到了连接的有效性判断配置,部分配置如下:

······propertyname="validationQuery"value="select1"/propertyname="testWhileIdle"value="true"/propertyname="testOnBorrow"value="false"/propertyname="testOnReturn"value="false"/······

在Druid的参考配置中,我们可以看到,通过“select1”,连接池就可以判断连接是否有效了。但是"select1"返回了,就表示主库没问题吗?经过学习,发现还真不是这么简单。

select1判断

实际上,select1成功返回,只能说明这个库的进程还存在,并不能说明数据库没有问题,以一下场景为例。

#设置innodb的并发线程数setglobalinnodb_thread_concurrency=3;#建表语句CREATETABLE`t`(`id`int(11)NOTNULL,`c`int(11)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDB;#数据初始化insertintotvalues(1,1)

设置innodb_thread_concurrency是为了控制InnoDB的并发线程上限。也就是说,一旦并发线程数达到这个值,InnoDB就不会马上执行新的请求,而是等待线程资源,直到当前正在执行的线程退出。InnoDB中,innodb_thread_concurrency默认为0,表示不限制并发线程数。但是不设置并发线程数肯定是不行的,因为机器的CPU处理能力有限,大量线程切换处理的过程中,上下文切换的成本太高。

在sessionD中,select1;是可以执行成功的,但实际查询语句却被blocked。也就是说,这个场景下,使用select1;并不能检测到问题。

不要混淆并发连接和并发查询

showprocesslist的结果里,看到的是并发连接,并发连接多只是多占用一些内存,实际消耗CPU资源的是并发查询。

而“当前正在执行”的语句,才是我们所说的并发查询。

在线程进入锁等待后,并发线程会减一

热点数据更新和死锁检测的时候,如果innodb_thread_concurrency设置的太小,同时该热点行更新过程中,发生了死锁等问题,那等待更新该行的线程岂不是很快就达到innodb_thread_concurrency了,导致数据库没有空闲的资源可以执行其他请求?

实际上,等待行锁的(也包括间隙锁)的线程是不算会算在innodb_thread_concurrency里面的。MySQL为什么要这么设计呢?因为,进入锁等待的线程已经不再消耗CPU了,更重要的是,这么设计可以避免整个数据系统被锁死。

举个例子:innodb_thread_concurrency设置为,此时有个线程等待同一个行锁;但是这个时候还是可以继续处理新的请求的,因为等待行锁的线程并不会占用innodb_thread_concurrency。当然,但等待中的线程真正的执行查询,就会占用innodb_thread_concurrency了。

查表判断

为了能够检测InnoDB并发线程数过多而导致系统不可用的情况,我们需要找一个访问InnoDB的场景。常见的做法是,在系统库(mysql库)里创建一个表,比如命名为health_check,里面放一行数据,然后定期执行。

mysqlselect*frommysql.health_check;

使用这个方法,我们可以检测出由于并发线程过多导致的数据库不可用的情况。但是,我们马上还会碰到下一个问题,即:磁盘空间满了以后,这个方法就无能为力了。

对于更新操作的事务,提交后是需要写binlog的,如果binlog所在的磁盘占用达到了%了,那么所有的更新语句提交的


转载请注明:http://www.aierlanlan.com/rzdk/323.html

  • 上一篇文章:
  •   
  • 下一篇文章: