Java Spring-事務管理概述
2017-11-11 23:05:39
事務(Transaction):是邏輯上一組操作,要麽全都成功,要麽全都失敗。
一、事務的特性
- 原子性:事務不可分割
- 一致性:事務執行的前後,數據完整性保持一致
- 隔離性:一個事務執行的時候,不應該受到其他事務的打擾
- 持久性:一旦結束,數據就永久的保存到數據庫
如果不考慮隔離性:
臟讀 :一個事務讀到另一個事務未提交數據
當一個事務正在多次修改某個數據,而在這個事務中這多次的修改都還未提交,這時一個並發的事務來訪問該數據,就會造成兩個事務得到的數據不一致。例如:用戶A向用戶B 轉賬100元,對應SQL命令如下:
update account set money=money+100 where name=’B’; (此時A通知B) update account set money=money - 100 where name=’A’;
當只執行第一條SQL時,A通知B查看賬戶,B發現確實錢已到賬(此時即發生了臟讀),而之後無論第二條SQL是否執行,只要該事務不提交,則所有操作都將回 滾,那 麽當B以後再次查看賬戶時就會發現錢其實並沒有轉。
不可重復讀 :一個事務讀到另一個事務已經提交數據(update)導致一個事務多次查詢結果不一致
例如事務T1在讀取某一數據,而事務T2立馬修改了這個數據並且提交事務給數據庫,事務T1再次讀取該數據就得到了不同的結果,發送了不可重復讀。
不可重復讀和臟讀的區別是,臟讀是某一事務讀取了另一個事務未提交的臟數據,而不可重復讀則是讀取了前一事務提交的數據。
在某些情況下,不可重復讀並不是問題,比如我們多次查詢某個數據當然以最後查詢得到的結果為主。但在另一些情況下就有可能發生問題,例如對於同一個數據A 和B依次查詢就可能不同,A和B就可能打起來了
虛讀
幻讀是事務非獨立執行時發生的一種現象。例如事務T1對一個表中所有的行的某個數據項做了從“1”修改為“2”的操作,這時事務T2又對這個表中插入了一行數據項,而這個數據 項的數值還是為“1”並且提交給數據庫。而操作事務T1的用戶如果再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這 就是發生了幻讀。
二、MySQL數據庫提供的四種隔離級別
① Serializable (串行化):可避免臟讀、不可重復讀、幻讀的發生。
② Repeatable read (可重復讀)
③ Read committed (讀已提交):可避免臟讀的發生。
④ Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
以上四種隔離級別最高的是Serializable級別,最低的是Read uncommitted級別,當然級別越高,執行效率就越低。像Serializable這樣的級別,就是以鎖表的方式(類似於Java多線程中的鎖)使得其他的線程只能在鎖外等待,所以平時選用何種隔離級別應該根據實際情況。在MySQL數據庫中默認的隔離級別為Repeatable read (可重復讀)。
三、Spring提供事務管理API
- PlatformTransactionManager:平臺事務管理器.
commit(TransactionStatus status) getTransaction(TransactionDefinition definition) rollback(TransactionStatus status)
- TransactionDefinition:事務定義
ISOLation_XXX:事務隔離級別. PROPAGATION_XXX:事務的傳播行為.(不是JDBC中有的,為了解決實際開發問題.) TIMEOUT_DEFAULT:過期時間
- TransactionStatus:事務狀態
是否有保存點 是否一個新的事務 事務是否已經提交
關系:PlatformTransactionManager通過TransactionDefinition設置事務相關信息管理事務,管理事務過程中,產生一些事務狀態:狀態由TransactionStatus記錄。
四、事務管理三個API詳解
- PlatformTransactionManager:平臺事務管理器接口
Spring為不同的持久化框架提供了不同PlatformTransactionManager接口實現,前兩種最常用:
- org.springframework.jdbc.datasource.DataSourceTransactionManager : 使用Spring JDBC或iBatis 進行持久化數據時使用
- org.springframework.orm.hibernate3.HibernateTransactionManager : 使用Hibernate3.0版本進行持久化數據時使用
- org.springframework.orm.jpa.JpaTransactionManager : 使用JPA進行持久化時使用
- org.springframework.jdo.JdoTransactionManager : 當持久化機制是Jdo時使用
- org.springframework.transaction.jta.JtaTransactionManager : 使用一個JTA實現來管理事務,在一個事務跨越多個資源時必須使用
- TransactionDefinition:事務定義
* 隔離級別
- ISOLATION_DEFAULT:默認級別. Mysql repeatable_read,oracle read_commited
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
* 事務的傳播行為
不是JDBC事務管理,用來解決實際開發的問題。
傳播行為:解決業務層之間的調用的事務的關系,有七種傳播行為:
- PROPAGATION_REQUIRED :支持當前事務,如果不存在 就新建一個
* A,B 如果A有事務,B使用A的事務,如果A沒有事務,B就開啟一個新的事務.(A,B是在一個事務中。)
- PROPAGATION_SUPPORTS :支持當前事務,如果不存在,就不使用事務
* A,B 如果A有事務,B使用A的事務,如果A沒有事務,B就不使用事務.
- PROPAGATION_MANDATORY :支持當前事務,如果不存在,拋出異常
* A,B 如果A有事務,B使用A的事務,如果A沒有事務,拋出異常.
- PROPAGATION_REQUIRES_NEW :如果有事務存在,掛起當前事務,創建一個新的事務
* A,B 如果A有事務,B將A的事務掛起,重新創建一個新的事務.(A,B不在一個事務中.事務互不影響.)
- PROPAGATION_NOT_SUPPORTED :以非事務方式運行,如果有事務存在,掛起當前事務
* A,B 非事務的方式運行,A有事務,就會掛起當前的事務.
- PROPAGATION_NEVER :以非事務方式運行,如果有事務存在,拋出異常
- PROPAGATION_NESTED :如果當前事務存在,則嵌套事務執行
* 基於 SavePoint 技術.
* A,B A有事務,A執行之後,將A事務執行之後的內容保存到SavePoint.B事務有異常的話,用戶需要自己
設置事務提交還是回滾.
常用:
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
PROPAGATION_NESTED
Java Spring-事務管理概述