个人随笔
目录
数据库连接超时案例分析(一)
2021-02-26 09:04:00

背景

有一个Java后台RocketMQ消费程序A,启动了20个线程来消费,消费逻辑为解析数据,插入数据库,然后登记一条新的消息给消费程序B消费。数据库记录为00,在新的消息
消费完后会改为02,今天突然之间查看数据库发现有一百多条记录一直是00的,然后怀疑是消费程序B消费失败了,但是看日志发现消息完全没有接收导消息。

原因

因为A在登记消息给B的时候,不仅仅是放一条消息到消息队列中,还新开启了一个事务,如果登记失败就会把失败消息记录在数据库中,等待消息补偿程序补发。所以如果是正常消费是没有问题的
但是如果一下子有几千条消息到消息队列A,然后A开启了20个线程来接受,那么在这期间内会占用20个数据库连接,并且每个线程在消息推送的时候会开启一个新的事物,所以可能会开启40个数据库线程。
然后我发现我的消费程序数据库连接池最大值才配置了20,所以有些线程就卡死在那里了,等默认的超时时间60s过后,新事务也还是没有或得到线程,就报超时了,所以消息也登记不了了。

解决方案

一般来说,若是程序每个线程一个事务也就占据一个数据库连接的话,将数据库连接的最大值设置为跟线程数相同或者比线程数大一点,为什么要大一点,因为防止程序里有自己没有留意的新开事务连接,比如
service上加了注解@Transaction(REQUIRES_NEW)那就会新起一个事务,暂用多一个数据库链接。比如我上面的程序已经明确知道一个线程会占用两个数据库链接的,所以我设置为线程数的两倍,这里用的是消费程序,线程池最大为50个消费线程,所以我把数据库连接最大设置为100后就解决了问题。

 45

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号