2015-10-27 109 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. 如果您的數據庫允許,請設置數據庫連接超時時間。這樣,數據庫不會無限期地保留斷開的連接。請注意,此解決方案可能需要更改應用程序中的代碼,以便應用程序可以根據需要保持連接打開或重新連接。