15-併發控制理論

金字塔下的蜗牛發表於2024-07-29

15-併發控制理論

併發控制橫跨了多個層級:

  • operator Execution 操作執行
  • Access Methods 讀表
  • buffer Pool Manager 快取池

日誌恢復

  • buffer Pool Manager 快取池
  • Disk 磁碟管理

Motivation:

  • 當多人修改資料庫同一條資料,就會出現競爭問題
  • 把100塊錢從A賬戶轉移到B賬戶,如果A賬戶扣100之後,機房斷電了。當斷電恢復之後,當前的資料庫狀態應該是什麼?(如果沒有恢復,狀態肯定是錯誤)

image-20240727152035882

上面一個涉及丟失更新的問題 Lost Updates ,用併發控來解決。下面一個問題,用永續性來解決,用恢復來解決

併發控制和恢復是資料庫非常重要的功能。他們是實現事務ACID特性的基礎。

基礎理論(txn)是事務.txn 是一個資料庫操作的基礎操作單元。如果沒有顯示開txn,在資料庫中一條sql也是一個txn。

image-20240727152157622

批: 關於儲存過程的理解

  • 從表現上來看,儲存過程整個可以看成是一個大的事務。要麼執行成功,要麼執行失敗。這也就是其與其他程式事務的區別

轉賬包含3個動作:

這三條語句要麼都成功,要麼都失敗。

image-20240727152247865

想當然的思路:

  • 一次只執行一條(不能併發跑,影響資料庫的效能)
  • 將整個資料複製一份,備份一份。在複製一份上進行修改,如果執行成功,就持久化,否則不操作(資料量太大)

image-20240724205526198

所謂併發,就是多個事務交替的執行。以併發的好處:

  • 單條相應時間更短
  • 對系統更高的利用效率

image-20240727152725725

併發的要求

  • 正確性
  • 公平

併發限制的必要性,如果併發不進行限制,會導致什麼問題呢?多個txn交叉執行,會有問題

  • 可能使得資料永久性損失

image-20240727152756018

多個txn能否併發,如何併發?如何交叉執行。這就是接下來要解決的問題

需要尋找一些標準,

image-20240727153027796

資料庫不知道sql語句本身代表的含義,所以 資料庫要判斷txn之間能否交叉執行,如何交叉執行,要根據sql本身去分析。

image-20240727153227567

記住:這裡的data object。為研究方便,將事務簡化成 讀寫操作。

如下介紹資料庫中運算元據的格式。begin開始,commit、abort(rollback)結束為止。 有的地方叫rollback

image-20240727153413407

回滾有可能是程式本身發出的,也有可能是資料庫本身發出的。

比如當前的txn和其他的txn產生了dead clock,那麼資料庫會主動打斷當前txn的程序

改變不了之前的衝突情況。

接下來介紹txn的ACID四個性質。

前面說了 事務併發執行的要滿足正確性與公平性,如下是正確性的四個標準:即 資料庫執行txn怎麼才算正確執行了,標準是什麼?

image-20240727153717645

原子性:要麼執行成功,要麼失敗。

一致性:資料在執行txn之前和之後,狀態要保持一致。資料來自於真實世界,反應真實世界,所以執行前後也要滿足真實世界的邏輯。比如 A向B賬戶賺錢,A賬戶和B賬戶的錢 轉賬前後要保持一致。

隔離性:無論多少個txn在併發執行,從結果上來說和資料庫序列執行一個txn的結果一致。

永續性:一個txn一旦執行成功,其對資料的影響是持久的。 無論是否停電或者是否發生其他非可抗因素。

通俗的版本:

image-20240727154343969

今天要研究四個方面如何實現?

image-20240727154434471

原子性質:

image-20240727154453889

txn只有兩種結局:成功,終止(被回滾)

在使用者看來, 你的指令要麼全部執行,要麼一個也不執行。

image-20240727154603521

兩個場景發生之後,資料庫當前這批資料的狀態應該是什麼?

image-20240727154720640

實現原子性的手段:

  • 日誌
    • 執行一步,同時在日誌中,記錄如果回滾,該如何操作(一般上是兩份日誌,一個是undo,一個是redo)
    • undo log 一般是在記憶體和磁碟中都會存日誌
    • 好像是飛機的黑匣子一樣

日誌不光有回滾txn的作用,還有審計和提高執行效率的作用。

審計:如果資料庫出問題,檢視是哪些操作觸發了審計。

提高效率:即先記錄,在當時並不是真的執行,而後再在合適的時候,執行。 lazy evaluation

  • 只備份你修改的page:增量備份。今天這個技術已經被淘汰了。

image-20240727155142523

一致性:

txn執行前後,要滿足基本的真實世界的邏輯。

一致性分為:

  • 資料庫一致性
  • txn一致性

image-20240727155249139

資料庫一致性:

前後一致性,後面的操作

image-20240727155432397

txn的一致性:要靠業務來保證。

image-20240727155523262

批註:似乎在求解一個帶約束的最佳化問題,最大化的執行事務 在 正確性和公平性的限制下。

二版:最大化事務的併發量

  • 約束條件:ACID

隔離性:

理想的隔離:在一個時間只執行一個txn。

在後面我們會看到:資料庫使用了非常複雜的方法來實現個理性。為什麼要實現隔離性?

為了提高併發度,同時也方便了使用者,寫sql的人。

  • 使用者在進行轉賬操作的時候,直接寫轉賬的sql,能不能操作成功,資料庫來做檢查。

資料庫做隔離性,就是為了使用者能更好的實現業務。

image-20240727155853319

所以,我們需要一種方法來交替穿插的跑txn。這裡面有一個基準:資料庫角度肯定是多個txn一起執行的,但是對使用者來說要像序列跑一樣。

接著從實際的執行效果,對txn進行分類,看看那些類可以進行直接跑,哪些類可以轉化為序列跑。

併發控制協議是決定多個txn如何交替,按照什麼順序執行?什麼時候讓txn失敗

image-20240727160251678

有兩大流派:

  • 悲觀派:事情還未發生之前做控制,讓壞的事情不要發生。比如 後續介紹的兩階段鎖
  • 樂觀派:先發展,後治理。矯枉必過正。出問題了再去讓出問題的txn回滾掉,比如 時間戳併發控制

樂觀比悲觀好。實際中,應該是樂觀悲觀並用。

image-20240727161046089

如何實現併發?

image-20240727161132160

從結果分析:如何才算正確的輸出。因為無論如何執行,要保證結果都是正確的。正確的基準是什麼?是序列執行的結果。只要是和序列執行的結果相符合,那麼就是正確的執行。併發的目標就是同時執行多個事務但是和序列的效果是一樣的。

image-20240727161149723

並沒有說,T1一定要比T2先執行,或者 T2一定要比T1先執。但是執行的結果一定要和序列執行的結果相同。

image-20240727161331267

image-20240727161340349

從結果來看,上述兩個事務順序無論誰先執行結果都是正確的。上述叫真正順序的執行。

interleave(交錯)

如果是真的併發過來的,那麼怎麼讓它交疊的去跑?

交替跑是一個最佳化問題,最佳化目標是最大併發量,約束條件是什麼?是公平,正確。

可以更好的利用頻寬,利用cpu。

交疊跑:

  • 最大化系統併發量
  • 更好的利用多核cpu(系統可用性更高,能更加充分的利用系統)

如果一個txn出錯了,那麼它不會影響別的txn

image-20240727162157216

如果對併發不進行控制,如下就是隨機跑的案例。(這頁PPT有問題)

image-20240729185354426

如下這個就是錯誤的,存在一致性問題。

image-20240729185501450

轉換成資料庫的操作,資料庫在幹什麼?對資料庫而言,所有的操作落實下去無非是讀寫兩個操作。所以後續用讀寫操作為線條,來分析併發中可能遇到的種種問題,而後對種種問題進行解決。

image-20240729185635023

後面分析問題的形式就要發生變化了。變成讀寫角度了

我們可以從人為的角度,判定txn的執行是否存在問題,那麼我們如何編寫程式,讓資料庫來識別出txn的執行是否存在問題?

以真正序列的排程作為基準,如果實際txn的執行可以等價成序列,那麼沒有問題。

image-20240729190035520

那麼如何等效?

image-20240729190054811

真正序列的執行稱之為:Serial Schedule。

ps:這裡面幾個改變,serial schedule(序列化排程),Equivalent Schedules(等價序列化),Serializable Schedule(可序列化排程)的概念

等效序列化:(序列等價)

  • 如果執行的效果 和序列一致,那麼稱之為等效序列化(無論實際制定的順序是什麼,描述有歧義)

image-20240729190224634

可序列化排程 。如果每一個txn都保證一執行,那麼可序列化排程也保證了一致性。

image-20240729190412730

可序列化是一個不太好理解的概念。更大的靈活性意味著更大的並行度。

接下來,從行為或者實際遇到的問題的角度,來分析什麼場景下的併發可以等效序列,什麼可以直接轉化為序列?

image-20240729190644734

衝突操作的定義:兩個操作是衝突的,其需要滿足如下條件:

  • 來自不同的事務
  • 針對在相同的object上,至少有一個是寫

根據上面的定義,衝突有如下三種:

image-20240729190851569

接下來,逐一的看:

讀寫衝突:一個讀了兩次,一個在讀的中間寫了一次,此時前後不一致稱之為 讀寫衝突(又叫不可重複讀)

image-20240729191130823

明顯破壞了隔離性,第一次讀和第二次讀不一樣。

寫讀衝突:(先寫後讀,而後撤銷寫操作)叫髒讀

image-20240729191232743

交叉之後,可序列的執行,會出問題。

序列的結果,要麼最後A和B是T1寫的結果;要麼是T2寫的結果;這兩者任意一個結果都是正確的。不能是兩者混著

寫寫衝突:結果交叉。

image-20240729191446759

研究衝突是為了更好的序列化。

可序列化有兩種

  • 基礎衝突
  • 基於觀察的序列化

image-20240729191757487

兩個txn是衝突等效,當且僅當:

  • 如果

一些衝突操作可以轉換為 序列化操作

ex:不懂這裡

image-20240729191924743

S是衝突等效的,當你可以將s變換成序列排程透過交換不同txn的連續非衝突操作。

image-20240729191951843

判斷如下是否能可以轉化成可序列化序列

image-20240729192246380

為什麼可以滑動?因為不同的action是不存在。

在時間上不同的操作可以滑動位置。(ps:滑動位置只是說明可以序列化,那麼實際執行也是序列化嗎?)

image-20240729192337763

一個反例:

image-20240729192422160

一旦有重複,寫些衝突,不能等效交換。沒辦法轉化成真正序列的。

如果有衝突,不能等效交換位置。

image-20240729192507898

如下也不能交換位置:

image-20240729192609541

除了如上的三種衝突,都是可以交換位置的。

image-20240729192736213

當存在多個txn的時候,交換操作就會變得很難,所以需要新的演算法。

引出依賴圖這個工具:

image-20240729192901745

構建依賴圖。(感覺拓撲排序可能在這裡有用)

如果依賴圖有環,永遠無法等效成序列化。構建依賴圖,判斷是否有環,

image-20240729193237973

如果兩個調換位置,那麼就和序列化之後結果不同的。

image-20240729193316323

因為圖中不存在環,所以可以先執行T2,再執行T2,再執行T3。

如上三個可序列化。不是真序列化,是執行效果相當於序列化。

如下是一個反例:永遠沒有透過滑動的辦法,將如下操作等效為序列化。

image-20240729193730056

好像給了一個依賴圖無法包含的問題。我不懂

前面的是基於衝突的,下面是基於觀察的。

image-20240729193929046

依賴圖顯示不可以,但是根據實際的業務發現是可序列的。依賴圖是有侷限性的,依賴圖會錯殺一些真正可序列化的情況

image-20240729194059418

image-20240729194109267

基於人類 觀察的可序列化 比 基於衝突的 侷限性更少。但是無法實現。

兩種都沒辦法做到100%的不誤殺,因為演算法沒辦法理解業務。多少都會存在錯殺的情況。

image-20240729194327127

實際中,基於衝突的用的更多,因為更好實現。錯殺的特殊情況有些可以形成案例,摘出來,單獨判斷。(大模型套小模型,大模型+規則)

大部分資料庫對於只讀txn,那麼就不需要判斷讀寫依賴,寫讀依賴。直接併發就可以了。

多種排程併發執行分類:
真正序列的是一小部分,稍微多點的是 衝突可序列化。再多的是觀察可序列化。

image-20240729194710449

永續性:

image-20240729194722574

image-20240729194808299

image-20240729194824350

併發控制和恢復是資料庫最重要的功能之一。mysql是免費開源的資料庫支援事務。

txn可以極大的減輕業務的實現複雜度。

併發控制是自動實現的

  • 併發控制要保證:併發執行的效果和單獨的序列執行效果相同

大部分情況下,能用事務儘量用事務,但是某些地方可能直接coding效能更好,因為資料庫不理解業務。

image-20240729195118391

相關文章