溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)

發(fā)布時(shí)間:2020-06-19 18:54:56 來源:網(wǎng)絡(luò) 閱讀:606 作者:Java技術(shù)箭 欄目:編程語言

認(rèn)識(shí)事務(wù)


1.1 為什么需要數(shù)據(jù)庫事務(wù)

轉(zhuǎn)賬是生活中常見的操作,比如從A賬戶轉(zhuǎn)賬100元到B賬號(hào)。站在用戶角度而言,這是一個(gè)邏輯上的單一操作,然而在數(shù)據(jù)庫系統(tǒng)中,至少會(huì)分成兩個(gè)步驟來完成:

  1. 將A賬戶的金額減少100元

  2. 將B賬戶的金額增加100元。

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


在這個(gè)過程中可能會(huì)出現(xiàn)以下問題:

  • 轉(zhuǎn)賬操作的第一步執(zhí)行成功,A賬戶上的錢減少了100元,但是第二步執(zhí)行失敗或者未執(zhí)行便發(fā)生系統(tǒng)崩潰,導(dǎo)致B賬戶并沒有相應(yīng)增加100元。


  • 轉(zhuǎn)賬操作剛完成就發(fā)生系統(tǒng)崩潰,系統(tǒng)重啟恢復(fù)時(shí)丟失了崩潰前的轉(zhuǎn)賬記錄。


  • 同時(shí)又另一個(gè)用戶轉(zhuǎn)賬給B賬戶,由于同時(shí)對(duì)B賬戶進(jìn)行操作,導(dǎo)致B賬戶金額出現(xiàn)異常。

為了便于解決這些問題,需要引入數(shù)據(jù)庫事務(wù)的概念。

1.2 什么是數(shù)據(jù)庫事務(wù)

定義:數(shù)據(jù)庫事務(wù)是構(gòu)成單一邏輯工作單元的操作集合,一個(gè)典型的數(shù)據(jù)庫事務(wù)如下所示:

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


關(guān)于事務(wù)的定義有幾點(diǎn)需要解釋下:

  • 數(shù)據(jù)庫事務(wù)可以包含一個(gè)或多個(gè)數(shù)據(jù)庫操作,但這些操作構(gòu)成一個(gè)邏輯上的整體。


  • 構(gòu)成邏輯整體的這些數(shù)據(jù)庫操作,要么全部執(zhí)行成功,要么全部不執(zhí)行。


  • 構(gòu)成事務(wù)的所有操作,要么全都對(duì)數(shù)據(jù)庫產(chǎn)生影響,要么全都不產(chǎn)生影響,即不管事務(wù)是否執(zhí)行成功,數(shù)據(jù)庫總能保持一致性狀態(tài)。


  • 以上即使在數(shù)據(jù)庫出現(xiàn)故障以及并發(fā)事務(wù)存在的情況下依然成立。


1.3 事務(wù)如何解決問題

對(duì)于上面的轉(zhuǎn)賬例子,可以將轉(zhuǎn)賬相關(guān)的所有操作包含在一個(gè)事務(wù)中

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


  1. 當(dāng)數(shù)據(jù)庫操作失敗或者系統(tǒng)出現(xiàn)崩潰,系統(tǒng)能夠以事務(wù)為邊界進(jìn)行恢復(fù),不會(huì)出現(xiàn)A賬戶金額減少而B賬戶未增加的情況。

  2. 當(dāng)有多個(gè)用戶同時(shí)操作數(shù)據(jù)庫時(shí),數(shù)據(jù)庫能夠以事務(wù)為單位進(jìn)行并發(fā)控制,使多個(gè)用戶對(duì)B賬戶的轉(zhuǎn)賬操作相互隔離。


事務(wù)使系統(tǒng)能夠更方便的進(jìn)行故障恢復(fù)以及并發(fā)控制,從而保證數(shù)據(jù)庫狀態(tài)的一致性。

1.4 事務(wù)的ACID特性以及實(shí)現(xiàn)原理

原子性(Atomicity):事務(wù)中的所有操作作為一個(gè)整體像原子一樣不可分割,要么全部成功,要么全部失敗。

一致性(Consistency):事務(wù)的執(zhí)行結(jié)果必須使數(shù)據(jù)庫從一個(gè)一致性狀態(tài)到另一個(gè)一致性狀態(tài)。

一致性狀態(tài)是指:

  1. 系統(tǒng)的狀態(tài)滿足數(shù)據(jù)的完整性約束(主碼,參照完整性,check約束等)

  2. 系統(tǒng)的狀態(tài)反應(yīng)數(shù)據(jù)庫本應(yīng)描述的現(xiàn)實(shí)世界的真實(shí)狀態(tài),比如轉(zhuǎn)賬前后兩個(gè)賬戶的金額總和應(yīng)該保持不變。

隔離性(Isolation):并發(fā)執(zhí)行的事務(wù)不會(huì)相互影響,其對(duì)數(shù)據(jù)庫的影響和它們串行執(zhí)行時(shí)一樣。

比如多個(gè)用戶同時(shí)往一個(gè)賬戶轉(zhuǎn)賬,最后賬戶的結(jié)果應(yīng)該和他們按先后次序轉(zhuǎn)賬的結(jié)果一樣。

持久性(Durability):事務(wù)一旦提交,其對(duì)數(shù)據(jù)庫的更新就是持久的。任何事務(wù)或系統(tǒng)故障都不會(huì)導(dǎo)致數(shù)據(jù)丟失。

在事務(wù)的ACID特性中,C即一致性是事務(wù)的根本追求,而對(duì)數(shù)據(jù)一致性的破壞主要來自兩個(gè)方面:

  1. 事務(wù)的并發(fā)執(zhí)行

  2. 事務(wù)故障或系統(tǒng)故障

數(shù)據(jù)庫系統(tǒng)是通過并發(fā)控制技術(shù)和日志恢復(fù)技術(shù)來避免這種情況發(fā)生的。

并發(fā)控制技術(shù)保證了事務(wù)的隔離性,使數(shù)據(jù)庫的一致性狀態(tài)不會(huì)因?yàn)椴l(fā)執(zhí)行的操作被破壞。

日志恢復(fù)技術(shù)保證了事務(wù)的原子性,使一致性狀態(tài)不會(huì)因事務(wù)或系統(tǒng)故障被破壞。

同時(shí)使已提交的對(duì)數(shù)據(jù)庫的修改不會(huì)因系統(tǒng)崩潰而丟失,保證了事務(wù)的持久性。

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



并發(fā)異常與并發(fā)控制


2.1 常見的并發(fā)異常

在講解并發(fā)控制技術(shù)前,先簡(jiǎn)單介紹下數(shù)據(jù)庫常見的并發(fā)異常。

臟寫,臟寫是指事務(wù)回滾了其他事務(wù)對(duì)數(shù)據(jù)項(xiàng)的已提交修改,比如下面這種情況

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


在事務(wù)1對(duì)數(shù)據(jù)A的回滾,導(dǎo)致事務(wù)2對(duì)A的已提交修改也被回滾了。

丟失更新。丟失更新是指事務(wù)覆蓋了其他事務(wù)對(duì)數(shù)據(jù)的已提交修改,導(dǎo)致這些修改好像丟失了一樣。

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



事務(wù)1和事務(wù)2讀取A的值都為10,事務(wù)2先將A加上10并提交修改,之后事務(wù)2將A減少10并提交修改,A的值最后為,導(dǎo)致事務(wù)2對(duì)A的修改好像丟失了一樣

臟讀。臟讀是指一個(gè)事務(wù)讀取了另一個(gè)事務(wù)未提交的數(shù)據(jù)

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



在事務(wù)1對(duì)A的處理過程中,事務(wù)2讀取了A的值,但之后事務(wù)1回滾,導(dǎo)致事務(wù)2讀取的A是未提交的臟數(shù)據(jù)。

不可重復(fù)讀,指一個(gè)事務(wù)對(duì)同一數(shù)據(jù)的讀取結(jié)果前后不一致。

臟讀和不可重復(fù)讀的區(qū)別在于:前者讀取的是事務(wù)未提交的臟數(shù)據(jù),后者讀取的是事務(wù)已經(jīng)提交的數(shù)據(jù),只不過因?yàn)閿?shù)據(jù)被其他事務(wù)修改過導(dǎo)致前后兩次讀取的結(jié)果不一樣

比如下面這種情況

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


由于事務(wù)2對(duì)A的已提交修改,事務(wù)1前后兩次讀取的結(jié)果不一致。

幻讀。幻讀是指事務(wù)讀取某個(gè)范圍的數(shù)據(jù)時(shí),因?yàn)槠渌聞?wù)的操作導(dǎo)致前后兩次讀取的結(jié)果不一致。

幻讀和不可重復(fù)讀的區(qū)別在于,不可重復(fù)讀是針對(duì)確定的某一行數(shù)據(jù)而言,而幻讀是針對(duì)不確定的多行數(shù)據(jù)。

因而幻讀通常出現(xiàn)在帶有查詢條件的范圍查詢中,比如下面這種情況:

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



事務(wù)1查詢A<5的數(shù)據(jù),由于事務(wù)2插入了一條A=4的數(shù)據(jù),導(dǎo)致事務(wù)1兩次查詢得到的結(jié)果不一樣

2.2 事務(wù)的隔離級(jí)別

事務(wù)具有隔離性,理論上來說事務(wù)之間的執(zhí)行不應(yīng)該相互產(chǎn)生影響,其對(duì)數(shù)據(jù)庫的影響應(yīng)該和它們串行執(zhí)行時(shí)一樣。

然而完全的隔離性會(huì)導(dǎo)致系統(tǒng)并發(fā)性能很低,降低對(duì)資源的利用率,因而實(shí)際上對(duì)隔離性的要求會(huì)有所放寬,這也會(huì)一定程度造成對(duì)數(shù)據(jù)庫一致性要求降低

SQL標(biāo)準(zhǔn)為事務(wù)定義了不同的隔離級(jí)別,從低到高依次是

  1. 讀未提交(READ UNCOMMITTED)

  2. 讀已提交(READ COMMITTED)

  3. 可重復(fù)讀(REPEATABLE READ)

  4. 串行化(SERIALIZABLE)


事務(wù)的隔離級(jí)別越低,可能出現(xiàn)的并發(fā)異常越多,但是通常而言系統(tǒng)能提供的并發(fā)能力越強(qiáng)。

不同的隔離級(jí)別與可能的并發(fā)異常的對(duì)應(yīng)情況如下表所示

有一點(diǎn)需要強(qiáng)調(diào),這種對(duì)應(yīng)關(guān)系只是理論上的,對(duì)于特定的數(shù)據(jù)庫實(shí)現(xiàn)不一定準(zhǔn)確

比如mysql的Innodb存儲(chǔ)引擎通過Next-Key Locking技術(shù)在可重復(fù)讀級(jí)別就消除了幻讀的可能。

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


所有事務(wù)隔離級(jí)別都不允許出現(xiàn)臟寫,而串行化可以避免所有可能出現(xiàn)的并發(fā)異常,但是會(huì)極大的降低系統(tǒng)的并發(fā)處理能力。

2.3 事務(wù)隔離性的實(shí)現(xiàn)—常見的并發(fā)控制技術(shù)

并發(fā)控制技術(shù)是實(shí)現(xiàn)事務(wù)隔離性以及不同隔離級(jí)別的關(guān)鍵,實(shí)現(xiàn)方式有很多。按照其對(duì)可能沖突的操作采取的不同策略可以分為樂觀并發(fā)控制和悲觀并發(fā)控制兩大類。

  • 樂觀并發(fā)控制:對(duì)于并發(fā)執(zhí)行可能沖突的操作,假定其不會(huì)真的沖突,允許并發(fā)執(zhí)行,直到真正發(fā)生沖突時(shí)才去解決沖突,比如讓事務(wù)回滾。

  • 悲觀并發(fā)控制:對(duì)于并發(fā)執(zhí)行可能沖突的操作,假定其必定發(fā)生沖突,通過讓事務(wù)等待(鎖)或者中止(時(shí)間戳排序)的方式使并行的操作串行執(zhí)行。


2.3.1 基于封鎖的并發(fā)控制

核心思想:對(duì)于并發(fā)可能沖突的操作,比如讀-寫,寫-讀,寫-寫,通過鎖使它們互斥執(zhí)行。

鎖通常分為共享鎖和排他鎖兩種類型

  • 共享鎖(S):事務(wù)T對(duì)數(shù)據(jù)A加共享鎖,其他事務(wù)只能對(duì)A加共享鎖但不能加排他鎖。

  • 排他鎖(X):事務(wù)T對(duì)數(shù)據(jù)A加排他鎖,其他事務(wù)對(duì)A既不能加共享鎖也不能加排他鎖

基于鎖的并發(fā)控制流程:

  • 事務(wù)根據(jù)自己對(duì)數(shù)據(jù)項(xiàng)進(jìn)行的操作類型申請(qǐng)相應(yīng)的鎖(讀申請(qǐng)共享鎖,寫申請(qǐng)排他鎖)

  • 申請(qǐng)鎖的請(qǐng)求被發(fā)送給鎖管理器。鎖管理器根據(jù)當(dāng)前數(shù)據(jù)項(xiàng)是否已經(jīng)有鎖以及申請(qǐng)的和持有的鎖是否沖突決定是否為該請(qǐng)求授予鎖。

  • 若鎖被授予,則申請(qǐng)鎖的事務(wù)可以繼續(xù)執(zhí)行;若被拒絕,則申請(qǐng)鎖的事務(wù)將進(jìn)行等待,直到鎖被其他事務(wù)釋放。

可能出現(xiàn)的問題:

  • 死鎖:多個(gè)事務(wù)持有鎖并互相循環(huán)等待其他事務(wù)的鎖導(dǎo)致所有事務(wù)都無法繼續(xù)執(zhí)行。


  • 饑餓:數(shù)據(jù)項(xiàng)A一直被加共享鎖,導(dǎo)致事務(wù)一直無法獲取A的排他鎖。

對(duì)于可能發(fā)生沖突的并發(fā)操作,鎖使它們由并行變?yōu)榇袌?zhí)行,是一種悲觀的并發(fā)控制。

2.3.2 基于時(shí)間戳的并發(fā)控制

核心思想:對(duì)于并發(fā)可能沖突的操作,基于時(shí)間戳排序規(guī)則選定某事務(wù)繼續(xù)執(zhí)行,其他事務(wù)回滾。

系統(tǒng)會(huì)在每個(gè)事務(wù)開始時(shí)賦予其一個(gè)時(shí)間戳,這個(gè)時(shí)間戳可以是系統(tǒng)時(shí)鐘也可以是一個(gè)不斷累加的計(jì)數(shù)器值,當(dāng)事務(wù)回滾時(shí)會(huì)為其賦予一個(gè)新的時(shí)間戳,先開始的事務(wù)時(shí)間戳小于后開始事務(wù)的時(shí)間戳。

每一個(gè)數(shù)據(jù)項(xiàng)Q有兩個(gè)時(shí)間戳相關(guān)的字段:

  • W-timestamp(Q):成功執(zhí)行write(Q)的所有事務(wù)的最大時(shí)間戳

  • R-timestamp(Q):成功執(zhí)行read(Q)的所有事務(wù)的最大時(shí)間戳

時(shí)間戳排序規(guī)則如下:

假設(shè)事務(wù)T發(fā)出read(Q),T的時(shí)間戳為TS

  1. 若TS(T)<w-timestamp(q),則t需要讀入的q已被覆蓋。此

  2. read操作將被拒絕,T回滾。

  3. 若TS(T)>=W-timestamp(Q),則執(zhí)行read操作,同時(shí)把R-timestamp(Q)設(shè)置為TS(T)與R-timestamp(Q)中的最大值


假設(shè)事務(wù)T發(fā)出write(Q)

  1. 若TS(T)<r-timestamp(q),write操作被拒絕,t回滾

  2. 若TS(T)<w-timestamp(q),則write操作被拒絕,t回滾

  3. 其他情況:系統(tǒng)執(zhí)行write操作,將W-timestamp(Q)設(shè)置為TS(T)

基于時(shí)間戳排序和基于鎖實(shí)現(xiàn)的本質(zhì)一樣:對(duì)于可能沖突的并發(fā)操作,以串行的方式取代并發(fā)執(zhí)行,因而它也是一種悲觀并發(fā)控制。

它們的區(qū)別主要有兩點(diǎn):

  • 基于鎖是讓沖突的事務(wù)進(jìn)行等待,而基于時(shí)間戳排序是讓沖突的事務(wù)回滾。

  • 基于鎖沖突事務(wù)的執(zhí)行次序是根據(jù)它們申請(qǐng)鎖的順序,先申請(qǐng)的先執(zhí)行;而基于時(shí)間戳排序是根據(jù)特定的時(shí)間戳排序規(guī)則。


2.3.3 基于有效性檢查的并發(fā)控制

核心思想:事務(wù)對(duì)數(shù)據(jù)的更新首先在自己的工作空間進(jìn)行,等到要寫回?cái)?shù)據(jù)庫時(shí)才進(jìn)行有效性檢查,對(duì)不符合要求的事務(wù)進(jìn)行回滾。

基于有效性檢查的事務(wù)執(zhí)行過程會(huì)被分為三個(gè)階段:

  1. 讀階段:數(shù)據(jù)項(xiàng)被讀入并保存在事務(wù)的局部變量中。所有write操作都是對(duì)局部變量進(jìn)行,并不對(duì)數(shù)據(jù)庫進(jìn)行真正的更新。

  2. 有效性檢查階段:對(duì)事務(wù)進(jìn)行有效性檢查,判斷是否可以執(zhí)行write操作而不違反可串行性。如果失敗,則回滾該事務(wù)。

  3. 寫階段:事務(wù)已通過有效性檢查,則將臨時(shí)變量中的結(jié)果更新到數(shù)據(jù)庫中。

有效性檢查通常也是通過對(duì)事務(wù)的時(shí)間戳進(jìn)行比較完成的,不過和基于時(shí)間戳排序的規(guī)則不一樣。

該方法允許可能沖突的操作并發(fā)執(zhí)行,因?yàn)槊總€(gè)事務(wù)操作的都是自己工作空間的局部變量,直到有效性檢查階段發(fā)現(xiàn)了沖突才回滾。因而這是一種樂觀的并發(fā)策略。

2.3.4 基于快照隔離的并發(fā)控制

快照隔離是多版本并發(fā)控制(mvcc)的一種實(shí)現(xiàn)方式。

其核心思想是:數(shù)據(jù)庫為每個(gè)數(shù)據(jù)項(xiàng)維護(hù)多個(gè)版本(快照),每個(gè)事務(wù)只對(duì)屬于自己的私有快照進(jìn)行更新,在事務(wù)真正提交前進(jìn)行有效性檢查,使得事務(wù)正常提交更新或者失敗回滾。

由于快照隔離導(dǎo)致事務(wù)看不到其他事務(wù)對(duì)數(shù)據(jù)項(xiàng)的更新,為了避免出現(xiàn)丟失更新問題,可以采用以下兩種方案避免:

  • 先提交者獲勝:對(duì)于執(zhí)行該檢查的事務(wù)T,判斷是否有其他事務(wù)已經(jīng)將更新寫入數(shù)據(jù)庫,是則T回滾否則T正常提交。

  • 先更新者獲勝:通過鎖機(jī)制保證第一個(gè)獲得鎖的事務(wù)提交其更新,之后試圖更新的事務(wù)中止。

事務(wù)間可能沖突的操作通過數(shù)據(jù)項(xiàng)的不同版本的快照相互隔離,到真正要寫入數(shù)據(jù)庫時(shí)才進(jìn)行沖突檢測(cè)。因而這也是一種樂觀并發(fā)控制。

故障與故障恢復(fù)


3.1 為什么需要故障恢復(fù)技術(shù)

數(shù)據(jù)庫運(yùn)行過程中可能會(huì)出現(xiàn)故障,這些故障包括事務(wù)故障和系統(tǒng)故障兩大類

  • 事務(wù)故障:比如非法輸入,系統(tǒng)出現(xiàn)死鎖,導(dǎo)致事務(wù)無法繼續(xù)執(zhí)行。

  • 系統(tǒng)故障:比如由于軟件漏洞或硬件錯(cuò)誤導(dǎo)致系統(tǒng)崩潰或中止。

這些故障可能會(huì)對(duì)事務(wù)和數(shù)據(jù)庫狀態(tài)造成破壞,因而必須提供一種技術(shù)來對(duì)各種故障進(jìn)行恢復(fù),保證數(shù)據(jù)庫一致性,事務(wù)的原子性以及持久性。

數(shù)據(jù)庫通常以日志的方式記錄數(shù)據(jù)庫的操作從而在故障時(shí)進(jìn)行恢復(fù),因而可以稱之為日志恢復(fù)技術(shù)。

3.2 事務(wù)的執(zhí)行過程以及可能產(chǎn)生的問題

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


事務(wù)的執(zhí)行過程可以簡(jiǎn)化如下:

  1. 系統(tǒng)會(huì)為每個(gè)事務(wù)開辟一個(gè)私有工作區(qū)

  2. 事務(wù)讀操作將從磁盤中拷貝數(shù)據(jù)項(xiàng)到工作區(qū)中,在執(zhí)行寫操作前所有的更新都作用于工作區(qū)中的拷貝.

  3. 事務(wù)的寫操作將把數(shù)據(jù)輸出到內(nèi)存的緩沖區(qū)中,等到合適的時(shí)間再由緩沖區(qū)管理器將數(shù)據(jù)寫入到磁盤。

由于數(shù)據(jù)庫存在立即修改和延遲修改,所以在事務(wù)執(zhí)行過程中可能存在以下情況:

  1. 在事務(wù)提交前出現(xiàn)故障,但是事務(wù)對(duì)數(shù)據(jù)庫的部分修改已經(jīng)寫入磁盤數(shù)據(jù)庫中。這導(dǎo)致了事務(wù)的原子性被破壞。

  2. 在系統(tǒng)崩潰前事務(wù)已經(jīng)提交,但數(shù)據(jù)還在內(nèi)存緩沖區(qū)中,沒有寫入磁盤。系統(tǒng)恢復(fù)時(shí)將丟失此次已提交的修改。這是對(duì)事務(wù)持久性的破壞。

3.3 日志的種類和格式

  • <T,X,V1,V2>:描述一次數(shù)據(jù)庫寫操作,T是執(zhí)行寫操作的事務(wù)的唯一標(biāo)識(shí),X是要寫的數(shù)據(jù)項(xiàng),V1是數(shù)據(jù)項(xiàng)的舊值,V2是數(shù)據(jù)項(xiàng)的新值。


  • <T,X,V1>:對(duì)數(shù)據(jù)庫寫操作的撤銷操作,將事務(wù)T的X數(shù)據(jù)項(xiàng)恢復(fù)為舊值V1。在事務(wù)恢復(fù)階段插入。

  • <T start>: 事務(wù)T開始

  • <T commit>: 事務(wù)T提交

  • <T,abort>: 事務(wù)T中止

關(guān)于日志,有以下兩條規(guī)則

  1. 系統(tǒng)在對(duì)數(shù)據(jù)庫進(jìn)行修改前會(huì)在日志文件末尾追加相應(yīng)的日志記錄。

  2. 當(dāng)一個(gè)事務(wù)的commit日志記錄寫入到磁盤成功后,稱這個(gè)事務(wù)已提交,但事務(wù)所做的修改可能并未寫入磁盤


3.4 日志恢復(fù)的核心思想

  • 撤銷事務(wù)undo:將事務(wù)更新的所有數(shù)據(jù)項(xiàng)恢復(fù)為日志中的舊值,事務(wù)撤銷完畢時(shí)將插入一條<T abort>記錄。

  • 重做事務(wù)redo:將事務(wù)更新的所有數(shù)據(jù)項(xiàng)恢復(fù)為日志中的新值。

事務(wù)正?;貪L/因事務(wù)故障中止將進(jìn)行redo,系統(tǒng)從崩潰中恢復(fù)時(shí)將先進(jìn)行redo再進(jìn)行undo。

以下事務(wù)將進(jìn)行undo:日志中只包括<T start>記錄,但既不包括<T commit>記錄也不包括<T abort>記錄.

以下事務(wù)將進(jìn)行redo:日志中包括<T start>記錄,也包括<T commit>記錄或<T abort>記錄。

假設(shè)系統(tǒng)從崩潰中恢復(fù)時(shí)日志記錄如下

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


由于T0既有start記錄又有commit記錄,將會(huì)對(duì)事務(wù)T0進(jìn)行重做,執(zhí)行相應(yīng)的redo操作。

由于T1只有start記錄,將會(huì)對(duì)T1進(jìn)行撤銷,執(zhí)行相應(yīng)的undo操作,撤銷完畢將寫入一條abort記錄。

3.5 事務(wù)故障中止/正?;貪L的恢復(fù)流程

  1. 從后往前掃描日志,對(duì)于事務(wù)T的每個(gè)形如<T,X,V1,V2>的記錄,將舊值V1寫入數(shù)據(jù)項(xiàng)X中。

  2. 往日志中寫一個(gè)特殊的只讀記錄<T,X,V1>,表示將數(shù)據(jù)項(xiàng)恢復(fù)成舊值V1,這是一個(gè)只讀的補(bǔ)償記錄,不需要根據(jù)它進(jìn)行undo。

  3. 一旦發(fā)現(xiàn)<T start>日志記錄,就停止繼續(xù)掃描,并往日志中寫一個(gè)

  4. <T abort>日志記錄。


「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



3.6 系統(tǒng)崩潰時(shí)的恢復(fù)過程(帶檢查點(diǎn))

檢查點(diǎn)是形如<checkpoint L>的特殊的日志記錄,L是寫入檢查點(diǎn)記錄時(shí)還未提交的事務(wù)的集合

系統(tǒng)保證在檢查點(diǎn)之前已經(jīng)提交的事務(wù)對(duì)數(shù)據(jù)庫的修改已經(jīng)寫入磁盤,不需要進(jìn)行redo。檢查點(diǎn)可以加快恢復(fù)的過程。

系統(tǒng)奔潰時(shí)的恢復(fù)過程分為兩個(gè)階段:重做階段和撤銷階段。

重做階段:

  1. 系統(tǒng)從最后一個(gè)檢查點(diǎn)開始正向的掃描日志,將要重做的事務(wù)的列表undo-list設(shè)置為檢查點(diǎn)日志記錄中的L列表。

  2. 發(fā)現(xiàn)<T,X,V1,V2>的更新記錄或<T,X,V>的補(bǔ)償撤銷記錄,就重做該操作。

  3. 發(fā)現(xiàn)<T start>記錄,就把T加入到undo-list中。

  4. 發(fā)現(xiàn)<T abort>或<T commit>記錄,就把T從undo-list中去除。

撤銷階段:

  1. 系統(tǒng)從尾部開始反向掃描日志

  2. 發(fā)現(xiàn)屬于undo-list中的事務(wù)的日志記錄,就執(zhí)行undo操作

  3. 發(fā)現(xiàn)undo-list中事務(wù)的T的<T start>記錄,就寫入一條<T abort>記錄,

  4. 并把T從undo-list中去除。

  5. undo-list為空,則撤銷階段結(jié)束

總結(jié):先將日志記錄中所有事務(wù)的更新按順序重做一遍,在針對(duì)需要撤銷的事務(wù)按相反的順序執(zhí)行其更新操作的撤銷操作。

3.6.1 一個(gè)系統(tǒng)崩潰恢復(fù)的例子

恢復(fù)前的日志如下,寫入最后一條日志記錄后系統(tǒng)崩潰

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)



總結(jié)

事務(wù)是數(shù)據(jù)庫系統(tǒng)進(jìn)行并發(fā)控制的基本單位,是數(shù)據(jù)庫系統(tǒng)進(jìn)行故障恢復(fù)的基本單位,從而也是保持?jǐn)?shù)據(jù)庫狀態(tài)一致性的基本單位。

ACID是事務(wù)的基本特性,數(shù)據(jù)庫系統(tǒng)是通過并發(fā)控制技術(shù)和日志恢復(fù)技術(shù)來對(duì)事務(wù)的ACID進(jìn)行保證的,從而可以得到如下的關(guān)于數(shù)據(jù)庫事務(wù)的概念體系結(jié)構(gòu)。

「技術(shù)干貨」阿里架構(gòu)師寫給 Java 工程師的數(shù)據(jù)庫事務(wù)


?


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI