日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

MySQL的本地事务、全局事务、分布式事务

發(fā)布時間:2023/10/11 综合教程 116 老码农
生活随笔 收集整理的這篇文章主要介紹了 MySQL的本地事务、全局事务、分布式事务 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本地事務(wù)

事務(wù)特性:ACID,其中C一致性是目的,AID是手段。

實(shí)現(xiàn)隔離性

寫鎖:數(shù)據(jù)加了寫鎖,其他事務(wù)不能寫也不能讀。

讀鎖:數(shù)據(jù)加了讀鎖,其他事務(wù)不能加寫鎖可以加讀鎖,可以允許自己升級為寫鎖。

范圍鎖:對某個范圍加寫鎖,范圍內(nèi)數(shù)據(jù)不能寫入。

隔離級別

以鎖為手段來實(shí)現(xiàn)隔離性才是數(shù)據(jù)庫表現(xiàn)出不同隔離級別的根本原因。

可串行化:對事務(wù)所有讀、寫數(shù)據(jù)加上三種鎖。

可重復(fù)讀:不加范圍鎖,會有幻讀問題。

幻讀是指在事務(wù)執(zhí)行過程中,兩個完全相同的范圍查詢得到了不同的結(jié)果集。譬如現(xiàn)在準(zhǔn)備統(tǒng)計(jì)一下 Fenix's Bookstore 中售價(jià)小于 100 元的書有多少本,會執(zhí)行以下第一條 SQL 語句:

SELECT count(1) FROM books WHERE price < 100					/* 時間順序:1,事務(wù): T1 */
INSERT INTO books(name,price) VALUES ('深入理解Java虛擬機(jī)',90) /* 時間順序:2,事務(wù): T2 */
SELECT count(1) FROM books WHERE price < 100 /* 時間順序:3,事務(wù): T1 */ 兩次執(zhí)行之間有另外一個事務(wù)在數(shù)據(jù)庫插入了一本小于 100 元的書籍,那這兩次相同的查詢就會得到不一樣的結(jié)果,原因是可重復(fù)讀沒有范圍鎖來禁止在該范圍內(nèi)插入新的數(shù)據(jù),這是一個事務(wù)受到其他事務(wù)影響,隔離性被破壞的表現(xiàn)。

讀已提交:寫鎖會一直持續(xù)到事務(wù)結(jié)束,讀鎖在查詢操作完成后馬上釋放。有不可重復(fù)讀問題,讀已提交的隔離級別缺乏貫穿整個事務(wù)周期的讀鎖,無法禁止讀取過的數(shù)據(jù)發(fā)生變化。

讀已提交:有臟讀問題。

MVCC

基本思路是對數(shù)據(jù)庫的修改不會直接覆蓋之前的數(shù)據(jù),而是產(chǎn)生一個新版副本與老版本共存。

“版本”可以理解為每一行記錄存在倆看不見的字段:CREATE_VERRSION和DELETE_VERSION,這兩個字段都是事務(wù)ID,事務(wù)ID是全局遞增的值,根據(jù)以下規(guī)則寫入數(shù)據(jù)。

  • 插入數(shù)據(jù):CREATE_VERRSION記錄插入數(shù)據(jù)的事務(wù)ID,DELETE_VERSION為空。
  • 刪除數(shù)據(jù):DELETE_VERSION記錄刪除數(shù)據(jù)的事務(wù)ID,CREATE_VERRSION為空。
  • 修改數(shù)據(jù):將修改數(shù)據(jù)視為“刪除舊數(shù)據(jù),插入新數(shù)據(jù)”,將原有數(shù)據(jù)復(fù)制一份,原有數(shù)據(jù)DELETE_VERSION記錄修改數(shù)據(jù)的事務(wù)ID。復(fù)制出來的新數(shù)據(jù)CREATE_VERSION記錄修改數(shù)據(jù)的事務(wù)ID。

此時,有另一個事務(wù)讀取這些發(fā)生了變化的數(shù)據(jù),根據(jù)隔離級別決定讀取哪個版本的數(shù)據(jù)。

  • 可重復(fù)讀:在“總是讀取CREATE_VERSION小于等于當(dāng)前事務(wù)ID的數(shù)據(jù)”前提下,如果數(shù)據(jù)有多個版本,讀取事務(wù)ID最大的。
  • 讀已提交:總是讀取最新版本,即最近被Commit版本的數(shù)據(jù)。

MVCC是針對“讀+寫”的優(yōu)化,“寫+寫”只能加鎖解決。競爭激烈的情況下,樂觀鎖可能更慢。

MVCC超售問題

數(shù)據(jù)庫采用的是MVCC方案,是否有可能出現(xiàn)以下這種超售情況

初始quantity值為10,事務(wù): T1和事務(wù): T2都想要將quantity減8

SELECT quantity FROM books WHERE id=1					/* 時間順序:1,事務(wù): T1 */
SELECT quantity FROM books WHERE id=1 /* 時間順序:2,事務(wù): T2 */ /*事務(wù): T1 運(yùn)算后將quantity改為2 因?yàn)镸VCC方案中事務(wù)2的select并不會加讀鎖,所以這條語句可以順利執(zhí)行并commit*/
UPDATE books SET quantity=2 WHERE id=1 /* 時間順序:3,事務(wù): T1 */
commit /*事務(wù): T2 運(yùn)算后將quantity改為2 ,此時沒有其他的事務(wù)了,所以這條語句可以順利執(zhí)行并commit*/
UPDATE books SET quantity=2 WHERE id=1 /* 時間順序:4,事務(wù): T2 */
commit

這種寫法會出現(xiàn)超售,相當(dāng)于賣了兩次8本書。

之前提到過,MVCC只解決“讀-寫”事務(wù)的情況(也就是解決可重復(fù)讀級別下的幻讀),在“寫-寫”的場景中它是不適用的。

也正是為了解決這類情況,InnoDB之類采用MVCC的引擎,都會提供諸如“l(fā)ock in share mode”的語法,讓開發(fā)者在“寫-寫”的場

景中顯式加共享鎖,讓數(shù)據(jù)庫進(jìn)行當(dāng)前讀而非快照讀。

以MySQL為例,把代碼修改為這樣,它就可以保證T1的Update語句被T2的共享鎖阻塞了,達(dá)到避免超售的目的了。

SELECT quantity FROM books WHERE id=1 lock in share mode;		/* 時間順序:1,事務(wù): T1 */
SELECT quantity FROM books WHERE id=1 lock in share mode; /* 時間順序:2,事務(wù): T2 */

全局事務(wù)

2PC

假如你平時以聲明式事務(wù)來編碼,那它與本地事務(wù)看起來可能沒什么區(qū)別,都是標(biāo)個@Transactional注解而已,但如果以編程式事務(wù)來實(shí)現(xiàn)的話,就能在寫法上看出差異,偽代碼如下所示:
public void buyBook(PaymentBill bill) {
userTransaction.begin();
warehouseTransaction.begin();
businessTransaction.begin();
try {
userAccountService.pay(bill.getMoney());
warehouseService.deliver(bill.getItems());
businessAccountService.receipt(bill.getMoney());
userTransaction.commit();
warehouseTransaction.commit();
businessTransaction.commit();
} catch(Exception e) {
userTransaction.rollback();
warehouseTransaction.rollback();
businessTransaction.rollback();
}
}
從代碼上可看出,程序的目的是要做三次事務(wù)提交,但實(shí)際上代碼并不能這樣寫,試想一下,如果在
businessTransaction.commit()中出現(xiàn)錯誤,代碼轉(zhuǎn)到catch塊中執(zhí)行,此時userTransaction和
warehouseTransaction已經(jīng)完成提交,再去調(diào)用rollback()方法已經(jīng)無濟(jì)于事,這將導(dǎo)致一部分?jǐn)?shù)據(jù)被提
交,另一部分被回滾,整個事務(wù)的一致性也就無法保證了。

為了解決這個問題,XA 將事務(wù)提交拆分成為兩階段過程:

  • 準(zhǔn)備階段:又作投票階段,協(xié)調(diào)者詢問事務(wù)的所有參與者是否準(zhǔn)備好提交,參與者如果準(zhǔn)備好提交則回復(fù)Prepared。對于數(shù)據(jù)庫來說,準(zhǔn)備操作是在重做日志中記錄全部事務(wù)提交操作所要做的內(nèi)容,不釋放隔離性,繼續(xù)持有鎖。
  • 提交階段:又作執(zhí)行階段,協(xié)調(diào)者在上一階段收到Prepared消息,先自己在本地持久化事務(wù)狀態(tài)為Commit,操作完成之后向所有參與者發(fā)送Commit指令;否則,任意一個參與者回復(fù)了 Non-Prepared 消息,或任意一個參與者超時未回復(fù),協(xié)調(diào)者將將自己的事務(wù)狀態(tài)持久化為 Abort 之后,向所有參與者發(fā)送 Abort 指令,參與者立即執(zhí)行回滾操作。

缺點(diǎn)

  • 單點(diǎn)問題:協(xié)調(diào)者在兩段提交中具有舉足輕重的作用,協(xié)調(diào)者等待參與者回復(fù)時可以有超時機(jī)制,允許參與者

    宕機(jī),但參與者等待協(xié)調(diào)者指令時無法做超時處理。一旦宕機(jī)的不是其中某個參與者,而是協(xié)調(diào)者的話,所有

    參與者都會受到影響。如果協(xié)調(diào)者一直沒有恢復(fù),沒有正常發(fā)送 Commit 或者 Rollback 的指令,那所有參與

    者都必須一直等待。

  • 性能問題:兩段提交過程中,所有參與者相當(dāng)于被綁定成為一個統(tǒng)一調(diào)度的整體,期間要經(jīng)過兩次遠(yuǎn)程服務(wù)調(diào)

    用,三次數(shù)據(jù)持久化(準(zhǔn)備階段寫重做日志,協(xié)調(diào)者做狀態(tài)持久化,提交階段在日志寫入 Commit

    Record),整個過程將持續(xù)到參與者集群中最慢的那一個處理操作結(jié)束為止,這決定了兩段式提交的性能通

    常都較差。

  • 一致性風(fēng)險(xiǎn)

3PC

三段式提交把原本的兩段式提交的準(zhǔn)備階段細(xì)分為兩個階段,分別稱為CanCommit、PreCommit,提交階段改為

DoCommit階段。CanCommit是詢問階段,協(xié)調(diào)者讓每個參與者根據(jù)自身狀態(tài)評估事務(wù)是否可能完成。

將準(zhǔn)備階段一分為二的理由是:協(xié)調(diào)者發(fā)出開始準(zhǔn)備的消息,參與者開始寫重做日志,如果此時,某一個參與者宣布無法完成,相當(dāng)于大家做了一輪無用功。

因此,在事務(wù)需要回滾的場景中,三段式的性能通常是要比兩段式好很多的,但在事務(wù)能夠正常提交的場景中,兩者的性能都依然很差,甚至三段式因?yàn)槎嗔艘淮卧儐?,還要稍微更差一些。

同樣也是由于事務(wù)失敗回滾概率變小的原因,在三段式提交中,如果在 PreCommit 階段之后發(fā)生了協(xié)調(diào)者宕機(jī),即參與者沒有能等到 DoCommit 的消息的話,默認(rèn)的操作策略將是提交事務(wù)而不是回滾事務(wù)或者持續(xù)等待,這就相當(dāng)于避免了協(xié)調(diào)者單點(diǎn)問題的風(fēng)險(xiǎn)。

分布式事務(wù)

CAP與ACID

柔性事務(wù)與最終一致性。

可靠事件隊(duì)列

最大努力一次提交:將最有可能出錯的業(yè)務(wù)以本地事務(wù)的方式完成后,采用不斷重試的方式促使分布式事務(wù)中的其他關(guān)聯(lián)業(yè)務(wù)全部完成。

TCC事務(wù)

如果業(yè)務(wù)需要隔離,該方案天生適合用于需要強(qiáng)隔離性的分布式事務(wù)中。

TCC 較為煩瑣,它是一種業(yè)務(wù)侵入式較強(qiáng)的事務(wù)方案,要求業(yè)務(wù)處理過程必須拆分為“預(yù)留業(yè)務(wù)資源”和“確認(rèn)/釋放消費(fèi)資源”兩個子過程。如同 TCC 的名字所示,它分為以下三個階段。

  • Try:嘗試執(zhí)行階段,完成所有業(yè)務(wù)可執(zhí)行性的檢查(保障一致性),并且預(yù)留好全部需用到的業(yè)務(wù)資源(保障隔離性)。
  • Confirm:確認(rèn)執(zhí)行階段,不進(jìn)行任何業(yè)務(wù)檢查,直接使用 Try 階段準(zhǔn)備的資源來完成業(yè)務(wù)處理。Confirm 階段可能會重復(fù)執(zhí)行,因此本階段所執(zhí)行的操作需要具備冪等性。
  • Cancel:取消執(zhí)行階段,釋放 Try 階段預(yù)留的業(yè)務(wù)資源。Cancel 階段可能會重復(fù)執(zhí)行,也需要滿足冪等性。

資料

鳳凰架構(gòu)

總結(jié)

以上是生活随笔為你收集整理的MySQL的本地事务、全局事务、分布式事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。