我们的应用程序遇到了一个不寻常的问题,在过去的一个月里,我们的应用程序达到了不可恢复的状态,在应用程序重启后恢复了。
背景:我们的应用程序进行数据库查询以获取一些信息,并且此数据库托管在单独的节点上。
有问题的情况:当分析线程转储时,我们看到所有线程都处于可运行状态,从数据库中获取数据,但即使在20分钟后它也没有完成。
按预期发布应用程序重启所有线程都已恢复。 CPU使用率也很正常。
以下是线程转储
ThreadPool:2:47“prio = 3 tid = 0x0000000007334000 nid = 0x5f runnable [0xfffffd7fe9f54000] java.lang.Thread.State:RUNNABLE at oracle.jdbc.driver.T2CStatement.t2cParseExecuteDescribe(Native方法) 在 oracle.jdbc.driver.T2CPreparedStatement.executeForDescribe(T2CPreparedStatement.java:518) 在 oracle.jdbc.driver.T2CPreparedStatement.executeForRows(T2CPreparedStatement.java:764) 在ora
All threads in the same state.
问题:
答案 0 :(得分:1)
它可能正在等待来自数据库服务器的网络数据。 JVM将I / O上等待(阻塞)的Java线程描述为处于RUNNABLE状态,即使从程序的角度来看它们也被阻止了。
答案 1 :(得分:1)
正如其他人已经提到的那样,本机方法总是处于可运行状态,因为JVM并不知道/关心它们。
默认情况下,客户端的Oracle驱动程序没有套接字超时。这意味着如果您遇到网络问题,客户端的低级套接字可能会卡住"永远存在,导致maxxed out连接池。您还可以检查到Oracle服务器的网络流量,看它是否甚至传输数据。
使用瘦客户端时,您可以设置oracle.jdbc.ReadTimeout
,但我不知道如何为您使用的胖(oci)客户端执行此操作,我不熟悉它。
怎么办?研究如何为thick ojdbc驱动程序指定读取超时,并观察与连接超时相关的异常,这将清楚地表明网络问题。如果您可以更改源,则可以在捕获与超时相关的SQLExceptions时包装调用并重试会话。
要快速解决问题,请手动终止Oracle服务器上的连接。
值得检查会话争用,可能是查询会阻止这些会话。如果找到一个,您将看到哪个数据库对象导致问题。
答案 2 :(得分:0)
本机方法
该方法可以在IO上阻止,任何其他事件等待或只是长cpu密集的任务...或无限循环。 你可以自己挑选。
在这种情况下如何恢复?
从oracle中删除连接。
答案 3 :(得分:0)
系统或JVM是否被绞死? 如果可配置,如果可能,减少线程/并行连接的数量。
线程在等待IO时只会浪费CPU周期。 是的,您的CPU很快就被等待DB响应的线程忙碌了。
答案 4 :(得分:0)
您的代码是否手动处理交易?如果那时,也许某些代码在更改数据后没有提交()。或者有人直接通过PLSQL或其他东西运行数据修改查询但没有提交,这导致所有读取操作都被挂起。
当您遇到“挂起”并且数据库已从状态恢复时,您是否检查了数据是否已回滚?询问此问题,因为您说“应用程序重启后恢复了”。当JDBC驱动程序更改了东西但没有提交,并且发生超时时,就会发生这种情况......数据库操作将被回滚。 (虽然可以根据配置而有所不同)