天天看點

事務與隔離級别

atomic(原子性):事務中所有的操作是一個整體單元,這個單元中的操作要麼全部成功,要麼全部失敗,不會出現部分失敗、部分成功的場景;

consistency(一緻性):事務在完成時,必須使所有的資料都保持一緻的狀态(限制 a + b = 10,事務結束後 a + b = 10 仍然成立);

isolation(隔離性):各個事務在一定程度上感覺不到其他事務的存在(展現在不同的隔離級别上);

durability(持久性):事務送出後,所有的資料都會永久寫入到磁盤。

資料庫标準提出了 4 類隔離級别,在不同程度上壓制更新丢失。

讀未送出

讀已送出

可重複讀

串行化

讀未送出(read uncommitted) 是最低的隔離級别,允許一個事務讀取另一個事務沒有送出的資料。适合對于資料一緻性沒有要求的場景。它存在髒讀的現象,如下表:

時刻

事務 1

事務 2

說明

t1

讀取庫存為 2

庫存為 2

t2

庫存 - 1

庫存為 1

t3

庫存為 0(讀取到事務 1 沒有送出的資料)

t4

送出事務

庫存儲存為 0

t5

復原

庫存為 0(第一類丢失更新已經克服)

第一類丢失更新:一個事務復原,另一個事務送出,復原覆寫了送出的資料。目前的資料庫都克服了第一類丢失更新。

讀已送出(read committed) 是指一個事務隻能讀取另一個事務已送出的資料,不能讀取未送出的資料。

事務 1 中庫存為 1

事務 2 中庫存為 1(事務 1 未送出)

送出

庫存儲存為 1

復原事務

庫存為 1 (第一類丢失更新已經克服)

上表中的操作結果最終正确。但是讀已送出會産生不可重複讀:

讀取庫存為 1

事務 1 中庫存為 0

事務 2 認為可以扣減(事務 1 未送出)

失敗,此時庫存為 0

這裡事務 2 在事務 1 送出之前認為可以扣減,而後來事務 2 扣減時發現庫存已經為 0 無法扣減,這樣的現象稱為不可重複讀,這就是讀已送出的一個不足。

可重複讀(read repeatable) 的目标是克服讀已送出中出現的不可重複讀的現象。

讀取庫存

事務 2 不能讀取,等待事務 1 送出

庫存為 0,無法扣減

當事務 2 讀取事務 1 事先讀取的資料時,會被阻塞,直到事務 1 送出後事務 2 才能讀取,讀已送出中出現的不可重複讀現象消失了。但是可重複讀會出現幻讀:

查詢庫存 100

庫存 100,10 個訂單

查詢訂單為 10

插入訂單

庫存 99,11 個訂單

t6

列印訂單,11 單

事務 2 中多了一條記錄,與之前查詢的不一緻

上表出現的就是幻讀現象,幻讀不是針對一條資料庫記錄而言,而是多條記錄,上表中訂單是多條記錄統計出來的,它會産生幻讀。

串行化(serializable) 是資料庫最高的隔離級别,所有的事務都按順序執行。它可以克服前面的隔離級别中出現的各種問題,能夠完全保證資料的一緻性。

隔離級别

髒讀

不可重複讀

幻讀

×

不同的隔離級别能夠在不同程度上壓制丢失更新,使用更高的隔離級别能夠更好地保證資料的一緻性,但是也要付出性能的代價。隔離級别越高,性能越是直線地下降。

繼續閱讀