Spring事務隔離級別簡介及實例解析
本文研究的主要是Spring事務隔離級別(solation level)介紹及例子,具體如下。
當兩個事務對同一個數(shù)據(jù)庫的記錄進行操作時,那么,他們之間的影響是怎么樣的呢?這就出現(xiàn)了事務隔離級別的概念。數(shù)據(jù)庫的隔離性與并發(fā)控制有很大關系。數(shù)據(jù)庫的隔離級別是數(shù)據(jù)庫的事務特性ACID的一部分。ACID,即原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)。Spring的事務隔離級別有四個:READ_UNCOMMITTED
、READ_COMMITTED
、REPEATABLE_READ
和SERIALIZABLE
。還有一個,是數(shù)據(jù)庫默認的隔離級別DEFAULT
,MySQL默認是REPEATABLE_READ
。
下面來具體看看。
READ_UNCOMMITTED
顧名思義,READ_UNCOMMITTED
意思是,一個事務可以讀取到另一個事務未提交的事務記錄。換句話說,a transaction can read the data that is still uncommitted by other transactions。這是Spring事務最弱的隔離級別。見下面的圖,事務A開啟,寫入一條記錄,這時候,事務B讀入數(shù)據(jù),讀到了這條記錄,但是,之后事務A回滾。因此,事務B讀到的數(shù)據(jù)不是有效的(the database is in an invalid state)。這種情況稱為臟讀(dirty read)。除了臟讀的問題,READ_UNCOMMITTED
還可能出現(xiàn)non-repeatable read
(不可重復讀)和phantom read
(幻讀)的問題。
READ_COMMITTED
READ_COMMITTED
隔離級別表明,一個事務只能讀取到已經(jīng)提交的記錄,不能讀取到未提交的記錄。換句話說,a transaction can only read the committed data, and it can't read the uncommitted data.因此,dirty read的情況不再發(fā)生,但可能會出現(xiàn)其他問題。見下圖。
在事務A兩次讀取的過程之間,事務B修改了那條記錄并進行提交。因此,事務A前后兩次讀取的記錄不一致。這個問題稱為non-repeatable read(不可重復讀)。(兩次讀取的記錄不一致,重復讀取就會發(fā)現(xiàn)問題。)
除了non-repeatable read的問題,READ_COMMITTED
還可能發(fā)生phantom read的問題。
REPEATABLE_READ
REPEATABLE_READ意思是,一個事務可以多次從數(shù)據(jù)庫讀取某條記錄,而且多次讀取的那條記錄都是一致的,相同的。這個隔離級別可以避免dirty read和non-repeatable read的問題,但可能發(fā)生phantom read的問題。如下圖。
事務A兩次從數(shù)據(jù)庫讀取一系列記錄,期間,事務B插入了某條記錄并提交。事務A第二次讀取時,會讀取到事務B剛剛插入的那條記錄。在事務期間,事務A兩次讀取的一系列記錄不一致,這個問題稱為phantom read。
SERIALIZABLE
SERIALIZABLE是Spring最強的隔離級別。事務執(zhí)行時,會在所有級別上加鎖,比如read和write時都會加鎖,仿佛事務是以串行的方式進行的,而不是一起發(fā)生的。這會防止dirty read、non-repeatable read和phantom read的出現(xiàn),但是,會帶來性能的下降。
DEFAULT
MySQL默認是REPEATABLE_READ
。
例子
下面,我們看一個例子。在數(shù)據(jù)庫mysql里開啟一個事務,不提交。然后,另一個事務讀取記錄。
剛開始,數(shù)據(jù)庫里的記錄,如圖
接下來,在數(shù)據(jù)庫mysql中開啟事務A,并插入一條記錄。
在service的業(yè)務類的事務屬性配置為READ_UNCOMMITTED
。
@Transactional(isolation=Isolation.READ_UNCOMMITTED) public class AccountService { private AccountDAO accountDAO; public AccountDAO getAccountDAO() { return accountDAO; } public void setAccountDAO(AccountDAO accountDAO) { this.accountDAO = accountDAO; } public void transfer(String from, String to, double money) { accountDAO.outMoney(from, money); accountDAO.inMoney(to, money); } public void readAllUser() { List<Account> accounts = accountDAO.getAllUser(); for (Account account : accounts) { System.out.println(account); } } }
運行下面的測試類
package com.chris.service; import static org.junit.Assert.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class ReadAllUserTest { @Autowired private AccountService accountService; @Test public void test() { accountService.readAllUser(); } }
結果如下:
可見,這個事務讀取到了未提交的數(shù)據(jù)。
這時候,將mysql中開啟的事務A回滾。
mysql> rollback;
再次運行程序,結果為
Account [name=Michael, money=1000.0]
Account [name=Jane, money=1000.0]
Account [name=Kate, money=1000.0]
總結
以上就是本文關于Spring事務隔離級別簡介及實例解析的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關文章
springboot(thymeleaf)中th:field和th:value的區(qū)別及說明
這篇文章主要介紹了springboot(thymeleaf)中th:field和th:value的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10Java關于BeabUtils.copyproperties的用法
這篇文章主要介紹了Java關于BeabUtils.copyproperties的用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析
這篇文章主要為大家介紹了mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08Java動態(tài)規(guī)劃之丑數(shù)問題實例講解
這篇文章主要介紹了Java動態(tài)規(guī)劃之丑數(shù)問題實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-09-09