最近一直在捣鼓hbase的项目,之前写了一些代码从数据库加载数据到hbase,所有的代码都跑得好好地,然而今天尝试着换了一个数据库,就跑不通了。通过数据工具,可以发现连接没有问题,而且有部分逻辑很顺利通过了,然而有一些就是卡主了,通过jstack打印出来的信息可以找到这样的堆栈:
"runner{object-loader#292}-objecthandler" #323 prio=5 os_prio=0 tid=0x00002aaadc5ec800 nid=0x7f62 in object.wait() [0x0000000056ce4000]
java.lang.thread.state: waiting (on object monitor)
at java.lang.object.wait(native method)
at java.lang.object.wait(object.java:502)
at org.apache.commons.pool.impl.genericobjectpool.borrowobject(genericobjectpool.java:1104)
- locked <0x00000007736013e8> (a org.apache.commons.pool.impl.genericobjectpool$latch)
at org.apache.commons.dbcp.poolingdatasource.getconnection(poolingdatasource.java:106)
at org.apache.commons.dbcp.basicdatasource.getconnection(basicdatasource.java:1044)
at org.springframework.jdbc.datasource.datasourceutils.dogetconnection(datasourceutils.java:111)
at org.springframework.jdbc.datasource.datasourceutils.getconnection(datasourceutils.java:77)
所以开始我怀疑是连接的问题,从网上也找到了一个类型的现象,有人怀疑是dbpc的一个bug导致死锁:http://stackoverflow.com/questions/5714511/deadlock-issue-in-dbcp-deployed-on-tomcat,所以我升级了dbcp版本1.4,然而和这人一样的结果,升级dbcp版本并没有解决问题。简单的看dbcp的代码,都开始怀疑是不是因为没有spring jdbctemplate没有正确的把connection返回回去引起泄漏了,然而也有点感觉不太可能,因为这段代码在其他数据库都跑得好好地,但是我们的数据库版本都是一致的,然而其他配置上也被假设一致了(被忽略的一个重要的点)。
后来开始调配置,减少连接数,减少线程数,经过各种组合,发现当把db读的batch降到1的时候就可以work了,非常诡异的一个问题。从数据工具中查到,如果用batch,得到的sql是:
select
, from where iid in (@p0, @p1)如果是batch是1的话:
select , from
where iid in (@p0)这段sql语句是这么产生的:
datasource datasource = ....this.jdbc = new namedparameterjdbctemplate(datasource);...
mapsqlparametersource parameters = new mapsqlparametersource();
parameters.addvalue("params", paramsmap.keyset());
jdbc.query("select from where in (:params)";, parameters, new resultsetextractor() {
....
})
如果是一个batch的话,在jstack堆栈中可以看到它一直在等数据库的返回结果:
"runner{object-loader#16}-objecthandler" #47 prio=5 os_prio=0 tid=0x0000000006ddd800 nid=0x2694 runnable [0x0000000045434000]
java.lang.thread.state: runnable
at java.net.socketinputstream.socketread0(native method)
at java.net.socketinputstream.socketread(socketinputstream.java:116)
at java.net.socketinputstream.read(socketinputstream.java:170)
at java.net.socketinputstream.read(socketinputstream.java:141)
at com.sybase.jdbc3.timedio.rawdbio.reallyread(unknown source)
at com.sybase.jdbc3.timedio.dbio.doread(unknown source)
at com.sybase.jdbc3.timedio.instreammgr.a(unknown source)
at com.sybase.jdbc3.timedio.instreammgr.doread(unknown source)
at com.sybase.jdbc3.tds.tdsprotocolcontext.getchunk(unknown source)
这也解释了第一个堆栈一直停在borrowobject(getconnection)的阶段,因为之前所有的connection都在数据库堵住没有返回,所以这个线程再拿connection的时候超过了我设置的最大connection数,所以就等着拿不到connection。
在后来查了一下不同数据库的jdbc driver信息(sp_version):
jconnect (tm) for jdbc(tm)/7.07 esd #4 (build 26793)/p/ebf20302/jdk 1.6.0/jdbcmain/opt/thu jul 5 22:08:44 pdt 2012
jconnect (tm) for jdbc(tm)/1000/wed mar 11 05:01:24 2015 pdt
也就是说这种用法是因为旧的jdbc driver对namedparameterjdbctemplate不完善引起的,这个坑花了我一整天的时间。。。。
posted on 2015-11-11 18:46
dlevin 阅读(6288)
评论(0) 编辑 收藏 所属分类:
database