1. 程式人生 > >Spring事務採坑 —— timeout

Spring事務採坑 —— timeout

問題描述

在使用Spring 事務的時候,加上了timeout的限制,@Transactional(timeout = 10),發現事務不會因為超時回滾。

功能描述

所謂事務超時,就是指一個事務所允許執行的最長時間,如果超過該時間限制但事務還沒有完成,則自動回滾事務。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒。
預設設定為底層事務系統的超時值,如果底層資料庫事務系統沒有設定超時值,那麼就是none,沒有超時限制。

問題原因

Spring事務超時 = 事務開始時到最後一個Statement建立時時間 + 最後一個Statement的執行時超時時間(即其queryTimeout)。所以在在執行Statement之外的超時無法進行事務回滾。

解決辦法

舉個例子

@Transactional(timeout = 2, rollbackFor = Exception.class,isolation = Isolation.DEFAULT)
  public void createOrder(Integer userId, Integer goodsId, Integer amount) throws Exception {
      //減少庫存
      int result = goodsDao.updateGoodsStock(goodsId, amount);
      if (result != 1) {
          throw new Exception("建立訂單失敗");
      }
      //製造異常
//        int i = 1/0;
      //插入訂單
      orderDao.insert(userId, goodsId, amount);
      Thread.sleep(3000);
  }

在段程式碼中,如果把Thread.sleep(3000);放到最後,並不會回滾。所以開發的時候要特別注意。如果真的有特別重要的操作(在最後一個Statement之後),我現在的解決辦法是,
* 儘量在執行Statement的中間
* 在操作的最後再加一個無關的輕量Statement操作

原理

有時間在看,肯定是Spring AOP裡面的