https://blog.csdn.net/yalishadaa/article/details/70261973
當同一個應用程式或者不同應用程式中的多個事務在同一個資料集上并發執行時,可能會出現許多意外的問題
并發事務所導緻的問題可以分為下面三種類型:
髒讀: 對于兩個事物T1,T2, T1 讀取了已經被T2更新但還沒有被送出的字段. 之後,若T2復原,T1讀取的内容就是臨時且無效的.
不可重複讀:對于兩個事物T1,T2, T1 讀取了一個字段,然後T2更新了該字段.之後,T1再次讀取同一個字段, 值就不同了.
幻讀:對于兩個事物T1,T2, T1 從一個表中讀取了一個字段,然後T2在該表中插入了一些新的行.之後,如果T1再次讀取同一個表,就會多出幾行.
從理論上來說, 事務應該彼此完全隔離,以避免并發事務所導緻的問題.然而,那樣會對性能産生極大的影響,因為事務必須按順序運作.
在實際開發中, 為了提升性能,事務會以較低的隔離級别運作.
事務的隔離級别可以通過隔離事務屬性指定
事務的隔離級别要得到底層資料庫引擎的支援,而不是應用程式或者架構的支援.
Oracle支援的2種事務隔離級别:READ_COMMITED, SERIALIZABLE
Mysql支援4中事務隔離級别.
事務的復原通過@Transactional 注解完成。
1.設定事務的隔離級别:
可以在 @Transactional的isolation屬性中設定隔離級别.
2.設定事務的復原屬性
預設情況下隻有未檢查異常(RuntimeException和Error類型的異常)會導緻事務復原.而受檢查異常不會.
事務的復原規則可以通過@Transactional注解的rollbackFor和noRollbackFor屬性來定義.
ex:
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
noRollbackFor = {UserAccountException.class},
)
UserAccountException
造成的異常都會被忽略。
rollbackFor: 遇到時必須進行復原
noRollbackFor: 一組異常類,遇到時必須不復原
3.設定逾時屬性
逾時事務屬性: 事務在強制復原之前可以保持多久.這樣可以防止長期運作的事務占用資源.
ex:
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
noRollbackFor = {UserAccountException.class},
timeout = 3)
如果在函數中有任務執行時間大于3秒,就算沒有異常抛出也會強制復原。
4.設定隻讀事務屬性
表示這個事務隻讀取資料但不更新資料,這樣可以幫助資料庫引擎優化事務.
ex:
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
noRollbackFor = {UserAccountException.class},
readOnly = false,timeout = 1)