事務的基本特征 ACID Atomic(原子性) :事務中所有的操作是一個整體單元,這個單元中的操作要麼全部成功,要麼全部失敗,不會出現部分失敗、部分成功的場景; Consistency(一致性) :事務在完成時,必須使所有的數據都保持一致的狀態(約束 a + b = 10,事務結束後 a + b ...
事務的基本特征 ACID
- Atomic(原子性):事務中所有的操作是一個整體單元,這個單元中的操作要麼全部成功,要麼全部失敗,不會出現部分失敗、部分成功的場景;
- Consistency(一致性):事務在完成時,必須使所有的數據都保持一致的狀態(約束 a + b = 10,事務結束後 a + b = 10 仍然成立);
- Isolation(隔離性):各個事務在一定程度上感覺不到其他事務的存在(體現在不同的隔離級別上);
- Durability(持久性):事務提交後,所有的數據都會永久寫入到磁碟。
事務的隔離級別
資料庫標準提出了 4 類隔離級別,在不同程度上壓制更新丟失。
- 讀未提交
- 讀已提交
- 可重覆讀
- 串列化
讀未提交
讀未提交(read uncommitted) 是最低的隔離級別,允許一個事務讀取另一個事務沒有提交的數據。適合對於數據一致性沒有要求的場景。它存在臟讀的現象,如下表:
時刻 | 事務 1 | 事務 2 | 說明 |
---|---|---|---|
T1 | 讀取庫存為 2 | 庫存為 2 | |
T2 | 庫存 - 1 | 庫存為 1 | |
T3 | 庫存 - 1 | 庫存為 0(讀取到事務 1 沒有提交的數據) | |
T4 | 提交事務 | 庫存保存為 0 | |
T5 | 回滾 | 庫存為 0(第一類丟失更新已經剋服) |
第一類丟失更新:一個事務回滾,另一個事務提交,回滾覆蓋了提交的數據。目前的資料庫都剋服了第一類丟失更新。
讀已提交
讀已提交(read committed) 是指一個事務只能讀取另一個事務已提交的數據,不能讀取未提交的數據。
時刻 | 事務 1 | 事務 2 | 說明 |
---|---|---|---|
T1 | 讀取庫存為 2 | 庫存為 2 | |
T2 | 庫存 - 1 | 事務 1 中庫存為 1 | |
T3 | 庫存 - 1 | 事務 2 中庫存為 1(事務 1 未提交) | |
T4 | 提交 | 庫存保存為 1 | |
T5 | 回滾事務 | 庫存為 1 (第一類丟失更新已經剋服) |
上表中的操作結果最終正確。但是讀已提交會產生不可重覆讀:
時刻 | 事務 1 | 事務 2 | 說明 |
---|---|---|---|
T1 | 讀取庫存為 1 | 庫存為 1 | |
T2 | 庫存 - 1 | 事務 1 中庫存為 0 | |
T3 | 讀取庫存為 1 | 事務 2 認為可以扣減(事務 1 未提交) | |
T4 | 提交 | 庫存保存為 0 | |
T5 | 庫存 - 1 | 失敗,此時庫存為 0 |
這裡事務 2 在事務 1 提交之前認為可以扣減,而後來事務 2 扣減時發現庫存已經為 0 無法扣減,這樣的現象稱為不可重覆讀,這就是讀已提交的一個不足。
可重覆讀
可重覆讀(read repeatable) 的目標是剋服讀已提交中出現的不可重覆讀的現象。
時刻 | 事務 1 | 事務 2 | 說明 |
---|---|---|---|
T1 | 讀取庫存為 1 | 庫存為 1 | |
T2 | 庫存 - 1 | 事務 1 中庫存為 0 | |
T3 | 讀取庫存 | 事務 2 不能讀取,等待事務 1 提交 | |
T4 | 提交 | 庫存保存為 0 | |
T5 | 讀取庫存 | 庫存為 0,無法扣減 |
當事務 2 讀取事務 1 事先讀取的數據時,會被阻塞,直到事務 1 提交後事務 2 才能讀取,讀已提交中出現的不可重覆讀現象消失了。但是可重覆讀會出現幻讀:
時刻 | 事務 1 | 事務 2 | 說明 |
---|---|---|---|
T1 | 查詢庫存 100 | 庫存 100,10 個訂單 | |
T2 | 查詢訂單為 10 | ||
T3 | 庫存 - 1 | ||
T4 | 插入訂單 | ||
T5 | 提交 | 庫存 99,11 個訂單 | |
T6 | 列印訂單,11 單 | 事務 2 中多了一條記錄,與之前查詢的不一致 |
上表出現的就是幻讀現象,幻讀不是針對一條資料庫記錄而言,而是多條記錄,上表中訂單是多條記錄統計出來的,它會產生幻讀。
串列化
串列化(serializable) 是資料庫最高的隔離級別,所有的事務都按順序執行。它可以剋服前面的隔離級別中出現的各種問題,能夠完全保證數據的一致性。
總結
隔離級別 | 臟讀 | 不可重覆讀 | 幻讀 |
---|---|---|---|
讀未提交 | √ | √ | √ |
讀已提交 | × | √ | √ |
可重覆讀 | × | × | √ |
串列化 | × | × | × |
不同的隔離級別能夠在不同程度上壓制丟失更新,使用更高的隔離級別能夠更好地保證數據的一致性,但是也要付出性能的代價。隔離級別越高,性能越是直線地下降。