Spring事務採坑 —— timeout
阿新 • • 發佈:2019-01-23
問題描述
在使用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裡面的