首先,连接池是为了节省打开关闭数据库连接的一个手段,如果不用连接池,最大能获取连接的数量限制则是mysql等数据库端配置的max_connections字段的数量。
使用连接池后,最大连接数就由程序这边来控制了,例如一般的最大连接数为20。
一个连接池的配置最常见,最关键的配置是最大连接数和超时时间
<!-- 配置初始化大小、最小、最大 --> <property name="maxActive" value="20" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="60000" />
然后大部分程序配置就是这些了。
首先说一下Too many connections这个问题,其实如果是使用的连接池,除非连接池存在bug或者多处初始化连接池一般是不会出现这个异常。原因是连接池就已经限制了最大连接数,基本上是不会超过数据库的最大连接数的。
然后就是超时问题:
现在你的程序可能会出现1个问题:获取连接超时了
一般情况下你可能想到的解决办法是调大最大连接池数量,增加超时时间。
但是这个做法只是掩盖了问题,而没有解决问题。而且sql抛出异常是个比较危险的行为。
因为,你不知道你的业务逻辑进行到哪一步的情况下才会抛出异常,而且大部分程序不会对dao业务进行try catch处理。举例说明:
某个service方法:
public void addGold(int gold){ User user=dao.getUser(uid); user.setGold(user.getGold); dao.update(user); }
有可能在update这一步报错,导致了什么问题呢。现在的系统大部分都用上了缓存,user 的值被修改过了很可能已经在缓存的值修改过了。然后数据库操作这边抛出了异常导致了两遍数据不一致的问题。
而且,前面说了。调大部分数值只是掩盖、拖延问题。
如何解决问题?首先,出现超时错误的原因就是1个:获取不到连接。
为什么获取不到连接?因为某些逻辑一直占用了连接导致了没有连接分配给你了,造成你超时。
而一般正常的情况下,不会有这种逻辑出现。所以我们要找出这些问题所在。
而且,获取不到连接问题抛出异常可能会影响你的现有业务。因为这是一个比较随机的事情,你的业务可能进行一半的时候抛出异常。A执行了,B没有执行。你可能会说有事物在可以回滚,但是实际上A的数据已经被同步到了缓存里面了,B的数据不一致。你能回滚缓存里面的数据吗。
所以我的建议是:maxWait这个不能随便就超时了。因为这个会影响业务,而且连接不一定是一直都被阻断的,总有能恢复正常获取到的时候。
就例如前面配置的超时时间:1分钟,已经超时1分钟的业务不在乎多等一会直到业务完成。
反而我们要找出导致问题的元凶,长时间占用连接的方法。
<!-- 防止某些连接被长期占用 单位秒 --> <property name="removeAbandoned" value="true" /> <property name="removeAbandonedTimeout" value="10" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="true" />
使用removeAbandoned来找出哪些长期占用的连接。根据自己的业务来决定超时时间。
例如你的业务里面有很多统计查询,有的确实是耗时长。你可与另外配置一个dataSource,另外一套配置来执行这些操作。但是我想基本上没有什么业务是需要客户等待1分钟的吧。
maxWait如果变成永不超时或者超时时间过长当然也有会有其他问题,会导致上层业务一直阻塞住。进而更进一步的消耗整个系统的性能。
例如:要查询一个结果,调用查询方法。dao层获取连接这一步一直阻塞住直到超时期间,业务层也会阻塞住。如果一直重复操作会生成一堆被阻塞的业务。阻塞这个问题主要是阻塞线程。线程被阻塞了要么是新建线程要么总的线程数量有上限。这样就导致了所有的业务都被停顿下来。
停顿的时间由maxWait决定,但是这本身是个很复杂的问题。如果你的系统到了这一步,会出现非常混乱的事情,任何一个操作都会报错,而且这些报错对你没有任何用处。主要原因是因为就算当前操作抛出了异常,实际上其他业务还是会获取连接,被阻塞住。获取连接这个不是出现问题的原因。
设置maxWait超时时间当然也是有好处的。当系统恢复正常的时候(那些长期占用连接的业务被干掉或者运行完毕)你的系统不会有一堆阻塞的业务。
我的推荐设置:2套数据源配置。主要是用来区分长时间会占用连接的业务和其他普通业务。如果系统没有那种会导致长时间执行的那么就只需要一套配置。
maxWait这个配置不会影响你的系统,也不会帮助你找出问题所在。
removeAbandonedTimeout这个配置用来检查哪些逻辑长期占用连接。这个才是导致问题的原因。
并且通过这个配置,可以干掉部分异常耗时的业务。来防止其他正常的业务被干扰。开发过程中可以把这个值尽量的设置小点,这样哪些不合理的业务能更快的暴露出来。
生产环境值可以设置大一些,主要的区别是如果业务量巨大,同样会导致一些连接问题出现。
我想到这些事情是在测试线程池数量对程序性能提升关系的时候出现的。
当我创建1万个线程并发执行某个sql的时候,连接池的最大数量是20。1万个线程并发执行完需要70秒
maxWait超时时间设置的是60秒。
我在想虽然确实是超时了60秒,但是毕竟系统的并发量这么高有延迟排队的现象也是非常正常的。现在就有一个考虑:在这么高的并发下连接池处理不过来是很正常的事情,不应该因为超时了10秒就向上抛异常。而且,如果程序没有问题的情况下,高并发条件下超时是情有可原的一件事情。如果直接抛弃操作会导致不可预知的事情发生。
所以maxWait不要轻易设置过短,而设置过长只会在系统本身出现问题或者高并发情况下干扰一些其他业务。
而对系统业务保持问题这个事情,应该由更上层系统来决定。例如上一篇说的构建更加稳定的系统多线程这个问题上。
而不是拿最底层数据层做文章。
相关推荐
38 案例实战:数据库无法连接故障的定位,Too many connections.pdf
39 案例实战:如何解决经典的Too many connections故障?背后原理是什么.pdf
行业-38 案例实战:数据库无法连接故障的定位,Too many connections.rar
行业-39 案例实战:如何解决经典的Too many connections故障?背后原理是什么.rar
从官方文档知道linux上面编译安装的mysql默认的连接为100个,这样对于网站的需求来说是远远不够的。 mysql官方告诉我们需要修改max_connections的值,那么我们怎么去修改呢?有两种方法 1、修改配置文件文件 修改/etc...
* 初始化连接池中数据库连接个数 * */ private void initConnections(){ for(int i=0;i;i++){ try { Connection conn=createConnection(); if(i==0){ DatabaseMetaData metaData=conn....
主要给大家介绍了关于Mysql错误Too many connections的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Mysql具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
关于mysql 提示too many connections问题解决办法mysql 提示too many connections是由于当前服务器上的mysql连接过多,一方面清当前已有连接,另一方面是改 max_connections (最大连接量)(就是开源节流思想),我...
2、减少数据库的并发连接数,即解决应用服务器过多导致的数据库 too many connections 问题 如果是为了解决问题1 则在workerman中数据库连接池不是最高效的方法,反而是自找麻烦的做法。由于PHP是单进程单线程的,...
解决方法是修改/etc/mysql/my.cnf,添加以下一行: set-variable = max_connections=500 或在启动命令中加上参数 max_connections=500 就是修改最大连接数,然后重启mysql.默认的连接数是100,太少了,所以容易出现如题...
ERROR 1040 (08004): Too many connections 解决办法,这也是centos7下修改mysql连接数的做法: 1)临时修改 MariaDB [(none)]> show variables like “max_connections”; +—————–+——-+ | Variable_name ...
Mysql 错误提示too many connections,最近遇到这个错误,经过上网查资料解决了,这里记录下,帮助有需要的朋友, 解决方法是修改/etc/mysql/my.cnf,添加以下一行: set-variable = max_connections=500 或在启动命令...
hibernate 数据库 连接池包文件,自己找了很多网站才找到的,传到CSDN方便需要的人使用
主要介绍了mysql too many open connections问题解决方法,其实是max_connections配置问题导致,它必须在[mysqld]下面才会生效,需要的朋友可以参考下
如果threads_connected == max_connections时,数据库系统就不能提供更多的连接数了,这时,如果程序还想新建连接线程,数据库系统就会拒绝,如果程序没做太多的错误处理,就会出现类似强坛的报错信息。
-- 连接池的别名 --> <alias>DBPool</alias> - <!-- proxool只能管理由自己产生的连接 --> <driver-url>jdbc:sqlserver://localhost:1433;dataBaseName=books</driver-url> - <!-- JDBC驱动程序 --> ...
JDBC整合c3p0数据库连接池 解决Too many connections错误 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。博客地址 ...