BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #55172同步于 2017/2/24
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

10个并发线程产生15个数据库连接的不明状况,求分析原因和改善

echojessicaa
2017/2/24镜像同步12 回复
正在学习搭建1个简单好用的DAO结构, 用了spring jdbc + c3p0连接数据库mysql, code如下: public class ThreadRunner implements Runnable{ @Override public void run(){ try{ DataSource ds = baseDao.getDatasource(); Connection conn = baseDao.getDatasource().getConnection(); PooledDataSource pds = (PooledDataSource) ds; List<UserEntity> list = baseDao.getQueryBySql("select handle from UPM_USER"); for(UserEntity entity:list){ System.out.println("*****************************"); System.out.println("当前线程为:" + Thread.currentThread().getName() + "count:" + count.addAndGet(1)); // System.out.println(handle); System.out.println(entity.getHandle()); System.out.println("connection:" + conn.hashCode()); System.out.println("空闲的连接: " + pds.getNumIdleConnectionsDefaultUser()); System.out.println("使用中的连接: " + pds.getNumBusyConnectionsDefaultUser()); if(count.intValue() == 9){ System.out.println(count); } } }catch (Exception e){ e.printStackTrace(); System.out.println(e.toString()); } } } 调用和创建新thread的code如下: @Test public void getQueryList(){ for (int i=0; i<10; i++){ System.out.println(i); new Thread(thR).start(); } try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } 但是结果非常奇怪,出现了15个数据库连接
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
echojessicaa机器人#1 · 2017/2/24
结果输出如下: ***************************** 当前线程为:Thread-2count:1 cas1 connection:1152504480 空闲的连接: 0 使用中的连接: 5 ***************************** 当前线程为:Thread-9count:2 cas1 connection:808853315 空闲的连接: 0 使用中的连接: 6 ***************************** 当前线程为:Thread-8count:3 cas1 connection:977347968 空闲的连接: 0 使用中的连接: 8 ***************************** 当前线程为:Thread-11count:4 cas1 connection:234596579 空闲的连接: 0 使用中的连接: 10 ***************************** 当前线程为:Thread-3count:5 cas1 connection:1701105699 空闲的连接: 0 使用中的连接: 12 ***************************** 当前线程为:Thread-4count:6 cas1 connection:1453195003 空闲的连接: 0 使用中的连接: 14 ***************************** 当前线程为:Thread-10count:7 cas1 connection:1503938704 空闲的连接: 0 ***************************** 当前线程为:Thread-5count:8 cas1 使用中的连接: 11 ***************************** 当前线程为:Thread-6count:9 cas1 connection:2135417684 空闲的连接: 5 使用中的连接: 10 connection:2142116456 空闲的连接: 5 ***************************** 使用中的连接: 10 9 当前线程为:Thread-7count:10 cas1 connection:1218306324 空闲的连接: 5 使用中的连接: 10 并发线程的debug并不成功,跳进断点的同时其他thread就都跑完了。。。但是在数据库中查询会发现,的确存在和log相同的连接数: 运行结束后再查询数据库连接,那15个连接就不见了,说明并不是遗存连接 这个诡异的现象应该怎么查找原因呢~
ml3615556机器人#2 · 2017/2/24
你的连接池配置是不是没有指定保持最大连接数?默认是15(maxPoolSize参数) btw楼主你知道你写的程序什么意思么?开10个线程遍历一张只有一条数据的表。。没发现打出来的日志都是颠三倒四的么? 连接池工作得很正常,没毛病
echojessicaa机器人#3 · 2017/2/24
1.的确没有指定保持最大连接数,指定的话是不是每个线程都打印出15个connection了,但是这个和我想知道的是2码事唉。。。 程序运行前,connection idle+busy =0 运行时,10个线程分别调用同1个datasource查询10次,产生10+个连接(每次打印出来的连接数不一样) 我的疑问是,为啥不是产生10个连接而是多于10个。。 2.我写的这只是个test程序,遍历1个数据的表和日志颠三倒四有啥因果关系么。。难道并行的线程不就是颠三倒四的运行嘛。。。 这个test程序的现阶段目的,是希望DAO并发线程比较高的时候,能够依次处理,而不是丢连接或者connection数超出或者直接死掉 但是for循环还没设置成50或者100的时候,只是设置成10,connection数不等于10,是不是哪不太对呢~ 【 在 ml3615556 的大作中提到: 】 : 你的连接池配置是不是没有指定保持最大连接数?默认是15(maxPoolSize参数) : btw楼主你知道你写的程序什么意思么?开10个线程遍历一张只有一条数据的表。。没发现打出来的日志都是颠三倒四的么? : 连接池工作得很正常,没毛病
echojessicaa机器人#4 · 2017/2/24
自问自答,datasource中有个参数是每次创建connection个数,默认值是3,我改成1之后,10个线程就是创建10个connection了
ml3615556机器人#5 · 2017/2/24
产生多于十个连接可能是连接池自己初始化了多于10个,你设置不允许连接池有空闲conn试试? 至于为什么每次打出来连接池个数不一样,我猜,是因为连接池是默认lazy-init的,你一边用连接它一边给你初始化连接,要证实这个说法,你可以在sleep后面再开10个线程跑跑看。 并行的线程却是是颠三倒四的。。所以我怀疑你到底想用它干啥。。 Dao并发过高,那么就会等待连接池有空余连接吧(看配置),适当调大一些poolsize就好 看到最后一句话,我知道你的问题在哪了。。 new thread并不是连接池中的线程!!!你for多少次都是最大15个线程,空闲线程看负载多大 连接池中的线程是在datasource.queryXXX的时候拿conn的。。
echojessicaa机器人#6 · 2017/2/25
嗯呐好感动回答的真详细~问题已经解决了,通过修改acquireIncrement=1,最多只会产生10个连接。 看来我这种测试并发的方法太非主流了,求主流方法~ 以及您是否了解dao的设计思路应该怎么应对好并发呢?就是那种并发数远大于db连接池最大数的时候,dao应该做的 【 在 ml3615556 的大作中提到: 】 : 产生多于十个连接可能是连接池自己初始化了多于10个,你设置不允许连接池有空闲conn试试? : 至于为什么每次打出来连接池个数不一样,我猜,是因为连接池是默认lazy-init的,你一边用连接它一边给你初始化连接,要证实这个说法,你可以在sleep后面再开10个线程跑跑看。 : 并行的线程却是是颠三倒四的。。所以我怀疑你到底想用它干啥。。
ml3615556机器人#7 · 2017/2/25
那个acquirement修改了用处不大。。保持空闲的连接是很有必要的,所以恐怕你提出的解决问题实际上是解决一个不是问题的问题 随便说几个。。基本很多人都知道的,随便搜索一下会更全 优化你的sql,优化你的表结构与策略,这样来减小连接池数据库压力 加大你的连接池 引入集群来处理高并发 【 在 echojessicaa 的大作中提到: 】 : 嗯呐好感动回答的真详细~问题已经解决了,通过修改acquireIncrement=1,最多只会产生10个连接。 : 看来我这种测试并发的方法太非主流了,求主流方法~ : 以及您是否了解dao的设计思路应该怎么应对好并发呢?就是那种并发数远大于db连接池最大数的时候,dao应该做的
echojessicaa机器人#8 · 2017/2/25
嗯…你的建议是为了扩充了数据库处理能力,提高最大连接数量;而我的问题是连接数无论多大都会遇到超出的那个场景,那个场景应该遵循什么原则处理呢,只能抛出异常并操作失败?是否已经有比较成熟的解决原则和解决方案呢 【 在 ml3615556 的大作中提到: 】 : : 那个acquirement修改了用处不大。。保持空闲的连接是很有必要的,所以恐怕你提出的解决问题实际上是解决一个不是问题的问题 :
ml3615556机器人#9 · 2017/2/25
当连接数不够时,新来的数据库查询操作请求会被阻塞,直到有空闲连接出现。 如果服务器吞吐量不够,过多的阻塞会让服务器挂掉。 这种规模的并发量,我还没遇到过 估计让服务器消极的处理被阻塞的线程,控制阻塞队列长度,让无法处理的请求直接抛请求失败吧 我还是感觉你的并发量不可能有你描述的那么夸张,这种级别的并发量不是小公司遇得到的[em4] 【 在 echojessicaa 的大作中提到: 】 : 嗯…你的建议是为了扩充了数据库处理能力,提高最大连接数量;而我的问题是连接数无论多大都会遇到超出的那个场景,那个场景应该遵循什么原则处理呢,只能抛出异常并操作失败?是否已经有比较成熟的解决原则和解决方案呢 : :