本篇文章主要介紹資料庫事務的四大特性ACID,以及資料庫的隔離級別。 ...
本篇文章主要介紹資料庫事務的四大特性ACID,以及資料庫的隔離級別。
事務
概念
事務指的是滿足 ACID 特性的一系列操作。在資料庫中,可以通過 Commit提交一個事務,也可以使用 Rollback 進行回滾。
四大特性
- 原子性(Atomicity):事務被視為不可分割的最小單元,要麼全部提交成功,要麼全部失敗回滾。
- 一致性(Consistency):事務執行前後都保持一致性狀態。在一致性狀態下,所有事務對一個數據的讀取結果都是相同的。
- 隔離性(Isolation):一個事務所做的修改在最終提交以前,對其它事務是不可見的。
- 持久性(Durability):一旦事務提交,則其所做的修改將會永遠保存到資料庫中。即使系統發生崩潰,事務執行的結果也不能丟失。可以通過資料庫備份和恢復來保證持久性。
在瞭解完資料庫的四大特性之後,我們來討論一下資料庫的隔離級別的問題。在此之前,我們考慮在沒有資料庫隔離性的情況下,多用戶併發操作可能會發生的問題。
併發一致性問題
在併發環境下,一個事務如果受到另一個事務的影響,那麼事務操作就無法滿足一致性條件。
- 丟失修改:多個事務同時讀取某一數據,一個事務成功處理好了數據,被另一個事務寫回原值,造成第一個事務更新丟失。例如,T1 和 T2 兩個事務都對一個數據進行修改,T1 先修改,T2 隨後修改,T2 的修改覆蓋了 T1 的修改。
- 臟讀:臟讀是指在一個事務處理過程里讀取了另一個未提交的事務中的數據。例如,T1 修改一個數據,T2 隨後讀取這個數據。如果 T1 撤銷了這次修改,那麼 T2 讀取的數據是臟數據。
- 不可重覆讀:不可重覆讀是指在對於資料庫的某個數據,一個事務範圍內多次查詢卻返回了不同的數據值。這是由於在查詢間隔,被另一個事務修改並提交了。例如,T2 讀取一個數據,T1 對該數據做了修改。如果 T2 再次讀取這個數據,此時讀取的結果和和第一次讀取的結果不同。
- 幻讀(虛讀):幻讀是事務非獨立執行時發生的一種現象。例如,T1 讀取某個範圍的數據,T2在這個範圍內插入新的數據,T1再次讀取這個範圍的數據,此時讀取的結果和和第一次讀取的結果不同。
解決方法
產生併發不一致性問題主要原因是破壞了事務的隔離性,解決方法是通過併發控制來保證隔離性。併發控制可以通過封鎖來實現,但是封鎖操作都要用戶自己控制,相當複雜。資料庫管理系統提供了事務的隔離級別,讓用戶以一種更輕鬆的方式處理併發一致性問題。
現在我們來看下事務的四種隔離級別。
隔離級別
- 未提交讀(READ UNCOMMITTED):事務中的修改,即使沒有提交,對其它事務也是可見的。最低級別,任何情況都無法保證。
- 提交讀(READ COMMITTED):一個事務只能讀取已經提交的事務所做的修改。換句話說,一個事務所做的修改在提交之前對其它事務是不可見的。可避免臟讀的發生。
- 可重覆讀(REPEATABLE READ):保證在同一個事務中多次讀取同樣數據的結果是一樣的。可避免臟讀、不可重覆讀的發生。
- 可串列化(SERIALIXABLE):強制事務串列執行。可避免臟讀、不可重覆讀、幻讀的發生。
四種隔離級別的對比
隔離級別 | 臟讀 | 不可重覆讀 | 幻影讀 |
---|---|---|---|
未提交讀 | YES | YES | YES |
提交讀 | NO | YES | YES |
可重覆讀 | NO | NO | YES |
可串列化 | NO | NO | NO |
以上四種隔離級別最高的是SERIALIXABLE(可串列化)級別,最低的是READUNCOMMITTED(未提交讀)級別,當然級別越高,執行效率就越低。像SERIALIXABLE(可串列化)這樣的級別, 就是以鎖表的方式使得其他的線程只能在鎖外等待,所以平時選用何種隔離級別應該根據實際情況。
在MySQL資料庫中,支持上面四種隔離級別,預設的為REPEATABLE READ(可重覆讀);而在Oracle資料庫中,只支持SERIALIXABLE(串列化)級別和READCOMMITTED(讀已提交)這兩種級別 ,其中預設的為READ COMMITTED級別。