Java程序毫无例外地挂起在executeUpdate上

时间:2015-02-20 15:15:11

标签: java database oracle

我有一个使用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:

enter image description here

但奇怪的是,此会话仅存在于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仍会打印这个并且没有即将到来的行的日志。

非常感谢指出方向的任何帮助。

3 个答案:

答案 0 :(得分:4)

您可以查看下表,无论您的会话是否处于等待模式。

从dba_blockers中选择*; select * from dba_waiters;

确保您的会话不在上述查询中。

并检查您的对象是否未使用以下查询锁定

在此视图中从v $ locked_object中选择*,您可以获得锁定的对象ID,并且从dba_objects中您可以获得对象名称。

如果您在此找到任何会话,请先杀死或完成该会话。

答案 1 :(得分:1)

我遇到了同样的问题, 我对其他人一无所知,但我通过关闭SQLplus来解决了! 我不认为这可以解决问题,因为在sqlplus在控制台上运行时某些查询可以工作,但是我关闭了它,现在每个查询都可以工作并且没有挂起!

如果遇到我们的问题,您可能想尝试一下!

答案 2 :(得分:0)

要点:

  1. 在SQL中设置超时
  2. 检查超时后,您的更新是否仍然有效并更改了任何行。
  3. 使用VisualVM和调试器检查驱动程序在客户端上执行的操作
  4. 您需要检查您的应用程序正在执行的操作。首先,您可以为要执行的语句设置Timeout。如果将其设置为20秒,则只需在客户端生成SQLTimeoutException。

    使用try {} catch(SQLTimeoutException e){}可以打印通知。接下来你可以创建一个语句来检查你的sql是否已被执行。

    典型的SQL Developer时序是什么?为什么需要这么长时间?你能给我们SQL和表结构吗?任何触发器,您更新视图或具体表吗?

    接下来你可以做的是使用VisualVM并在SQL挂起时创建线程转储。将超时增加到60秒并创建ThreadDump。在那里,您可以看到线程正在做什么以及Oracle驱动程序是否等待套接字连接,而不是等待数据库响应。如果你看到不同的行为,你可能会猜到发生了什么。

    另一个想法是在调试模式下运行您的应用程序。等待30秒(超时仍为60秒)并暂停应用程序并检查管理连接的线程。他在做什么以及为什么做。如果我没记错的话,你可以为oracle驱动程序获取源代码。如果不只是使用JD或类似的东西反编译代码或只是读取字节代码......