【问题标题】:Oracle Select for update not working and sometimes hangs after whileOracle Select for update 不起作用,有时会在一段时间后挂起
【发布时间】:2015-07-29 12:35:42
【问题描述】:

我正在使用 java 进行 Oracle Select for Update,它可以按时工作,有时它会随会话挂起并且无法删除锁定的会话(必须手动终止会话) 这适用于大多数场景,但是当我将它部署在两台服务器(Web 服务)中并同时请求它们时,我不明白这是否是我的代码的问题, 我的代码

 public boolean checkJobStatus(long taskId)
{
    Connection con = null;
    PreparedStatement selectForUpdate = null;
    String lastJobStatus = null;
    boolean runNow = false;
    try
    {
        con = conPool.getConnection();
        con.setAutoCommit(false);
        selectForUpdate  = con.prepareStatement("SELECT LAST_JOB_STATUS FROM ADM_JOB WHERE TASK_ID = ? FOR UPDATE ");
        selectForUpdate.setLong(1, taskId);
        ResultSet resultSet = selectForUpdate.executeQuery();

        while(resultSet.next())
        {
            if (resultSet.getObject("LAST_JOB_STATUS") == null)
            {
                lastJobStatus = ScheduledJob.STATUS_FAILED;
            }
            else
            {
                lastJobStatus = resultSet.getString("LAST_JOB_STATUS");
            }
        }

     if(ScheduledJob.STATUS_RUNNING.equalsIgnoreCase(lastJobStatus) || ScheduledJob.STATUS_STARTED.equalsIgnoreCase(lastJobStatus))
     {
         runNow = false;
         // commit n update setting autocommit to true
         selectForUpdate = con.prepareStatement("UPDATE ADM_JOB SET LAST_JOB_STATUS =? WHERE TASK_ID = ?");
         selectForUpdate.setString(1, lastJobStatus);
         selectForUpdate.setLong(2, taskId);
         selectForUpdate.executeUpdate();
     }
     else
     {
         runNow =true;
         // commit n update setting autocommit to true
         selectForUpdate  = con.prepareStatement("UPDATE ADM_JOB SET LAST_JOB_STATUS =? WHERE TASK_ID = ?");
         selectForUpdate.setString(1, ScheduledJob.STATUS_STARTED);
         selectForUpdate.setLong(2, taskId);
         selectForUpdate.executeUpdate();

         con.commit();
         con.setAutoCommit(true);
     }

    } catch (SQLException e)
    {
        Logger.getLogger( "" ).log(Level.SEVERE, "Error in getting database connection", e);
        try
        {
            con.rollback();   // rolling back the row lock in case of a exception
        } catch (SQLException e1)
        {
            e1.printStackTrace();
        }
    }
    finally
    {
        DBUtility.close( selectForUpdate  );
        DBUtility.close( con );
    }


    return runNow;
}

【问题讨论】:

  • 通常“For Update”与游标一起使用,您在这里并没有真正这样做。记录锁在提交或回滚时释放,但您仅在运行启动状态时才提交。

标签: java database oracle transactions


【解决方案1】:

提交只发生在 else 分支中。如果这种情况没有发生,则事务不会关闭,因此第二个线程在 select for update 上永远挂起。

【讨论】:

  • 谢谢 Simimmo,它确实有效,认为更新会自行提交。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多