springboot事務的傳播行為和隔離級別
1. 在springboot中事務的傳播行為和隔離級別都是在TransactionDefinition這個接口中定義的
- 傳播行為定義了7種,分別用0-6來表示
int PROPAGATION_REQUIRED = 0;//如果當前上下文中的已經存在一個事務,就使用當前的事務;如果當前沒有事務就創建一個新的事務
int PROPAGATION_SUPPORTS = 1;//如果當前上下文中的已經存在一個事務,就使用當前的事務;如果當前沒有事務也不會開啟一個新事務,以非事務的方式執行
int PROPAGATION_MANDATORY = 2;//如果當前上下文中的已經存在一個事務,就使用當前的事務;如果當前沒有事務就拋出異常
int PROPAGATION_REQUIRES_NEW = 3;//如果當前上下文中的已經存在一個事務,就暫停該事務;創建一個新的事務開始執行。完成后恢復之前掛起的事務
int PROPAGATION_NOT_SUPPORTED = 4;//不支持事務,如果當前上下文中已經存在一個事務,就掛起事務;已非事務的方式執行
int PROPAGATION_NEVER = 5;//不支持事務,如果當前上下文中已經存在一個事務,就拋出異常
int PROPAGATION_NESTED = 6;//如果當前上下文中已經存在事務,就開啟一個嵌套的事務。簡單來說就是不管當前上下文中是否存在事務,本次都會創建一個事務
- 隔離級別有4種
int ISOLATION_DEFAULT = -1;//默認的隔離級別,使用數據庫當前的隔離級別。會是后面四種隔離級別的其中一種
int ISOLATION_READ_UNCOMMITTED = 1;//讀未提交;會有臟讀,不可重復讀,幻讀發生
int ISOLATION_READ_COMMITTED = 2; //讀已提交;會有不可重復讀,幻讀發生
int ISOLATION_REPEATABLE_READ = 4; //重復讀;會有幻讀出現
int ISOLATION_SERIALIZABLE = 8; //串行化
關於臟讀、不可重復讀、幻讀引用《深入淺出MySQL:數據庫開發、優化與管理維護(第2版》中的描述吧
臟讀(Dirty Reads):一個事務正在對一條記錄做修改,在這個事務完成並提交前,這條記錄的數據就處於不一致狀態;這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“臟”數據,並據此做進一步的處理,就會產生未提交的數據依賴關系。這種現象被形象地叫做“臟讀”。
不可重復讀(Non-Repeatable Reads):一個事務在讀取某些數據后的某個時間,再次讀取以前讀過的數據,卻發現其讀出的數據已經發生了改變或某些記錄已經被刪除了!這種現象就叫做“不可重復讀”。
幻讀(Phantom Reads):一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的新數據,這種現象就稱為“幻讀”。
關於各種隔離級別的描述可以參考我之前的文章隔離性與隔離級別
2. 關於事務屬性的默認值,對於springboot來說Transactional注解中定義的。我們可以在定義我們的事務的時候,根據實際需要修改這些屬性值
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
String[] label() default {};
Propagation propagation() default Propagation.REQUIRED;//默認的傳播行為
Isolation isolation() default Isolation.DEFAULT;//默認的隔離級別
int timeout() default -1;
String timeoutString() default "";
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}