日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
優(yōu)化擴(kuò)展分布式數(shù)據(jù)庫(kù)的隔離級(jí)別

譯者 | 康少京

審校 | 孫淑娟

隔離定義為在數(shù)據(jù)庫(kù)并發(fā)執(zhí)行多個(gè)事務(wù)時(shí),不會(huì)影響到其他事務(wù)的執(zhí)行。本文將解釋這些隔離級(jí)別,并概述它們之間的權(quán)衡。我們還建議選擇最適合您需求的隔離級(jí)別。

讓我們從有效使用隔離級(jí)別所需的最低知識(shí)開始,研究表示大多數(shù)應(yīng)用程序的兩個(gè)用例及其對(duì)不同隔離級(jí)別的影響。

用例1:銀行交易

客戶從銀行賬戶取錢:

  • 開始交易;
  • 讀取用戶余額;
  • 在活動(dòng)表中創(chuàng)建一行(我們避免將其稱為事務(wù),以避免與數(shù)據(jù)庫(kù)事務(wù)混淆);
  • 從讀取的金額中減去提款金額后,更新用戶的余額;
  • 提交。

在交易完成之前,我們不希望用戶的余額發(fā)生變化。

用例2:零售交易

國(guó)際客戶從零售店購(gòu)買物品時(shí)使用的貨幣與標(biāo)價(jià)不同:

  • 開始交易;
  • 讀取exchange_rate表,獲取最新的兌換率;
  • 在訂單表中創(chuàng)建一行;
  • 提交。

假設(shè)有一個(gè)單獨(dú)的過(guò)程正在不斷更新匯率,但我們不關(guān)心匯率在讀取之后是否會(huì)發(fā)生變化,即使當(dāng)前交易還沒(méi)有完成。

可序列化

Serializable隔離級(jí)別是唯一滿足ACID屬性理論定義的級(jí)別。它從本質(zhì)上說(shuō),兩個(gè)并發(fā)事務(wù)不允許相互干擾對(duì)方的更改,如果一個(gè)接一個(gè)地執(zhí)行,則必須產(chǎn)生相同的結(jié)果。

不幸的是,Serializable通常被認(rèn)為是不切實(shí)際的,即使對(duì)于非分布式數(shù)據(jù)庫(kù)。所有現(xiàn)有的流行數(shù)據(jù)庫(kù)(如Postgres和MySQL)都不推薦它,這并不是巧合。

為什么這個(gè)設(shè)置如此不切實(shí)際?讓我們來(lái)看看兩個(gè)用例:

在銀行用例中,Serializable是完美的。在讀取用戶余額后,數(shù)據(jù)庫(kù)保證用戶余額不會(huì)改變。因此,應(yīng)用業(yè)務(wù)邏輯是安全的,例如確保用戶有足夠的余額,并根據(jù)讀取的值寫入新的余額。在銀行用例中,Serializable是完美的。

在零售用例中,Serializable也可以正常工作。在創(chuàng)建訂單的事務(wù)成功之前,不允許更新匯率的流程執(zhí)行其操作。

由于事件的精確順序,這聽起來(lái)像是一個(gè)很棒的功能。但是,如果創(chuàng)建訂單的交易緩慢又復(fù)雜怎么辦?也許它需要去倉(cāng)庫(kù)檢查庫(kù)存。也許它必須對(duì)下訂單的用戶進(jìn)行信用檢查。它將持有該行上的鎖,防止匯率進(jìn)程更新。這種意想不到的依賴關(guān)系可能會(huì)阻止系統(tǒng)擴(kuò)展。

Serializable設(shè)置也會(huì)經(jīng)常出現(xiàn)死鎖。例如,如果兩個(gè)事務(wù)讀取一個(gè)用戶的余額,它們將在該行上放置一個(gè)共享讀取鎖。如果事務(wù)稍后修改該行,它們將嘗試將讀鎖升級(jí)為寫鎖。這將導(dǎo)致死鎖,因?yàn)槊總€(gè)事務(wù)都將被另一個(gè)事務(wù)持有的讀鎖阻塞。正如我們將在下面看到的,不同的隔離級(jí)別可以很容易地避免這個(gè)問(wèn)題。

換句話說(shuō),有爭(zhēng)議的工作負(fù)載將無(wú)法使用Serializable設(shè)置進(jìn)行擴(kuò)展。如果工作負(fù)載沒(méi)有爭(zhēng)議,我們就不需要這個(gè)隔離級(jí)別。較低的隔離可能同樣有效。

為了解決這種不必要且昂貴的安全問(wèn)題,必須重構(gòu)應(yīng)用程序。例如,獲取匯率的代碼在事務(wù)開始之前調(diào)用,或者使用單獨(dú)的連接來(lái)完成讀取程序。

雖然理論上沒(méi)有那么純粹,但其他隔離級(jí)別允許您在個(gè)案的基礎(chǔ)上執(zhí)行序列化讀取。這使得它們?cè)诰帉懣缮炜s系統(tǒng)時(shí)更加靈活和實(shí)用。

無(wú)鎖定實(shí)現(xiàn)

有一些方法可以在不鎖定數(shù)據(jù)的情況下提供可序列化的一致性。然而,這類系統(tǒng)也會(huì)遇到上述相同的問(wèn)題,即沖突交易的失敗方式不同。問(wèn)題的根本原因在于隔離級(jí)別本身,任何實(shí)現(xiàn)都無(wú)法讓您擺脫這些約束。

重復(fù)讀

RepeatableRead是一個(gè)模糊的設(shè)置。因?yàn)樗鼌^(qū)分了點(diǎn)選擇和搜索,并為每個(gè)點(diǎn)定義了不同的行為。這不是非黑即白的,并導(dǎo)致了許多其他實(shí)現(xiàn)。這里就不詳細(xì)討論這個(gè)隔離級(jí)別。然而,就我們的用例而言,RepeatableRead提供了與Serializable相同的保證,因此繼承了相同的問(wèn)題。

快照讀

SnapshotRead隔離級(jí)別雖然不是ANSI標(biāo)準(zhǔn),但已經(jīng)越來(lái)越流行了。也被稱為MVCC。這種隔離級(jí)別的優(yōu)點(diǎn)是無(wú)爭(zhēng)用:它在事務(wù)開始時(shí)創(chuàng)建一個(gè)快照。所有讀取都發(fā)送到該快照,而不獲取任何鎖。但寫操作遵循嚴(yán)格的可序列化規(guī)則。

SnapshotRead事務(wù)對(duì)于只讀工作負(fù)載最有價(jià)值,因?yàn)槟梢钥吹揭恢碌臄?shù)據(jù)庫(kù)快照。這避免了在加載事務(wù)上相互依賴的不同數(shù)據(jù)片段時(shí)出現(xiàn)意外。還可以使用快照功能在特定時(shí)間讀取多個(gè)表,然后觀察自該快照以來(lái)發(fā)生的更改。對(duì)于希望將更改流式傳輸?shù)椒治鰯?shù)據(jù)庫(kù)的更改數(shù)據(jù)捕獲工具,這個(gè)功能非常方便。

對(duì)于執(zhí)行寫入的事務(wù),快照特性不是很有用。您主要想控制是否允許在上次讀取后更改值。如果您想允許該值更改,它將在您閱讀后立即失效,因?yàn)槠渌丝梢陨院髮?duì)其進(jìn)行更新。因此,無(wú)論您是從快照讀取還是獲取最新值,這都沒(méi)有關(guān)系。如果不希望更改,則需要最新的值,并且必須鎖定行以防止更改。

換句話說(shuō),SnapshotRead對(duì)于只讀工作負(fù)載很有用,但對(duì)于寫工作負(fù)載來(lái)說(shuō),它并不比ReadCommitted好,我們將在下面介紹。

在此隔離級(jí)別中重新應(yīng)用Retail用例可以很自然地工作,不會(huì)產(chǎn)生爭(zhēng)用:從匯率中讀取的值產(chǎn)生了創(chuàng)建事務(wù)時(shí)快照的值。在進(jìn)行此交易時(shí),允許單獨(dú)的交易來(lái)更新匯率。

銀行用例如何?數(shù)據(jù)庫(kù)允許您對(duì)數(shù)據(jù)進(jìn)行鎖定。例如,MySQL能夠“在共享模式下選擇…鎖定”(讀鎖)。此模式將讀取升級(jí)為可序列化事務(wù)的讀取。當(dāng)然,還繼承了此隔離級(jí)別的死鎖風(fēng)險(xiǎn)。

較低的隔離級(jí)別可以兩全其美。您可以發(fā)出一個(gè)“select…for update”(寫鎖)。此鎖阻止另一個(gè)事務(wù)獲取此行上的任何類型的鎖。這種悲觀鎖定方法一開始聽起來(lái)很糟糕,但它允許兩個(gè)競(jìng)爭(zhēng)事務(wù)成功完成,而不會(huì)遇到死鎖。第二個(gè)事務(wù)將等待第一個(gè)事務(wù)完成,此時(shí)它將讀取并鎖定新值所在的行。

MySQL默認(rèn)支持SnapshotRead隔離級(jí)別,但會(huì)將其稱為REPEATABLE_READ。

分布式數(shù)據(jù)庫(kù)

雖然單個(gè)數(shù)據(jù)庫(kù)有多種有效實(shí)現(xiàn)可重復(fù)讀取的方法,但在分布式數(shù)據(jù)庫(kù)中,問(wèn)題變得更加復(fù)雜。這是因?yàn)槭聞?wù)可以跨越多個(gè)碎片。如果是這樣,系統(tǒng)必須提供嚴(yán)格的訂購(gòu)保證。這種排序要求系統(tǒng)使用集中的并發(fā)控制機(jī)制或全局一致的時(shí)鐘。這兩種方法本質(zhì)上都試圖將原本可以彼此獨(dú)立執(zhí)行的事件緊密耦合起來(lái)。

因此,在希望分布式數(shù)據(jù)庫(kù)支持分布式快照讀取之前,必須了解并愿意接受這些權(quán)衡。

已提交

ReadCommitted隔離比SnapshotRead更明確,因?yàn)樗粩喾祷財(cái)?shù)據(jù)庫(kù)的最新視圖。這也是隔離級(jí)別中爭(zhēng)議最小的。在這個(gè)級(jí)別上,每次讀取一行時(shí)可能會(huì)得到不同的值。

ReadCommitted設(shè)置還允許您通過(guò)發(fā)出讀或?qū)戞i定來(lái)升級(jí)讀取,從而有效地允許您按需執(zhí)行可序列化讀取。正如前面所說(shuō)的,對(duì)于打算修改數(shù)據(jù)的應(yīng)用程序事務(wù),這種方法提供了兩全其美的解決方案。

Postgres支持的默認(rèn)隔離級(jí)別是ReadCommitted。

讀取未提交

這種隔離級(jí)別通常被認(rèn)為是不安全的,不建議用于分布式或非分布式設(shè)置。這是因?yàn)槟赡軙?huì)讀取稍后可能回滾的數(shù)據(jù)(或者從一開始就不存在的數(shù)據(jù))。

分布式事務(wù)

這個(gè)主題與隔離級(jí)別是正交的,但這里必須涵蓋這一點(diǎn),因?yàn)樗诒3质挛锏乃缮Ⅰ詈戏矫婢哂兄匾饬x。

在分布式系統(tǒng)中,如果兩行位于不同的碎片或數(shù)據(jù)庫(kù)中,并且您希望在單個(gè)事務(wù)中原子化地修改它們,則會(huì)產(chǎn)生兩階段提交(2PC)的開銷。

這需要更多的工作:

  • 創(chuàng)建關(guān)于分布式事務(wù)的元數(shù)據(jù)并保存到持久存儲(chǔ)中。
  • 對(duì)所有單個(gè)交易發(fā)布準(zhǔn)備。
  • 提交的決策保存到元數(shù)據(jù)中。
  • 向準(zhǔn)備好的事務(wù)發(fā)出提交。

prepare要求您保存元數(shù)據(jù),以便在提交(或回滾)前,如果節(jié)點(diǎn)發(fā)生崩潰,可以在新的leader中恢復(fù)事務(wù)。

分布式事務(wù)還與隔離級(jí)別交互。例如,假設(shè)只有2PC事務(wù)的第一次提交成功,第二次提交被延遲。如果應(yīng)用程序已經(jīng)讀取了第一次提交的效果,那么數(shù)據(jù)庫(kù)必須阻止應(yīng)用程序讀取第二次提交的行,直到完成。反過(guò)來(lái)說(shuō),如果應(yīng)用程序在第二次提交之前讀取了一行,那么它肯定看不到第一次提交的效果。

數(shù)據(jù)庫(kù)必須做額外的工作來(lái)支持分布式事務(wù)的隔離保證。如果應(yīng)用程序可以容忍這些部分提交呢?然后,我們就做了應(yīng)用程序不關(guān)心的不必要的工作??赡苤档靡胍粋€(gè)新的隔離級(jí)別,如ReadPartialCommits。請(qǐng)注意,這不同于ReadUncommitted,用戶讀取的數(shù)據(jù)最終可能被回滾。

最后,過(guò)度使用2PC會(huì)降低系統(tǒng)的整體可用性和延遲。這是因?yàn)樾阅茏畈畹乃槠瑢Q定您的有效可用性。

總結(jié)

為了具有可伸縮性,應(yīng)用程序應(yīng)該避免依賴數(shù)據(jù)庫(kù)的任何高級(jí)隔離功能。相反,它應(yīng)該盡可能少地使用擔(dān)保。如果可以編寫一個(gè)應(yīng)用程序來(lái)使用ReadCommitted隔離級(jí)別,那么不建議遷移到SnapshotRead。Serializable或RepeatableRead。

最好避免多語(yǔ)句事務(wù),但隨著應(yīng)用程序的發(fā)展,這可能會(huì)不可避免。此時(shí),嘗試主要依賴事務(wù)的原子保證,并保持?jǐn)?shù)據(jù)庫(kù)系統(tǒng)支持的最低隔離級(jí)別。

如果使用分片數(shù)據(jù)庫(kù),請(qǐng)完全避免分布式事務(wù)。這可以通過(guò)將相關(guān)行保留在同一個(gè)碎片中來(lái)實(shí)現(xiàn)。必須從一開始就這樣做,因?yàn)楹茈y將非并發(fā)程序重構(gòu)為并發(fā)程序。

譯者介紹

康少京,社區(qū)編輯,從事通訊類行業(yè),底層驅(qū)動(dòng)開發(fā)崗位。

原文標(biāo)題:??Optimizing Isolation Levels for Scaling Distributed Databases??,作者:Sugu Sougoumarane


當(dāng)前文章:優(yōu)化擴(kuò)展分布式數(shù)據(jù)庫(kù)的隔離級(jí)別
網(wǎng)頁(yè)路徑:http://www.5511xx.com/article/cogceei.html