2015-10-27 6 views
0

Я использую hibernate для сохранения данных, и я рассчитываю на инструкцию SELECT FOR UPDATE sql в качестве блокирующей системы, чтобы гарантировать, что только одна нить работает над моей задачей, но когда интернет-соединение прерывается , потоки блокируются в инструкции SELECT FOR UPDATE.SELECT FOR UPDATE блокировка

Моя теория: первый поток попадает в функции блокировки, выполняет оператор SQL, и ставит блокировку, и, прежде чем совершать какие-либо изменения в таблице базы данных, соединение прерывается нить не удается совершить, и разблокировать таблица, поэтому замок продолжает жить, а когда следующие потоки выполняют инструкцию SQL, они блокируются.

В коде сниппета сильфона, моя задача внутри блока в то время, я представлял его «...»

Фрагмент кода

while(lockIsOk()){ 
    ... 
} 

И lockIsOk() функция который обрабатывает замок.

Фрагмент кода

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); 
} 

Я могу предоставить файл журнала, если это необходимо.

Вопросы:

  • Является ли моя теория разумного?
  • Если это так, я могу решить эту проблему?
+0

Последний абзац [этого сообщения] (http://stackoverflow.com/a/27207636/3224483), похоже, описывает ту же проблему. К сожалению, это не дает решения. – Rainbolt

ответ

0

Ваша теория разумна и, вероятно, правильна.

Я бы сделал две вещи, чтобы исправить ситуацию.

  1. Если возможно, уменьшите время, в течение которого транзакция открыта для снижения уязвимости к поврежденным соединениям.

  2. Если ваша база данных позволяет установить время ожидания подключения к базе данных. Таким образом, база данных не будет долгое время работать на разрыве соединений. Обратите внимание, что это решение может потребовать изменения кода в вашем приложении, чтобы приложение могло либо открывать соединения, либо повторно подключаться по мере необходимости.