先來(lái)講講臟讀 不可重復(fù)讀 和 幻讀。
要求事務(wù)所包含的全部操作是一個(gè)不可分割的整體,如果有一步發(fā)生異常,則全部不提交。
A給B轉(zhuǎn)錢(qián),A減和B增這兩個(gè)操作必須保持一致。
事務(wù)會(huì)將一部分?jǐn)?shù)據(jù)與其他事務(wù)隔離,防止臟讀等。
事務(wù)的結(jié)果被寫(xiě)到持久化存儲(chǔ)器中。
隔離級(jí)別越高,則性能相對(duì)越低,反之亦然。
最低的隔離級(jí)別,跟你直譯的意思一樣:可以讀取其它事務(wù)未完成的結(jié)果。(臟讀)
很明顯,臟讀 不可重復(fù)讀 和 幻讀這三個(gè)問(wèn)題它都有。
大部分?jǐn)?shù)據(jù)庫(kù)采用的默認(rèn)隔離級(jí)別,比上一個(gè)隔離級(jí)別多了限定:在該事務(wù)完成后,才能讀取該事務(wù)的數(shù)據(jù)更新后的結(jié)果。
它可以避免臟讀,但是也有不可重復(fù)讀取和幻讀的問(wèn)題。
可以保證在整個(gè)事務(wù)的過(guò)程中,對(duì)同一筆數(shù)據(jù)的讀取結(jié)果是相同的,不管其他事務(wù)是否同時(shí)在對(duì)同一筆數(shù)據(jù)進(jìn)行更新,也不管其他事務(wù)對(duì)同一筆數(shù) 據(jù)的更新提交與否。
Repeatable Read隔離級(jí)別避免了臟讀和不可重復(fù)讀取的問(wèn)題,但無(wú)法避免幻讀。
最為嚴(yán)格的隔離級(jí)別,所有的事務(wù)操作都必須依次順序執(zhí)行,可以避免其他隔離級(jí)別遇到的所有問(wèn)題,是最為安全的隔離級(jí)別, 但同時(shí)也是性能最差的隔離級(jí)別。
通常情況下,我們會(huì)使用其他隔離級(jí)別加上相應(yīng)的并發(fā)鎖的機(jī)制來(lái)控制對(duì)數(shù)據(jù)的訪問(wèn),這樣既保證 了系統(tǒng)性能不會(huì)損失太大,也能夠一定程度上保證數(shù)據(jù)的一致性。
事務(wù)傳播行為 | 含義 |
PROPAGATION_REQUIRED(默認(rèn)) | 必須在事務(wù)中執(zhí)行,如果沒(méi)有,就新new一個(gè)新事務(wù) |
PROPAGATION_SUPPORTS | 誰(shuí)調(diào)用我我就在誰(shuí)的事務(wù)中執(zhí)行,沒(méi)有的話就沒(méi)有 |
PROPAGATION_MANDATORY | 必須要有事務(wù),沒(méi)有就報(bào)錯(cuò) |
PROPAGATION_REQUIRED_NEW | 不管調(diào)用我的方法有沒(méi)有事務(wù),我都new一個(gè)事務(wù) |
PROPAGATION_NOT_SUPPORTED | 調(diào)用我的方法有事務(wù),但我不在事務(wù)中執(zhí)行 |
PROPAGATION_NEVER | 不允許在事務(wù)中運(yùn)行,有事務(wù)則報(bào)錯(cuò) |
PROPAGATION_NESTED | 有事務(wù)則嵌套,沒(méi)有則new一個(gè)新事務(wù) |
我們都知道,JDBC給我們提供了事務(wù)。
try{ con.setAutoCommit(false);//開(kāi)啟事務(wù) ...... con.commit();//try的最后提交事務(wù) } catch() { con.rollback();//回滾事務(wù)}
獲取事務(wù)隔離級(jí)別。
Connection.getTransactionIsolation()
設(shè)置事務(wù)隔離級(jí)別。
con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
Spring并不會(huì)直接管理事務(wù),而是提供了事務(wù)管理器,將事務(wù)管理的職責(zé)委托給JPA JDBC JTA DataSourceTransaction JMSTransactionManager 等框架提供的事務(wù)來(lái)實(shí)現(xiàn)。
那么,Spring提供的事務(wù)管理器是什么呢?
是
PlatformTransactionManager.java接口:
Spring提供的事務(wù)管理器。不同的事務(wù)遵循該事務(wù)管理器的API,便能很輕松的交給Spring管理。
public interface PlatformTransactionManager { // 通過(guò)Transation定義 獲取Transation TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; // 提交事務(wù) void commit(TransactionStatus var1) throws TransactionException; // 回滾事務(wù) void rollback(TransactionStatus var1) throws TransactionException;}
可以看到它里面引用到了TransactionDefinition和TransactionStatus。
它里面包含了事務(wù)的定義。
public interface TransactionDefinition { // 傳播機(jī)制 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; // 隔離級(jí)別 int ISOLATION_DEFAULT = -1; int ISOLATION_READ_UNCOMMITTED = 1; int ISOLATION_READ_COMMITTED = 2; int ISOLATION_REPEATABLE_READ = 4; int ISOLATION_SERIALIZABLE = 8; int TIMEOUT_DEFAULT = -1; int getPropagationBehavior(); // 獲取隔離級(jí)別 int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); @Nullable String getName();}
事務(wù)的狀態(tài)。
public interface TransactionStatus extends SavepointManager, Flushable { boolean isNewTransaction(); boolean hasSavepoint(); void setRollbackOnly(); boolean isRollbackOnly(); void flush(); boolean isCompleted();}
@Autowiredprivate PlatformTransactionManager transactionManager;public void testTX(){ DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); TransactionStatus status = transactionManager.getTransaction(definition); try { // 業(yè)務(wù)邏輯 // ... // 提交事務(wù) transactionManager.commit(status); }catch (Exception e){ // 發(fā)生異常,事務(wù)回滾 transactionManager.rollback(status); }}
@Transactionalvoid testTX2(){ // 業(yè)務(wù)邏輯 ...}
這不是玄學(xué),它的底層是依靠AOP動(dòng)態(tài)代理實(shí)現(xiàn),其實(shí)重新渲染出的代碼和第一個(gè)使用方式類(lèi)似,不過(guò)大大減少了開(kāi)發(fā)復(fù)雜度。
@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Transactional { //指定使用的事務(wù)管理器 @AliasFor("transactionManager") String value() default ""; @AliasFor("value") String transactionManager() default ""; // 可選的事務(wù)傳播行為設(shè)置 Propagation propagation() default Propagation.REQUIRED; // 可選的事務(wù)隔離級(jí)別設(shè)置 Isolation isolation() default Isolation.DEFAULT; // 事務(wù)超時(shí)時(shí)間設(shè)置 int timeout() default -1; // 讀寫(xiě)或只讀事務(wù),默認(rèn)讀寫(xiě) boolean readOnly() default false; // 導(dǎo)致事務(wù)回滾的異常類(lèi)數(shù)組 Class<? extends Throwable>[] rollbackFor() default {}; // 導(dǎo)致事務(wù)回滾的異常類(lèi)名字?jǐn)?shù)組 String[] rollbackForClassName() default {}; // 不會(huì)導(dǎo)致事務(wù)回滾的異常類(lèi)數(shù)組 Class<? extends Throwable>[] noRollbackFor() default {}; // 不會(huì)導(dǎo)致事務(wù)回滾的異常類(lèi)名字?jǐn)?shù)組 String[] noRollbackForClassName() default {};}
非入門(mén)選手下面的demo可能會(huì)引起你的不適(浪費(fèi)時(shí)間)。
假設(shè)我要完成一個(gè)功能,當(dāng)刪除用戶的時(shí)候,將與該用戶有關(guān)的所有數(shù)據(jù)行都刪除。
public void delUser(Integer userId) { // 刪除和用戶相關(guān)的信息 otherRepository.deleteByUserId(userId); // 刪除用戶 userRepository.deleteById(userId);}
這樣的寫(xiě)法一般來(lái)講,會(huì)成功的完成任務(wù)。但是如果這樣一段代碼:
public void delUser(Integer userId) { // 刪除和用戶相關(guān)的信息 otherRepository.deleteByUserId(); if (true) { throw new RuntimeException("xxx"); } // 刪除用戶 userRepository.deleteById(userId);}
結(jié)果會(huì)是:deleteByUserId()執(zhí)行成功,deleteById()執(zhí)行失敗,不滿足數(shù)據(jù)的一致性。
所以我們需要事務(wù)來(lái)限制:要么全部執(zhí)行,要么全部不執(zhí)行(方法中有異常就自動(dòng)回滾)。那怎么實(shí)現(xiàn)呢,只需要在方法上加一個(gè)注解:@Transactional
@Transactionalpublic void delUser(Integer userId) { // 刪除和用戶相關(guān)的信息 otherRepository.deleteByUserId(); if (true) { throw new RuntimeException("xxx"); } // 刪除用戶 userRepository.deleteById(userId);}
比如我有個(gè)需求(接著上次的強(qiáng)票系統(tǒng)II),要求信息不能丟失,要用到RabbitMQ的事務(wù)管理,那怎么去加載到Spring的事務(wù)管理器中呢?
@Beanpublic ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); return connectionFactory;}@Beanpublic RabbitTransactionManager rabbitTransactionManager(ConnectionFactory connectionFactory) { return new RabbitTransactionManager(connectionFactory);}
我們只需要這樣做便可以使的使用@Transactional注解來(lái)實(shí)現(xiàn)對(duì)RabbitMQ的事務(wù)管理,其它框架也類(lèi)似。
本文鏈接:http://www.tebozhan.com/showinfo-26-12417-0.htmlSpring事務(wù)管理—快速入門(mén)
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: 詳解Spring多線程下如何保證事務(wù)的一致性
下一篇: HTTP協(xié)議揭秘:探尋互聯(lián)網(wǎng)的背后密碼、探秘?cái)?shù)據(jù)傳輸?shù)膴W秘