自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

優(yōu)化擴展分布式數(shù)據(jù)庫的隔離級別

譯文 精選
數(shù)據(jù)庫
本文將解釋分布式數(shù)據(jù)庫的隔離級別,并概述它們之間的權(quán)衡。我們還建議選擇最適合您需求的隔離級別。

譯者 | 康少京

審校 | 孫淑娟

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

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

用例1:銀行交易

客戶從銀行賬戶取錢:

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

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

用例2:零售交易

國際客戶從零售店購買物品時使用的貨幣與標(biāo)價不同:

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

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

可序列化

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

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

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

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

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

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

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

換句話說,有爭議的工作負(fù)載將無法使用Serializable設(shè)置進行擴展。如果工作負(fù)載沒有爭議,我們就不需要這個隔離級別。較低的隔離可能同樣有效。

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

雖然理論上沒有那么純粹,但其他隔離級別允許您在個案的基礎(chǔ)上執(zhí)行序列化讀取。這使得它們在編寫可伸縮系統(tǒng)時更加靈活和實用。

無鎖定實現(xiàn)

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

重復(fù)讀

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

快照讀

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

SnapshotRead事務(wù)對于只讀工作負(fù)載最有價值,因為您可以看到一致的數(shù)據(jù)庫快照。這避免了在加載事務(wù)上相互依賴的不同數(shù)據(jù)片段時出現(xiàn)意外。還可以使用快照功能在特定時間讀取多個表,然后觀察自該快照以來發(fā)生的更改。對于希望將更改流式傳輸?shù)椒治鰯?shù)據(jù)庫的更改數(shù)據(jù)捕獲工具,這個功能非常方便。

對于執(zhí)行寫入的事務(wù),快照特性不是很有用。您主要想控制是否允許在上次讀取后更改值。如果您想允許該值更改,它將在您閱讀后立即失效,因為其他人可以稍后對其進行更新。因此,無論您是從快照讀取還是獲取最新值,這都沒有關(guān)系。如果不希望更改,則需要最新的值,并且必須鎖定行以防止更改。

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

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

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

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

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

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

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

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

已提交

ReadCommitted隔離比SnapshotRead更明確,因為它不斷返回數(shù)據(jù)庫的最新視圖。這也是隔離級別中爭議最小的。在這個級別上,每次讀取一行時可能會得到不同的值。

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

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

讀取未提交

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

分布式事務(wù)

這個主題與隔離級別是正交的,但這里必須涵蓋這一點,因為它在保持事物的松散耦合方面具有重要意義。

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

這需要更多的工作:

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

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

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

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

最后,過度使用2PC會降低系統(tǒng)的整體可用性和延遲。這是因為性能最差的碎片將決定您的有效可用性。

總結(jié)

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

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

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

譯者介紹

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

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

責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2022-03-10 06:36:59

分布式數(shù)據(jù)庫排序

2021-12-20 15:44:28

ShardingSph分布式數(shù)據(jù)庫開源

2023-12-05 07:30:40

KlustronBa數(shù)據(jù)庫

2023-07-31 08:27:55

分布式數(shù)據(jù)庫架構(gòu)

2023-07-28 07:56:45

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

2021-01-13 08:49:36

數(shù)據(jù)庫2PC優(yōu)化

2023-11-14 08:24:59

性能Scylla系統(tǒng)架構(gòu)

2022-06-09 10:19:10

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

2020-06-23 09:35:13

分布式數(shù)據(jù)庫網(wǎng)絡(luò)

2023-03-07 09:49:04

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

2022-08-01 18:33:45

關(guān)系型數(shù)據(jù)庫大數(shù)據(jù)

2024-09-09 09:19:57

2011-05-19 09:18:48

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

2024-03-11 08:57:02

國產(chǎn)數(shù)據(jù)庫證券

2023-12-11 09:11:14

TDSQL技術(shù)架構(gòu)

2024-07-25 07:55:37

2011-03-24 17:15:06

分布式數(shù)據(jù)庫系統(tǒng)

2018-05-25 13:12:10

UCloud數(shù)據(jù)庫UDDB

2023-04-26 06:56:31

分布式數(shù)據(jù)庫偽需求

2012-09-29 13:18:23

分布式數(shù)據(jù)庫Google Span
點贊
收藏

51CTO技術(shù)棧公眾號