`
aa87963014
  • 浏览: 154897 次
  • 性别: Icon_minigender_1
  • 来自: 布尼塔尼亚
社区版块
存档分类
最新评论

构建更健壮的系统:数据库连接池的问题Too many connections、timeout等等

阅读更多

首先,连接池是为了节省打开关闭数据库连接的一个手段,如果不用连接池,最大能获取连接的数量限制则是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不要轻易设置过短,而设置过长只会在系统本身出现问题或者高并发情况下干扰一些其他业务。

而对系统业务保持问题这个事情,应该由更上层系统来决定。例如上一篇说的构建更加稳定的系统多线程这个问题上。

而不是拿最底层数据层做文章。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    关于mysql提示too many connections问题解决方法.doc

    - **使用连接池**:使用连接池管理数据库连接,可以更有效地复用和回收连接。 - **监控和报警**:设置监控工具监控MySQL的连接数,当达到阈值时触发报警,以便及时处理。 - **定期审查和调整参数**:根据业务增长和...

    行业-39 案例实战:如何解决经典的Too many connections故障?背后原理是什么.rar

    "Too many connections"错误是数据库操作中常见的问题,尤其在高并发或者长时间运行的应用中。本案例实战将深入探讨这个问题的解决方案及其背后的原理。 首先,我们需要理解“Too many connections”错误的含义。这...

    Mysql错误:Too many connections的解决方法

    MySQL错误“Too many connections”是数据库用户在尝试建立新的连接时遇到的一个常见问题。这个错误表明MySQL服务器已经达到了其允许的最大并发连接数,通常默认设置为100个。当数据库连接未正确关闭,或者应用程序...

    mysql too many open connections问题解决方法

    MySQL中的"Too many open connections"错误是数据库管理员经常遇到的问题,它意味着当前的MySQL服务器已经达到了其允许的最大并发连接数。这个限制是由`max_connections`系统变量设定的,它定义了MySQL服务器可以...

    CI框架出现mysql数据库连接资源无法释放的解决方法

    然而,在使用过程中,可能会遇到一些问题,如数据库连接资源无法释放,导致“Too many connections”错误。本文将深入探讨这个问题的原因以及解决方案。 当CI框架在处理大量并发请求时,如果每个请求都创建一个新的...

    高并发系统MySQL遇到的挑战.pdf

    6. **连接池问题**:连接池管理不当可能导致“DB too many connections”或“get connection timeout”的问题。未使用线程池时,随着连接数增加,性能会急剧下降。需要合理设置连接池大小,并确保及时归还连接,避免...

    记一次MySQL数据库问题排查

    当系统频繁报告`Error: ER_CON_COUNT_ERROR: Too many connections`时,意味着数据库的并发连接数达到了上限。默认情况下,MySQL允许的最大并发连接数为100。然而,即使应用的并发任务量只有30~40,也出现了这样的...

    mysql_my.ini_优化

    如果经常收到“Too many connections”错误,应考虑增加此值,如从100增加到1024。 6. **record_buffer**:用于顺序扫描操作的每个线程缓冲区大小。如果执行很多顺序扫描查询,可以增大此值,例如从128K增加到16M。...

    mysql数据库my.cnf配置文件

    innodb_lock_wait_timeout = 120 # InnoDB事务在被回滚之前可以等待一个锁定的超时秒数。InnoDB在它自己的锁定表中自动检测事务死锁并且回滚事务。InnoDB用LOCK TABLES语句注意到锁定设置。默认值是50秒 bulk_insert...

    MySQL优化之连接优化

    如果`Max_used_connections`接近`max_connections`,可能需要考虑优化连接管理和数据库设计,例如使用连接池来复用连接,减少新连接的创建。 除了上述参数,还有一些其他连接相关的设置,如`wait_timeout`和`...

    mysql优化连接数防止访问量过高的方法

    MySQL数据库在面临高访问量时可能会遇到“ERROR 1040: Too many connections”的问题,这通常是由于并发连接数过多导致的。优化MySQL的连接数管理是解决此问题的关键,下面将详细介绍如何进行优化。 首先,理解...

    my.ini优化mysql数据库性能的十个参数(推荐)

    增大此值可以防止“too many connections”错误,但也要注意不要设置得过大,以免消耗过多系统资源。例如,将其设置为1024。 2. **record_buffer**:用于顺序扫描时每个线程的缓冲区大小。增加这个值有助于提高顺序...

    MySQL 配置优化(多个参数)

    过多的连接会导致内存开销增大,可能导致"ERROR 1040: Too many connections"错误。可以通过`show variables like 'max_connections';`来查看当前设置,并使用`show status like 'max_used_connections';`来监控实际...

    MySQL优化必须调整的10项配置

    但过高的max_connections可能导致服务器在处理大量并发事务时变得无响应,此时可以考虑使用连接池或进程池。 接下来是针对InnoDB存储引擎的优化配置: 4. **innodb_file_per_table**:设置为ON时,每个表的数据和...

Global site tag (gtag.js) - Google Analytics