最近一个项目里面出现了一个比较诡异的问题:页面上有个功能不定期的报错 Communication error
碰到这种问题我们第一时间怀疑是网络问题,但是客户端工具可以正常连接数据库,页面上其他功能也没报错,所以可以排除网络问题。
为方便跟踪问题,我们可以开启 DM JDBC 的日志,获取更详细的信息
[ERROR - 2020-04-26 11:36:58] tid:262{ conn-33, pstmt-3706 } execute();
dm.jdbc.driver.DMException: Communication error
at dm.jdbc.driver.DBError.throwException(DBError.java:683)
at dm.jdbc.c.a.a(DBAccess.java:897)
at dm.jdbc.c.a.a(DBAccess.java:365)
at dm.jdbc.driver.DmdbPreparedStatement.executeInner(DmdbPreparedStatement.java:212)
at dm.jdbc.driver.DmdbPreparedStatement.do_execute(DmdbPreparedStatement.java:301)
at dm.jdbc.filter.FilterChain.PreparedStatement_execute(FilterChain.java:5498)
at dm.jdbc.filter.log.LogFilter.PreparedStatement_execute(LogFilter.java:8061)
at dm.jdbc.filter.FilterChain.PreparedStatement_execute(FilterChain.java:5494)
at dm.jdbc.driver.DmdbPreparedStatement.execute(DmdbPreparedStatement.java:1625)
通过语句句柄:pstmt-3706 可以找到报错的 SQL 语句和它的参数。
然后我们根据语句和参数自己写了一个小程序进行验证,发现并不会报错,SQL 语句单独在客户端中执行也不会报错,这就有点令人费解了。
接下来我们查一查数据库的 SQL 日志,看看是什么情况。
从 SQL 日志可以看出报错是-6007:连接异常,并且是在执行几秒钟之后,这种情况很可能是 SQL 超时然后断开了连接。
造成这种情况的有两个可能原因:
经过排查,我们发现数据库并未对用户设置资源限制,仔细分析 JDBC 日志后发现应用调用了 JDBC 的接口设置了连接限制。
--JDBC日志中有很多类似的信息,说明应用针对不同SQL设置了不同的超时时间
setNetworkTimeout(ThreadPoolExecutor, Integer); [PARAMS]: java.util.concurrent.ThreadPoolExecutor@49e62b17[Running, pool size = 1, active threads = 0, queued tasks = 0, completed tasks = 111], 5000;
setNetworkTimeout(ThreadPoolExecutor, Integer); [PARAMS]: java.util.concurrent.ThreadPoolExecutor@49e62b17[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 110], 15000;
可是询问客户的开发人员,他们说没有对 SQL 设置超时时间,只在连接池中做了配置,如下:
显然这个设置和我们分析到的现象不太一致,JDBC 日志里面可以看到应用多次调用接口设置了超时时间,并且每次时间不太一致,应该另有原因,这时我们给客户的开发人员提供了参考文章,主要内容为 JDBC 中还可以用什么方式设置超时,很快客户开发人员就从代码里面找到了超时的设置。
针对这个原因,有两个解决方案:
治标的方法:修改这个超时的配置,将时间改大一点。
治本的方法:分析一下这个 SQL 语句,将其进一步优化。
本次问题处理的体会:你看到的不一定是真的,你听到的也不一定是真的,要透过现象看本质!
文章
阅读量
获赞