- 什么是事務(wù)?
事務(wù)就是以可控的方式對(duì)數(shù)據(jù)資源進(jìn)行訪問的一組操作壮锻,它有四個(gè)限定屬性琐旁,原子性、一致性猜绣、隔離性灰殴、持久性,就是我們常稱的ACID屬性掰邢。 - 隔離性的四種隔離級(jí)別由弱到強(qiáng)分別是Read Uncommited牺陶、Read Commited、Repeatable Read辣之、Serializable掰伸。
- Read Uncommited
最低的隔離級(jí)別,可以讀取到其他事務(wù)未提交的數(shù)據(jù)怀估,無(wú)法避免臟讀狮鸭,幻讀合搅,不可重復(fù)讀等問題。- 臟讀
讀取到另一個(gè)事務(wù)未提交的數(shù)據(jù)歧蕉,然后那個(gè)事務(wù)回滾了灾部,那我們讀到的數(shù)據(jù)就是臟數(shù)據(jù)。 - 不可重復(fù)讀
在同一個(gè)事務(wù)中對(duì)同一筆數(shù)據(jù)進(jìn)行多次讀取惯退,讀取到的結(jié)果不完全相同赌髓。比如在Read Commited隔離級(jí)別,一個(gè)事務(wù)在另一個(gè)事務(wù)提交數(shù)據(jù)前讀一次蒸痹,提交后讀一次,兩次讀取的結(jié)果不一致呛哟。 - 幻讀
同一個(gè)事務(wù)中對(duì)多條記錄(聚合操作也算)進(jìn)行查詢結(jié)果不完全相同的情況叫幻讀叠荠,比如事務(wù)A查詢表發(fā)現(xiàn)表為空,然后準(zhǔn)備插入一個(gè)主鍵為1的數(shù)據(jù)扫责,在事務(wù)A插入之前榛鼎,事務(wù)B完成了插入主鍵為1數(shù)據(jù)的操作,在Repeatable Read級(jí)別鳖孤,事務(wù)A對(duì)B事務(wù)的插入操作不可見(因?yàn)镽epeatable Read能避免不可重復(fù)讀)者娱,但當(dāng)A事務(wù)插入數(shù)據(jù)時(shí)報(bào)錯(cuò),發(fā)現(xiàn)表里已經(jīng)有主鍵為1的數(shù)據(jù)了苏揣。
- 臟讀
- Read Commited
隔離級(jí)別比Read Uncommited 高黄鳍,通常是數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別,一個(gè)事務(wù)的更新操作只有在事務(wù)提交后才能被讀取到平匈】蚬担可以避免臟讀,但無(wú)法避免幻讀和不可重復(fù)讀 - Repeatable Read
可重復(fù)讀增炭,它可以保證在整個(gè)事務(wù)過程中忍燥,對(duì)同一筆數(shù)據(jù)讀取的結(jié)果是相同的,不管其他事務(wù)是否對(duì)該筆數(shù)據(jù)進(jìn)行更新隙姿∶仿ⅲ可以避免臟讀和不可重復(fù)讀,但是不可避免幻讀输玷。 - Serializable
最為嚴(yán)格的隔離級(jí)別队丝,所以操作必須按照順序執(zhí)行,可以避免所有的問題欲鹏,但是效率最低
-
全局事務(wù)和局部事務(wù)
全局事務(wù)也叫分布式事務(wù)炭玫,通過兩階段提交協(xié)調(diào)多RM(Resource Manager一般是數(shù)據(jù)庫(kù))之間的事務(wù)處理,有個(gè)非常恰當(dāng)?shù)睦邮腔槎Y上主持會(huì)分別問男女雙方你愿意嫁給他嗎貌虾?如果有任意一方拒絕吞加,就各自回滾到單身狀態(tài)。TP Monitor負(fù)責(zé)在分布式事務(wù)中協(xié)調(diào)多個(gè)RM的事務(wù)處理,TM是它的核心模塊衔憨。
全局事務(wù)
只有一個(gè)RM參與的就叫局部事務(wù)叶圃,它不必引進(jìn)TP Monitor,應(yīng)用程序可以直接和RM打交道践图,全局事務(wù)和局部事務(wù)的區(qū)別是涉及多少RM掺冠,如果系統(tǒng)中有多個(gè)RM,但是事務(wù)只涉及一個(gè)RM,同樣是局部事務(wù)。
-
Spring事務(wù)
Spring事務(wù)抽象接口關(guān)系圖
- TransactionDefinition
TransactionDefinition定義了事務(wù)的隔離級(jí)別码党,傳播行為德崭,事務(wù)的超時(shí)時(shí)間,是否為只讀事務(wù)揖盘。
public interface TransactionDefinition {
/*傳播行為*/
//如果當(dāng)前存在一個(gè)事務(wù)眉厨,則加入當(dāng)前事務(wù),如果不存在兽狭,則新建一個(gè)事務(wù)憾股,至少保證在一個(gè)事務(wù)中運(yùn)行
int PROPAGATION_REQUIRED = 0;
//如果當(dāng)前存在一個(gè)事務(wù),則加入當(dāng)前事務(wù)箕慧,如果不存在服球,則直接執(zhí)行
int PROPAGATION_SUPPORTS = 1;
//強(qiáng)制要求當(dāng)前存在一個(gè)事務(wù),如果不存在則跑出異常
int PROPAGATION_MANDATORY = 2;
//不管當(dāng)前是否存在事務(wù)颠焦,都會(huì)創(chuàng)建新的事務(wù)斩熊,如果當(dāng)前存在事務(wù)會(huì)掛起當(dāng)前事務(wù)
int PROPAGATION_REQUIRES_NEW = 3;
//不支持當(dāng)前事務(wù),在沒有事務(wù)的情況下執(zhí)行伐庭,如果當(dāng)前存在事務(wù)座享,會(huì)掛起當(dāng)前事務(wù)
int PROPAGATION_NOT_SUPPORTED = 4;
//永遠(yuǎn)不需要當(dāng)前存在事務(wù),如果存在則拋出異常
int PROPAGATION_NEVER = 5;
//如果存在當(dāng)前事務(wù)似忧,則在當(dāng)前事務(wù)的一個(gè)嵌套事務(wù)中執(zhí)行
int PROPAGATION_NESTED = 6;
/*隔離級(jí)別*/
//表示使用數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
int ISOLATION_DEFAULT = -1;
//對(duì)應(yīng)Read_Uncommitted隔離級(jí)別渣叛,無(wú)法避免臟讀,不可重復(fù)讀和幻讀
int ISOLATION_READ_UNCOMMITTED = 1;
//對(duì)應(yīng)Read Committed隔離級(jí)別盯捌,無(wú)法避免不可重復(fù)讀和幻讀
int ISOLATION_READ_COMMITTED = 2;
//對(duì)應(yīng)Repeatable Read淳衙, 無(wú)法避免幻讀
int ISOLATION_REPEATABLE_READ = 4;
//對(duì)應(yīng)Serializable隔離級(jí)別,并發(fā)行最低饺著,能避免所有問題
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
-
PROPAGATION_SUPPORTS和PROPAGATION_NOT_SUPPORTS的區(qū)別
-
PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED的區(qū)別
- TransactionStatus
PlatfornTransactionManager的getTransaction會(huì)返回一個(gè)Transaction對(duì)象箫攀,可以通過它查詢事務(wù)的狀態(tài)
public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
//標(biāo)記當(dāng)前事務(wù)使其回滾
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
- PlatformTransactionManager
public interface PlatformTransactionManager {
/*getTransaction會(huì)開啟一個(gè)事務(wù),但在此之前需要判斷是否存在是否幼衰,
如果存在則根據(jù)傳播行為決定是掛起事務(wù)或者拋出異常靴跛,
不存在事務(wù),同樣需要根據(jù)傳播行為決定如何處理*/
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
/*檢測(cè)全局的rollBackOnly渡嚣,如果被設(shè)置則執(zhí)行回滾*/
void commit(TransactionStatus var1) throws TransactionException;
/*檢測(cè)全局的rollBackOnly梢睛,如果沒被設(shè)置則執(zhí)行提交*/
void rollback(TransactionStatus var1) throws TransactionException;
}