一、事務的重要性,相信在實際開發過程中,都有很深的了解了。但是存在一個問題我們經常在開發的時候一般情況下都是用的注解的方式來進行事務的控制,說白了基於spring的7種事務控制方式來進行事務的之間的協調。
二、spring的7中事務傳播行為
Propagation.REQUIRED | 代表當前方法支持當前的事務,且與調用者處於同一事務上下文中,回滾統一回滾(如果當前方法是被其他方法調用的時候,且調用者本身即有事務),如果沒有事務,則自己新建事務, |
Propagation.SUPPORTS | 代表當前方法支持當前的事務,且與調用者處於同一事務上下文中,回滾統一回滾(如果當前方法是被其他方法調用的時候,且調用者本身即有事務),如果沒有事務,則該方法在非事務的上下文中執行 |
Propagation.MANDATORY | 代表當前方法支持當前的事務,且與調用者處於同一事務上下文中,回滾統一回滾(如果當前方法是被其他方法調用的時候,且調用者本身即有事務),如果沒有事務,則拋出異常 |
Propagation.REQUIRES_NEW | 創建一個新的事務上下文,如果當前方法的調用者已經有了事務,則掛起調用者的事務,這兩個事務不處於同一上下文,如果各自發生異常,各自回滾 |
Propagation.NOT_SUPPORTED | 該方法以非事務的狀態執行,如果調用該方法的調用者有事務則先掛起調用者的事務 |
Propagation.NEVER | 該方法以非事務的狀態執行,如果調用者存在事務,則拋出異常 |
Propagation.NESTED | 如果當前上下文中存在事務,則以嵌套事務執行該方法,也就說,這部分方法是外部方法的一部分,調用者回滾,則該方法回滾,但如果該方法自己發生異常,則自己回滾,不會影響外部事務,如果不存在事務,則與PROPAGATION_REQUIRED一樣 |
三、數據庫四大特性和MySQL事務的隔離級別
1)四大特性
a、原子性(Atomicity)
原子性是指事務包含的所有操作要么全部成功,要么全部失敗回滾。
b、 一致性(Consistency)
一致性是指事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之后都必須處於一致性狀態。
c、隔離性(Isolation)
隔離性是當多個用戶並發訪問數據庫時,比如操作同一張表時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作所干擾,多個並發事務之間要相互隔離。
d、 持久性(Durability)
持久性是指一個事務一旦被提交了,那么對數據庫中的數據的改變就是永久性的,即便是在數據庫系統遇到故障的情況下也不會丟失提交事務的操作。
2)隔離級別
a、臟讀是指在一個事務處理過程里讀取了另一個未提交的事務中的數據。(讀取未提交的數據)
b、不可重復讀是指在對於數據庫中的某個數據,一個事務范圍內多次查詢卻返回了不同的數據值,這是由於在查詢間隔,被另一個事務修改並提交了。(邊讀邊寫)
c、幻讀指兩個事務同時發生,兩個事務修改數據,讀到的數據不是自己開始修改的數據。幻讀和不可重復讀都是讀取了另一條已經提交的事務(這點就臟讀不同),所不同的是不可重復讀查詢的都是同一個數據項,而幻讀針對的是一批數據整體。(同時寫,同時讀)
3)數據庫事務級別,默認使用Repeatable read級別,列表級別從下往上級別越低。查看級別
select @@tx_isolation;
四、扯遠了,寫上面spring事務和數據庫事務隔離級別,主要的目的就是了解事務之間存在的傳遞關系,這樣在控制的時候,spring會通過事務與事務之間關系,來達到回滾或者提交的效果。
五、如果在沒有辦法使用注解的時候(比如多線程等),就要使用手動的方式來做事務管理了,這也就是編程式的事務管理。
1)首先加入注解,這就是spring的jdbc框架中提供的事務管理方式
@Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private TransactionDefinition transactionDefinition;
2)看一下源碼(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)
@Bean @ConditionalOnMissingBean({PlatformTransactionManager.class}) public DataSourceTransactionManager transactionManager(DataSourceProperties properties) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource); if (this.transactionManagerCustomizers != null) { this.transactionManagerCustomizers.customize(transactionManager); } return transactionManager; }
備注:有興趣可以了解一下DataSourceTransactionManager的寫法和原理。
@Bean @ConditionalOnMissingBean public TransactionTemplate transactionTemplate() { return new TransactionTemplate(this.transactionManager); }
注意,這里的所有事務傳播方式包括處理,都需要自己手動去處理。
3)編寫方式
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
platformTransactionManager.commit(transactionStatus);
platformTransactionManager.rollback(transactionStatus);
說明:這里開發事務過后,返回一個事務狀態,這個狀態記錄了東西,用來控制事務的管理,當然,多個事務之間的控制需要人為控制。
4)編程式的事務控制經量少用,因為控制程度上面來說spring的方式還是來的更加不錯,編程式的方式,更多用於在需要事務的時候,沒有辦法加入事務,才采取手動控制事務的方式。