起因是因为日志里经常报出锁等待超时的错误,并且这个是环环相扣的,一个锁等待会直接引发另外的锁等待,所以危害非常严重,影响非常深远。寻找原因发现是C3P0
报出了DEADLOCK
,如下图所示:
可以看出来ScatteredAcquireTask
,也就是获取连接的任务,全部卡在那不动了。那显然是无法获取新的数据库连接了。正好前一天刚刚进行过架构上的调整——从应用直连Mysql
变化到中间添加了一层Cobar
(关于Cobar
,它是一个Mysql
代理中间件,用来处理分库)。猜测就是切换到Cobar的问题,但是究竟是什么问题呢?下面我们来一起分析一下:
首先是切换到Cobar
前的服务器结构图:
N台应用 –> 1台Mysql
下面是添加Cobar后的:
N台应用 –> 2台Cobar -> N台Mysql
那么两者之间到底有什么区别呢?我在本地做了一个测试,将C3P0
的初始连接数设置到5000,也就是模拟在大量的连接请求下数据库的反应,看看是否会出现ScatteredAcquireTask
卡住的情况。5000个连接建立完成了,但是出乎意料的是,我用show processlist
查看Mysql线程时,居然并没有看到线程的增长,而是和刚才一样。到这里我差不多已经意识到了问题所在,为了证实这一点,我又用直连数据库的方式起了5000个连接,这次数据库连接果断就上去了。恩,看到这里大家应该也都猜到了吧,与Cobar
建立连接,并不表示与Mysql
建立连接,其实在我们的应用到Mysql
这段道路上存在着两个“池”,一个是我们应用和Cobar
之间的数据库连接池,还有一个是Cobar和Mysql
之间的连接池。应用和Cobar之间的连接数并不存在瓶颈,并且我们也知道它们之间是用NIO
通信的。但是Cobar
和Mysql
之间呢?OH,由于Cobar
只实现了一半的NIO
,所以和Mysql
之间还是走的BIO
。
这里还需要说明的一点是,我们公司的Cobar
服务器是DBA来搭建和维护的。所以对我们后端开发来说所有的配置都是不透明的,我们不熟悉Cobar
的配置也不知道有哪些东西可配置。但是凭借刚才的猜想,已经差不多知道瓶颈就是Cobar
和Mysql
之间。
跟随着自己的猜想,果断百度了一下Cobar
的配置参数,发现有一个参数名为PoolSize
,用来设置Cobar
与后端数据源连接池大小。将其调大,即将问题解决。
并且事后在查看Cobar
的alarm
日志时,发现出问题的时间段内正好打出如下的日志,也更加证实了我的猜想!
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u012345283/article/details/49861153