Transaction 也就是所謂的事務(wù)了,通俗理解就是一件事情。從小,父母就教育我們,做事情要有始有終,不能半途而廢。 事務(wù)也是這樣,不能做一般就不做了,要么做完,要么就不做。也就是說,事務(wù)必須是一個(gè)不可分割的整體,就像我們?cè)诨瘜W(xué)課里學(xué)到的原子,原子是構(gòu)成物質(zhì)的最小單位。于是,人們就歸納出事務(wù)的第一個(gè)特性:原子性(Atomicity)。我靠,一點(diǎn)都不神秘嘛。
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),威信企業(yè)網(wǎng)站建設(shè),威信品牌網(wǎng)站建設(shè),網(wǎng)站定制,威信網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,威信網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。特別是在數(shù)據(jù)庫領(lǐng)域,事務(wù)是一個(gè)非常重要的概念,除了原子性以外,它還有一個(gè)極其重要的特性,那就是:一致性(Consistency)。也就是說,執(zhí)行完數(shù)據(jù)庫操作后,數(shù)據(jù)不會(huì)被破壞。打個(gè)比方,如果從 A 賬戶轉(zhuǎn)賬到 B 賬戶,不可能因?yàn)?A 賬戶扣了錢,而 B 賬戶沒有加錢吧。如果出現(xiàn)了這類事情,您一定會(huì)非常氣憤,什么 diao 銀行??!
當(dāng)我們編寫了一條 update 語句,提交到數(shù)據(jù)庫的一剎那間,有可能別人也提交了一條 delete 語句到數(shù)據(jù)庫中。也許我們都是對(duì)同一條記錄進(jìn)行操作,可以想象,如果不稍加控制,就會(huì)出×××煩來。我們必須保證數(shù)據(jù)庫操作之間是“隔離”的(線程之間有時(shí)也要做到隔離),彼此之間沒有任何干擾。這就是:隔離性(Isolation)。
要想真正的做到操作之間完全沒有任何干擾是很難的,于是乎,每天上班打醬油的數(shù)據(jù)庫專家們,開始動(dòng)腦筋了,“我們要制定一個(gè)規(guī)范,讓各個(gè)數(shù)據(jù)庫廠商都支持我們的規(guī)范!”,這個(gè)規(guī)范就是:事務(wù)隔離級(jí)別(Transaction Isolation Level)。能定義出這樣牛逼的規(guī)范真的挺不容易的,其實(shí)說白了就四個(gè)級(jí)別:
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE
千萬不要去翻譯,那只是一個(gè)代號(hào)而已。從上往下,級(jí)別越來越高,并發(fā)性越來越差,安全性越來越高,反之則反。
當(dāng)我們執(zhí)行一條 insert 語句后,數(shù)據(jù)庫必須要保證有一條數(shù)據(jù)永久地存放在磁盤中,這個(gè)也算事務(wù)的一條特性, 它就是:持久性(Durability)。
歸納一下,以上一共提到了事務(wù)的4條特性,把它們的英文單詞首字母合起來就是:ACID,這個(gè)就是傳說中的“事務(wù) ACID 特性”!
真的是非常牛逼的特性?。∵@ 4 條特性,是事務(wù)管理的基石,一定要透徹理解。此外還要明確,這四個(gè)家伙當(dāng)中,誰才是老大?
其實(shí)想想也就清楚了:原子性是基礎(chǔ),隔離性是手段,持久性是目的,真正的老大就是一致性。數(shù)據(jù)不一致了,就相當(dāng)于“江湖亂套了,流氓戴胸罩”。所以說,這三個(gè)小弟都是跟著“一致性”這個(gè)老大混,為他全心全意服務(wù)。
這四個(gè)家伙當(dāng)中,其實(shí)最難理解的反倒不是一致性,而是隔離性。因?yàn)樗潜WC一致性的重要手段,是工具,使用它不能有半點(diǎn)差池,否則后果自負(fù)!怪不得數(shù)據(jù)庫行業(yè)專家們都要來研究所謂的事務(wù)隔離級(jí)別了。其實(shí),定義這四個(gè)級(jí)別就是為了解決數(shù)據(jù)在高并發(fā)下所產(chǎn)生的問題,那又有哪些問題呢?
Dirty Read(臟讀)
Unrepeatable Read(不可重復(fù)讀)
Phantom Read(幻讀)
首先看看“臟讀”,看到“臟”這個(gè)字,我就想到了惡心、骯臟。數(shù)據(jù)怎么可能臟呢?其實(shí)也就是我們經(jīng)常說的“垃圾數(shù)據(jù)”了。比如說,有兩個(gè)事務(wù),它們?cè)诓l(fā)執(zhí)行(也就是競爭)??纯匆韵逻@個(gè)表格,您一定會(huì)明白我在說什么:
余額應(yīng)該為 1500 元才對(duì)!請(qǐng)看 T5 時(shí)間點(diǎn),事務(wù) A 此時(shí)查詢余額為 0 元,這個(gè)數(shù)據(jù)就是臟數(shù)據(jù),它是事務(wù) B 造成的,明顯事務(wù)沒有進(jìn)行隔離,滲過來了,亂套了。
所以臟讀這件事情是非常要不得的,一定要解決掉!讓事務(wù)之間隔離起來才是硬道理。
那第 2 條,不可重復(fù)讀又怎么解釋呢?還是用類似的例子來說明:
事務(wù) A 其實(shí)除了查詢了兩次以外,其他什么事情都沒有做,結(jié)果錢就從 1000 變成 0 了,這就是重復(fù)讀了。可想而知,這是別人干的,不是我干的。其實(shí)這樣也是合理的,畢竟事務(wù) B 提交了事務(wù),數(shù)據(jù)庫將結(jié)果進(jìn)行了持久化,所以事務(wù) A 再次讀取自然就發(fā)生了變化。
這種現(xiàn)象基本上是可以理解的,但在有些變態(tài)的場景下卻是不允許的。畢竟這種現(xiàn)象也是事務(wù)之間沒有隔離所造成的,但我們對(duì)于這種問題,似乎可以忽略。
最后一條,幻讀。我去!Phantom 這個(gè)單詞不就是“幽靈、鬼魂”嗎?剛看到這個(gè)單詞時(shí),真的把我的小弟弟都給驚呆了。怪不得這里要翻譯成“幻讀”了,總不能翻譯成“幽靈讀”、“鬼魂讀”吧。其實(shí)意義就是鬼在讀,不是人在讀,或者說搞不清楚為什么,它就變了,很暈,真的很暈。還是用一個(gè)示例來說話吧:
銀行工作人員,每次統(tǒng)計(jì)總存款,都看到不一樣的結(jié)果。不過這也確實(shí)也挺正常的,總存款增多了,肯定是這個(gè)時(shí)候有人在存錢。但是如果銀行系統(tǒng)真的這樣設(shè)計(jì),那算是玩完了。這同樣也是事務(wù)沒有隔離所造成的,但對(duì)于大多數(shù)應(yīng)用系統(tǒng)而言,這似乎也是正常的,可以理解,也是允許的。銀行里那些惡心的那些系統(tǒng),要求非常嚴(yán)密,統(tǒng)計(jì)的時(shí)候,甚至?xí)⑺械钠渌僮鹘o隔離開,這種隔離級(jí)別就算非常高了(估計(jì)要到 SERIALIZABLE 級(jí)別了)。
歸納一下,以上提到了事務(wù)并發(fā)所引起的跟讀取數(shù)據(jù)有關(guān)的問題,各用一句話來描述一下:
臟讀:事務(wù) A 讀取了事務(wù) B 未提交的數(shù)據(jù),并在這個(gè)基礎(chǔ)上又做了其他操作。
不可重復(fù)讀:事務(wù) A 讀取了事務(wù) B 已提交的更改數(shù)據(jù)。
幻讀:事務(wù) A 讀取了事務(wù) B 已提交的新增數(shù)據(jù)。
第一條是堅(jiān)決抵制的,后兩條在大多數(shù)情況下可不作考慮。
這就是為什么必須要有事務(wù)隔離級(jí)別這個(gè)東西了,它就像一面墻一樣,隔離不同的事務(wù)。看下面這個(gè)表格,您就清楚了不同的事務(wù)隔離級(jí)別能處理怎樣的事務(wù)并發(fā)問題:
根據(jù)您的實(shí)際需求,再參考這張表,最后確定事務(wù)隔離級(jí)別,應(yīng)該不再是一件難事了。
JDBC 也提供了這四類事務(wù)隔離級(jí)別,但默認(rèn)事務(wù)隔離級(jí)別對(duì)不同數(shù)據(jù)庫產(chǎn)品而言,卻是不一樣的。我們熟知的 MySQL 數(shù)據(jù)庫的默認(rèn)事務(wù)隔離級(jí)別就是 READ_COMMITTED,Oracle、SQL Server、DB2等都有有自己的默認(rèn)值。我認(rèn)為 READ_COMMITTED 已經(jīng)可以解決絕大多數(shù)問題了,其他的就具體情況具體分析吧。
若對(duì)其他數(shù)據(jù)庫的默認(rèn)事務(wù)隔離級(jí)別不太清楚,可以使用以下代碼來獲?。?/p>
DatabaseMetaData meta = DBUtil.getDataSource().getConnection().getMetaData();
int defaultIsolation = meta.getDefaultTransactionIsolation();
提示:在 java.sql.Connection 類中可查看所有的隔離級(jí)別。
我們知道 JDBC 只是連接 Java 程序與數(shù)據(jù)庫的橋梁而已,那么數(shù)據(jù)庫又是怎樣隔離事務(wù)的呢?其實(shí)它就是“鎖”這個(gè)東西。當(dāng)插入數(shù)據(jù)時(shí),就鎖定表,這叫“鎖表”;當(dāng)更新數(shù)據(jù)時(shí),就鎖定行,這叫“鎖行”。當(dāng)然這個(gè)已經(jīng)超出了我們今天討論的范圍,所以還是留點(diǎn)空間給我們的 DBA 同學(xué)吧,免得他沒啥好寫的了。
除了 JDBC 給我們提供的事務(wù)隔離級(jí)別這種解決方案以外,還有哪些解決方案可以完善事務(wù)管理功能呢?
不妨看看 Spring 的解決方案吧,其實(shí)它是對(duì) JDBC 的一個(gè)補(bǔ)充或擴(kuò)展。它提供了一個(gè)非常重要的功能,就是:事務(wù)傳播行為(Transaction Propagation Behavior)。
確實(shí)夠牛逼的,Spring 一下子就提供了 7 種事務(wù)傳播行為,這 7 種行為一出現(xiàn),真的是亮瞎了我的狗眼!
PROPAGATION_REQUIRED
RROPAGATION_REQUIRES_NEW
PROPAGATION_NESTED
PROPAGATION_SUPPORTS
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
PROPAGATION_MANDATORY
看了 Spring 參考手冊(cè)之后,更是暈了,這到底是在干嘛?
首先要明確的是,事務(wù)是從哪里來?傳播到哪里去?答案是,從方法 A 傳播到方法 B。Spring 解決的只是方法之間的事務(wù)傳播,那情況就多了,比如:
方法 A 有事務(wù),方法 B 也有事務(wù)。
方法 A 有事務(wù),方法 B 沒有事務(wù)。
方法 A 沒有事務(wù),方法 B 有事務(wù)。
方法 A 沒有事務(wù),方法 B 也沒有事務(wù)。
這樣就是 4 種了,還有 3 種特殊情況。還是用我的 Style 給大家做一個(gè)分析吧:
假設(shè)事務(wù)從方法 A 傳播到方法 B,您需要面對(duì)方法 B,問自己一個(gè)問題:
方法 A 有事務(wù)嗎?
如果沒有,就新建一個(gè)事務(wù);如果有,就加入當(dāng)前事務(wù)。這就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默認(rèn)事務(wù)傳播行為,適合絕大多數(shù)情況。
如果沒有,就新建一個(gè)事務(wù);如果有,就將當(dāng)前事務(wù)掛起。這就是 RROPAGATION_REQUIRES_NEW,意思就是創(chuàng)建了一個(gè)新事務(wù),它和原來的事務(wù)沒有任何關(guān)系了。
如果沒有,就新建一個(gè)事務(wù);如果有,就在當(dāng)前事務(wù)中嵌套其他事務(wù)。這就是 PROPAGATION_NESTED,也就是傳說中的“嵌套事務(wù)”了,所嵌套的子事務(wù)與主事務(wù)之間是有關(guān)聯(lián)的(當(dāng)主事務(wù)提交或回滾,子事務(wù)也會(huì)提交或回滾)。
如果沒有,就以非事務(wù)方式執(zhí)行;如果有,就使用當(dāng)前事務(wù)。這就是 PROPAGATION_SUPPORTS,這種方式非常隨意,沒有就沒有,有就有,有點(diǎn)無所謂的態(tài)度,反正我是支持你的。
如果沒有,就以非事務(wù)方式執(zhí)行;如果有,就將當(dāng)前事務(wù)掛起。這就是 PROPAGATION_NOT_SUPPORTED,這種方式非常強(qiáng)硬,沒有就沒有,有我也不支持你,把你掛起來,不鳥你。
如果沒有,就以非事務(wù)方式執(zhí)行;如果有,就拋出異常。這就是 PROPAGATION_NEVER,這種方式更猛,沒有就沒有,有了反而報(bào)錯(cuò),確實(shí)夠牛的,它說:我從不支持事務(wù)!
如果沒有,就拋出異常;如果有,就使用當(dāng)前事務(wù)。這就是 PROPAGATION_MANDATORY,這種方式可以說是牛逼中的牛逼了,沒有事務(wù)直接就報(bào)錯(cuò),確實(shí)夠狠的,它說:我必須要有事務(wù)!
看到我上面這段解釋,小伙伴們是否已經(jīng)感受到,被打通任督二脈的感覺?多讀幾遍,體會(huì)一下,就是您自己的東西了。
需要注意的是 PROPAGATION_NESTED,不要被它的名字所欺騙,Nested(嵌套),所以凡是在類似方法 A 調(diào)用方法 B 的時(shí)候,在方法 B 上使用了這種事務(wù)傳播行為,如果您真的那樣做了,那您就錯(cuò)了。因?yàn)槟e(cuò)誤地以為 PROPAGATION_NESTED 就是為方法嵌套調(diào)用而準(zhǔn)備的,其實(shí)默認(rèn)的 PROPAGATION_REQUIRED 就可以幫助您,做您想要做的事情了。
Spring給我們帶來了事務(wù)傳播行為,這確實(shí)是一個(gè)非常強(qiáng)大而又實(shí)用的功能。除此以外,也提供了一些小的附加功能,比如:
1事務(wù)超時(shí)(Transaction Timeout):為了解決事務(wù)時(shí)間太長,消耗太多的資源,所以故意給事務(wù)設(shè)置一個(gè)大時(shí)常,如果超過了,就回滾事務(wù)。
2只讀事務(wù)(Readonly Transaction):為了忽略那些不需要事務(wù)的方法,比如讀取數(shù)據(jù),這樣可以有效地提高一些性能。
最后,推薦大家使用 Spring 的注解式事務(wù)配置,而放棄 XML 式事務(wù)配置。因?yàn)樽⒔鈱?shí)在是太優(yōu)雅了,當(dāng)然這一切都取決于您自身的情況了。
在 Spring 配置文件中使用:
...
<tx:annotation-driven />
...
在需要事務(wù)的方法上使用:
Transactional
public void xxx() {
...
}
可在 @Transactional 注解中設(shè)置:事務(wù)隔離級(jí)別、事務(wù)傳播行為、事務(wù)超時(shí)時(shí)間、是否只讀事務(wù)。
簡直是太完美了,太優(yōu)雅了!
最后,有必要對(duì)本文的內(nèi)容做一個(gè)總結(jié),免費(fèi)贈(zèng)送一張高清無碼思維導(dǎo)圖:
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
分享標(biāo)題:事務(wù)Transaction那點(diǎn)事兒-創(chuàng)新互聯(lián)
本文路徑:http://jinyejixie.com/article18/dcgjgp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、網(wǎng)站策劃、企業(yè)網(wǎng)站制作、服務(wù)器托管、網(wǎng)站改版、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容