【问题标题】:SELECT FOR UPDATE lockingSELECT FOR UPDATE 锁定
【发布时间】:2015-10-27 16:28:28
【问题描述】:

我使用 hibernate 进行数据持久性,我指望 SELECT FOR UPDATE sql 语句作为锁定系统,以确保只有一个线程在处理我的任务,但是当互联网连接中断时,线程会在 SELECT FOR UPDATE 语句中被阻塞。

我的理论:第一个线程进入lock函数,执行SQL语句,加锁,在提交对数据库表的任何更改之前,连接被中断线程失败提交,并解锁表,因此锁一直存在,当下一个线程执行 SQL 语句时,它们被阻塞。

在下面的代码 sn-p 中,我的任务在 while 块内,我用“...”表示它

代码 sn-p

while(lockIsOk()){
    ...
}

而lockIsOk()就是处理锁的函数。

代码 sn-p

private boolean lockIsOk(){
    Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            SQLQuery request = DaoFactory.getCurrentSession().createSQLQuery("SELECT * FROM SYNCHRO_STATUS where id = 1 FOR UPDATE ");

            List<Object> resultList = request.addEntity("synchro_status", SynchroStatusModel.class).list();
            if(!resultList.isEmpty()) {
                SynchroStatusModel docSynchroStatusModel = (SynchroStatusModel) resultList.get(0);
                updateSync(docSynchroStatusModel);
                transaction.commit();
                return true;    
            } else {
                try {
                    Thread.sleep(configurator.getPropertyAsInt(SolrIndexerForStiProperties.SLEEP_TIME));
                } catch (InterruptedException e) {
                    // Restore the interrupted status
                    Thread.currentThread().interrupt();
                    ExploitLogger.error(ExploitError.EXECUTION_FAILED, SeverityError.MINOR, "Error while sleeping thread.", e, StiExploitId.ID_50114);
                }
            }
            // Commit the transaction
            transaction.commit();
        } catch (Exception e) {
            // Rollback the transaction
            ExploitLogger.error(ExploitError.UNATTEMPTED_ERROR, SeverityError.MAJOR, "Error while checking synchronization status table.", e, StiExploitId.ID_50115);
            HibernateTransactionHelper.rollbackTransaction(transaction);
        } finally {
            if (session.isOpen()) {
                session.close();
            }
        }
        return false;
}

private void updateSync(){
        SynchroStatusDao synchroStatusDao = DaoFactory.getSynchroStatusDao();
        String stiName = ManagementFactory.getRuntimeMXBean().getName();
        docSynchroStatusModel.setStiName(stiName);
        docSynchroStatusModel.setSynchroEnabled(1);
        docSynchroStatusModel.setLastActionDate(Calendar.getInstance().getTime());
        synchroStatusDao.update(docSynchroStatusModel);
}

如果需要,我可以提供日志文件。

问题:

  • 我的理论合理吗?
  • 如果是我该如何解决这个问题?

【问题讨论】:

  • this post 的最后一段似乎描述了同样的问题。不幸的是,它没有提供解决方案。

标签: java multithreading oracle hibernate


【解决方案1】:

你的理论是合理的,很可能是正确的。

我会做两件事来解决这个问题。

  1. 如果可能,请减少保持事务打开的时间,以减少连接中断的漏洞。

  2. 如果您的数据库允许,请设置数据库连接超时时间。这样,数据库就不会无限期地保持断开的连接。请注意,此解决方案可能需要在您的应用程序中更改代码,以便应用程序可以保持连接打开或根据需要重新连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2016-03-30
    • 1970-01-01
    相关资源
    最近更新 更多