我有一个使用Oracle Driver进行数据库更新的简单程序。它是一个长期运行的SQL,它在SQLDeveloper模式下工作,但在Java程序中执行时挂起:
String sql = "UPDATE ...";
PreparedStatement ps = conn.prepareStatement(sql);
log.info(sql);
int affectedRows = ps.executeUpdate();
log.info("affected rows = " + affectedRows);
它记录sql行,但从不打印受影响的行行。
在数据库中,它显示执行(V$SESSION_LONGOPS
)已完成,剩余时间为0:
但奇怪的是,此会话仅存在于V$SESSION_LONGOPS
中,而不存在于V$SESSION
中。显然,这永远不会回到Java程序。在程序的运行系统中,ps -ef
提供了以下信息:
user 5889 5885 0 00:00 ? 00:00:11 /java/jdk1.6.0_25/bin/java -cp ...
它显示它开始在00.00(由Cron安排)运行并且仅执行了11秒(现在是10点,其中10小时已经过去)。似乎程序只是挂起/死亡,并且日志中没有给出异常(一个很大的尝试catch被日志异常包围)。
它永远不会到达程序的末尾,因为ps仍会打印这个并且没有即将到来的行的日志。
非常感谢指出方向的任何帮助。
答案 0 :(得分:4)
您可以查看下表,无论您的会话是否处于等待模式。
从dba_blockers中选择*; select * from dba_waiters;
确保您的会话不在上述查询中。
并检查您的对象是否未使用以下查询锁定
在此视图中从v $ locked_object中选择*,您可以获得锁定的对象ID,并且从dba_objects中您可以获得对象名称。
如果您在此找到任何会话,请先杀死或完成该会话。
答案 1 :(得分:1)
我遇到了同样的问题, 我对其他人一无所知,但我通过关闭SQLplus来解决了! 我不认为这可以解决问题,因为在sqlplus在控制台上运行时某些查询可以工作,但是我关闭了它,现在每个查询都可以工作并且没有挂起!
如果遇到我们的问题,您可能想尝试一下!
答案 2 :(得分:0)
要点:
您需要检查您的应用程序正在执行的操作。首先,您可以为要执行的语句设置Timeout。如果将其设置为20秒,则只需在客户端生成SQLTimeoutException。
使用try {} catch(SQLTimeoutException e){}可以打印通知。接下来你可以创建一个语句来检查你的sql是否已被执行。
典型的SQL Developer时序是什么?为什么需要这么长时间?你能给我们SQL和表结构吗?任何触发器,您更新视图或具体表吗?
接下来你可以做的是使用VisualVM并在SQL挂起时创建线程转储。将超时增加到60秒并创建ThreadDump。在那里,您可以看到线程正在做什么以及Oracle驱动程序是否等待套接字连接,而不是等待数据库响应。如果你看到不同的行为,你可能会猜到发生了什么。
另一个想法是在调试模式下运行您的应用程序。等待30秒(超时仍为60秒)并暂停应用程序并检查管理连接的线程。他在做什么以及为什么做。如果我没记错的话,你可以为oracle驱动程序获取源代码。如果不只是使用JD或类似的东西反编译代码或只是读取字节代码......