Spring原始碼分析之事務
Spring提供一流的事務管理,分為宣告式事務和程式設計式事務。
1 Spring的事務
事務是一組任務組成的工作單元,執行的結果是要麼全部執行,要麼都不執行。
Spring事務的優點:
提供統一的程式設計模式 提供更簡單,更易用的事務管理 支援宣告事務 整合Spring對資料訪問的抽象
2 事務的ACID特性
原子性:
要麼事務的中的任務全部執行,要不都不執行
一致性:事務必須保證和資料庫的一致性,即資料庫的資料必須和現實的資料一致。
隔離性
不同的事務之間互不干擾
永續性:
如果事務執行成功,無論系統發生什麼情況,事務的執行結果都是永久的
3 事務的缺陷
髒讀取:
一個事務讀取另一個事務尚未提交的更新
不可重複的讀取:
一個事務前後兩次讀取資料都不一致,因為前後讀取期間有另一個事務改變了資料。不可重複讀讀到的是更改或者是刪除的資料
幻讀:
A事務讀取了B事務提交的新增資料,這時候A事務就會出現幻象讀的問題,幻象讀讀到的是新增的資料
4 資料庫鎖的機制
根據鎖定的物件不同,可以分為表鎖定和行鎖定,前者對整個表鎖定,或者對錶中的特定的行鎖定。從併發事務鎖定的關係上看,可以分為共享鎖定和獨佔鎖定。
行共享鎖定:一般可以通過select for update來隱式來獲取,也可以通過lock table in row share mode.行共享鎖並不防止對資料行進行更改的操作,但是可以防止其它會話獲取獨佔性資料表鎖定。
行獨佔鎖定:可以通過insert update delete來語句隱式來獲取,可以通過lock table in row exclusive mode.這個鎖定可以防止其它會話獲取一個共享鎖定,共享行獨佔鎖定或獨佔鎖定。
表共享鎖定:lock table in share mode
表共享行獨佔:lock table in share mode row exclusive mode.
表獨佔:lock table in Exclusive mode,防止其它會話的所有的鎖。
5 事務隔離級別
READ UNCOMMITED READ COMMITED REPEATABLE READ SERIALIZABLE
6 事務管理關鍵抽象
在事務管理管理SPI高層抽象層主要包括3個介面,分別是TransactionDefinition<------------PlaformTransactionManager------>TransactionStatus
TransactionDefinition用於標書事務的隔離級別,超時時間,是否為只讀事務和事務傳播等控制事務具體行為的事務屬性,這些事務屬性可以通過XML配置或註解描述提供,也可以通過手工程式設計的方式設定。
PlatformTransactionManager根據TransactionDefinition提供的事務屬性配置資訊,建立事務,並用TransactionStatus描述這個啟用事務的狀態。
TransactionDefinition:
TransactionDefinition定義了Spring相容性的事務屬性,這些屬性對事務管理控制的若干方面進行配置。
事務隔離:當前事務和其它事務的隔離的程度。在TranscationDefiniton介面中,定義了和java.sql.Connnection介面彙總同名的4個隔離級別:
ISOLATION_READ_UNCOMMITED,ISOLATION_READ_COMMITTED,ISOLATION_REPEATABLE_READ,ISOLATION_SERIALIZABLE,還有一個預設的
隔離級別:ISOLATION_DEFUALT
事務傳播:通常一個事務中執行的所有程式碼都會執行在同一事務上下文中,但是Spring也提供了幾個可選的事務傳播型別,如掛起當前的事務,建立一個新的
事務。
事務超時:
事務在超時前能執行多久,超過時間後,事務會被回滾。
只讀狀態:
只讀事務不修改任何資料,效能高。
TransactionStatus:
TransactionStatus代表一個事務的具體執行狀態,事務管理器可以通過該介面來獲取事務執行時期的狀態資訊,可以通過該介面間接地回滾事務。該介面繼承於SavepointManager.
SavepintManager介面擁有一下的方法:
Object createSavepoint()
建立一個儲存點物件,以便後面可以利用rollbackToSavePoint(Object savepoint)方法回滾大特定的儲存點上
void rollbackToSavepoint(Object savepoint)
將事務回滾到特定的儲存點上,被回滾的儲存單將自動釋放。
void releaseSavepoint(Object savepoint)
釋放一個儲存點,如果事務提交,所有的儲存點都對被釋放,不需要手工釋放。
TransactionStatus擴充套件了SavepointManager提供了一下的方法:
boolean hasSavepoint():判斷是否在內部建立了一個儲存點。
boolean isNewTransaction():潘丹是不是一個新的事務
boolean isCompleted():判斷事務是不是已經結束:已經提交或者回滾
boolean isRollbackOnly:當前事務是否已經被標誌位rollback_only
void setRollbackOnly:將當前的事務設定為rollback_only.
PlatformTransactionManager:
public interface PlatformTransactionManager {
/**
* Return a currently active transaction or create a new one, according to
* the specified propagation behavior.
* <p>Note that parameters like isolation level or timeout will only be applied
* to new transactions, and thus be ignored when participating in active ones.
* <p>Furthermore, not all transaction definition settings will be supported
* by every transaction manager: A proper transaction manager implementation
* should throw an exception when unsupported settings are encountered.
* <p>An exception to the above rule is the read-only flag, which should be
* ignored if no explicit read-only mode is supported. Essentially, the
* read-only flag is just a hint for potential optimization.
* @param definition TransactionDefinition instance (can be {@code null} for defaults),
* describing propagation behavior, isolation level, timeout etc.
* @return transaction status object representing the new or current transaction
* @throws TransactionException in case of lookup, creation, or system errors
* @throws IllegalTransactionStateException if the given transaction definition
* cannot be executed (for example, if a currently active transaction is in
* conflict with the specified propagation behavior)
* @see TransactionDefinition#getPropagationBehavior
* @see TransactionDefinition#getIsolationLevel
* @see TransactionDefinition#getTimeout
* @see TransactionDefinition#isReadOnly
*/
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
/**
* Commit the given transaction, with regard to its status. If the transaction
* has been marked rollback-only programmatically, perform a rollback.
* <p>If the transaction wasn't a new one, omit the commit for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after committing the new one.
* <p>Note that when the commit call completes, no matter if normally or
* throwing an exception, the transaction must be fully completed and
* cleaned up. No rollback call should be expected in such a case.
* <p>If this method throws an exception other than a TransactionException,
* then some before-commit error caused the commit attempt to fail. For
* example, an O/R Mapping tool might have tried to flush changes to the
* database right before commit, with the resulting DataAccessException
* causing the transaction to fail. The original exception will be
* propagated to the caller of this commit method in such a case.
* @param status object returned by the {@code getTransaction} method
* @throws UnexpectedRollbackException in case of an unexpected rollback
* that the transaction coordinator initiated
* @throws HeuristicCompletionException in case of a transaction failure
* caused by a heuristic decision on the side of the transaction coordinator
* @throws TransactionSystemException in case of commit or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
* @see TransactionStatus#setRollbackOnly
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* Perform a rollback of the given transaction.
* <p>If the transaction wasn't a new one, just set it rollback-only for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after rolling back the new one.
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
* The transaction will already have been completed and cleaned up when commit
* returns, even in case of a commit exception. Consequently, a rollback call
* after commit failure will lead to an IllegalTransactionStateException.
* @param status object returned by the {@code getTransaction} method
* @throws TransactionSystemException in case of rollback or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
*/
void rollback(TransactionStatus status) throws TransactionException;
}
5 程式設計式事務管理
TransactionTemplate和那些持久化模板類一樣,是執行緒安全的。
Object execute(TransactionCallback action) :在TransactionCallBack回撥介面中定義需要以事務方式組織的資料訪問邏輯。
public class Forum1Service {
private TransactionTemplate template;
public void addForum(){
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//需要在事務環境中執行的程式碼
}
});
}
}
6 使用XML宣告事務
7 使用註解宣告事務