spring事務五大隔離級別、七大傳播行為
阿新 • • 發佈:2018-12-25
1.事務的定義:事務是指多個操作單元組成的合集,多個單元操作是整體不可分割的,要麼都操作不成功,要麼都成功。其必須遵循四個原則(ACID)。
- 原子性(Atomicity):即事務是不可分割的最小工作單元,事務內的操作要麼全做,要麼全不做;
- 一致性(Consistency):在事務執行前資料庫的資料處於正確的狀態,而事務執行完成後資料庫的資料還是應該處於正確的狀態,即資料完整性約束沒有被破壞;如銀行轉帳,A轉帳給B,必須保證A的錢一定轉給B,一定不會出現A的錢轉了但B沒收到,否則資料庫的資料就處於不一致(不正確)的狀態。
- 隔離性(Isolation):併發事務執行之間互不影響,在一個事務內部的操作對其他事務是不產生影響,這需要事務隔離級別來指定隔離性;
- 永續性(Durability):事務一旦執行成功,它對資料庫的資料的改變必須是永久的,不會因比如遇到系統故障或斷電造成資料不一致或丟失。
2.事務的型別
- 資料庫分為本地事務跟全域性事務
- 本地事務:普通事務,獨立一個數據庫,能保證在該資料庫上操作的ACID。
- 分散式事務:涉及兩個或多個數據庫源的事務,即跨越多臺同類或異類資料庫的事務(由每臺數據庫的本地事務組成的),分散式事務旨在保證這些本地事務的所有操作的ACID,使事務可以跨越多臺資料庫;
- Java事務型別分為JDBC事務跟JTA事務
- JDBC事務:即為上面說的資料庫事務中的本地事務,通過connection物件控制管理。
- JTA事務:JTA指Java事務API(Java Transaction API),是Java EE資料庫事務規範, JTA只提供了事務管理介面
3.Spring事務隔離級別:spring有五大隔離級別,其在TransactionDefinition介面中定義。看原始碼可知,其默isolation_default(底層資料庫預設級別),其他四個隔離級別跟資料庫隔離級別一致。
- ISOLATION_DEFAULT:用底層資料庫的預設隔離級別,資料庫管理員設定什麼就是什麼
- ISOLATION_READ_UNCOMMITTED(未提交讀):最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、髒讀、不可重複讀)
- ISOLATION_READ_COMMITTED(提交讀):一個事務提交後才能被其他事務讀取到(該隔離級別禁止其他事務讀取到未提交事務的資料、所以還是會造成幻讀、不可重複讀)、sql server預設級別
- ISOLATION_REPEATABLE_READ(可重複讀):可重複讀,保證多次讀取同一個資料時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的資料(該隔離基本可防止髒讀,不可重複讀(重點在修改),但會出現幻讀(重點在增加與刪除))(MySql預設級別,更改可通過set transaction isolation level 級別)
- ISOLATION_SERIALIZABLE(序列化):代價最高最可靠的隔離級別(該隔離級別能防止髒讀、不可重複讀、幻讀)
- 丟失更新:兩個事務同時更新一行資料,最後一個事務的更新會覆蓋掉第一個事務的更新,從而導致第一個事務更新的資料丟失,這是由於沒有加鎖造成的;
- 幻讀:同樣的事務操作過程中,不同時間段多次(不同事務)讀取同一資料,讀取到的內容不一致(一般是行數變多或變少)。
- 髒讀:一個事務讀取到另外一個未提及事務的內容,即為髒讀。
- 不可重複讀:同一事務中,多次讀取內容不一致(一般行數不變,而內容變了)。
幻讀與不可重複讀的區別:幻讀的重點在於插入與刪除,即第二次查詢會發現比第一次查詢資料變少或者變多了,以至於給人一種幻象一樣,而不可重複讀重點在於修改,即第二次查詢會發現查詢結果比第一次查詢結果不一致,即第一次結果已經不可重現了。
資料庫隔離級別越高,執行代價越高,併發執行能力越差,因此在實際專案開發使用時要綜合考慮,為了考慮併發效能一般使用提交讀隔離級別,它能避免丟失更新和髒讀,儘管不可重複讀和幻讀不能避免,但可以在可能出現的場合使用悲觀鎖或樂觀鎖來解決這些問題。
4.傳播行為:有七大傳播行為,也是在TransactionDefinition介面中定義。
- PROPAGATION_REQUIRED:支援當前事務,如當前沒有事務,則新建一個。
- PROPAGATION_SUPPORTS:支援當前事務,如當前沒有事務,則已非事務性執行(原始碼中提示有個注意點,看不太明白,留待後面考究)。
- PROPAGATION_MANDATORY:支援當前事務,如當前沒有事務,則丟擲異常(強制一定要在一個已經存在的事務中執行,業務方法不可獨自發起自己的事務)。
- PROPAGATION_REQUIRES_NEW:始終新建一個事務,如當前原來有事務,則把原事務掛起。
- PROPAGATION_NOT_SUPPORTED:不支援當前事務,始終已非事務性方式執行,如當前事務存在,掛起該事務。
- PROPAGATION_NEVER:不支援當前事務;如果當前事務存在,則引發異常。
- PROPAGATION_NESTED:如果當前事務存在,則在巢狀事務中執行,如果當前沒有事務,則執行與 PROPAGATION_REQUIRED 類似的操作(注意:當應用到JDBC時,只適用JDBC 3.0以上驅動)。
5.Spring事務支援
1.spring提供了很多內建事務管理器,支援不同資料來源。常見的有三大類
- DataSourceTransactionManager:org.springframework.jdbc.datasource包下,資料來源事務管理類,提供對單個javax.sql.DataSource資料來源的事務管理,只要用於JDBC,Mybatis框架事務管理。
- HibernateTransactionManager:org.springframework.orm.hibernate3包下,資料來源事務管理類,提供對單個org.hibernate.SessionFactory事務支援,用於整合Hibernate框架時的事務管理;注意:該事務管理器只支援Hibernate3+版本,且Spring3.0+版本只支援Hibernate 3.2+版本;
- JtaTransactionManager:位於org.springframework.transaction.jta包中,提供對分散式事務管理的支援,並將事務管理委託給Java EE應用伺服器,或者自定義一個本地JTA事務管理器,巢狀到應用程式中。
內建事務管理器都繼承了抽象類AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又繼承了介面PlatformTransactionManager
Spring框架支援事務管理的核心是事務管理器抽象,對於不同的資料訪問框架通過實現策略介面PlatformTransactionManager,從而能支援多鍾資料訪問框架的事務管理。
PlatformTransactionManager介面定義如下
- publicinterface PlatformTransactionManager {
- TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;//返回一個已經啟用的事務或建立一個新的事務(具體由TransactionDefinition引數定義的事務屬性決定),返回的TransactionStatus物件代表了當前事務的狀態,其中該方法丟擲TransactionException(未檢查異常)表示事務由於某種原因失敗。
- void commit(TransactionStatus status) throws TransactionException;//用於提交TransactionStatus引數代表的事務。
- void rollback(TransactionStatus status) throws TransactionException;//用於回滾TransactionStatus引數代表的事務。
- }
TransactionDefinition介面定義如下:
TransactionStatus介面定義如下:
- publicinterface TransactionDefinition {
- int getPropagationBehavior(); //返回定義的事務傳播行為
- int getIsolationLevel(); //返回事務隔離級別
- int getTimeout(); //返回定義的事務超時時間
- boolean isReadOnly(); //返回定義的事務是否是隻讀的
- String getName(); //返回事務名稱
- }
- publicinterface TransactionStatus extends SavepointManager {
- boolean isNewTransaction(); //返回當前事務是否是新的事務
- boolean hasSavepoint(); //返回當前事務是否有儲存點
- void setRollbackOnly(); //設定事務回滾
- boolean isRollbackOnly(); //設定當前事務是否應該回滾
- void flush(); //用於重新整理底層會話中的修改到資料庫,一般用於重新整理如Hibernate/JPA的會話,可能對如JDBC型別的事務無任何影響;
- boolean isCompleted(); //返回事務是否完成
- }
轉載自:http://blog.csdn.net/liaohaojian/article/details/68488150