淺談關係型數據庫事務的隔離級別

   我們知道在關係型數據庫裏面事務有四個屬性:


  • 原子性(Atomicity):事務作爲一個整體被執行,包含在其中的對數據庫的操作要麼全部被執行,要麼都不執行。

  • 一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變爲另一個一致狀態。一致狀態的含義是數據庫中的數據應滿足完整性約束。

  • 隔離性(Isolation):多個事務併發執行時,一個事務的執行不應影響其他事務的執行。

  • 持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中。


   我們假設現在有A,B不同的兩個事務,並且假設事務A在事務B之前啓動,在併發執行時會出現的情況無非只有兩個狀態提交跟未提交,我們排列組合一下得到:


  • A事務啓動並提交完成後B事務提交

  • A事務啓動並提交完成後B事務未提交

  • A事務啓動並未提交B事務提交

  • A事務啓動並未提交B事務未提交


    進過排序組合後我們得出上面四種情況,而我們只要考慮這四種情況裏面的第2,3點。以下我們來分析1,2,3點的情況,大致可劃分爲A事務提交跟未提交。

   而關係型數據庫裏面對數據的無非是四個基本操作,增,刪,改,查。假設現在有A,B兩個不同的事務,我們根據事務的狀態個四個基本操作組合一下,會得到以下結果。


  A:A事務已提交情況

  1. A事務增加數據已提交B事務增加數據

  2. A事務增加數據已提交B事務刪除數據

  3. A事務增加數據已提交B事務修改數據

  4. A事務增加數據已提交B事務查詢數據

  5. A事務刪除數據已提交B事務增加數據

  6. A事務刪除數據已提交B事務刪除數據

  7. A事務刪除數據已提交B事務修改數據

  8. A事務刪除數據已提交B事務查詢數據

  9. A事務修改數據已提交B事務增加數據

  10. A事務修改數據已提交B事務刪除數據

  11. A事務修改數據已提交B事務修改數據

  12. A事務修改數據已提交B事務查詢數據

  13. A事務查詢數據已提交B事務增加數據

  14. A事務查詢數據已提交B事務刪除數據

  15. A事務查詢數據已提交B事務修改數據

  16. A事務查詢數據已提交B事務查詢數據


  B:A事務未提交情況

  1. A事務增加數據未提交B事務增加數據

  2. A事務增加數據未提交B事務刪除數據

  3. A事務增加數據未提交B事務修改數據

  4. A事務增加數據未提交B事務查詢數據

  5. A事務刪除數據未提交B事務增加數據

  6. A事務刪除數據未提交B事務刪除數據

  7. A事務刪除數據未提交B事務修改數據

  8. A事務刪除數據未提交B事務查詢數據

  9. A事務修改數據未提交B事務增加數據

  10. A事務修改數據未提交B事務刪除數據

  11. A事務修改數據未提交B事務修改數據

  12. A事務修改數據未提交B事務查詢數據

  13. A事務查詢數據未提交B事務增加數據

  14. A事務查詢數據未提交B事務刪除數據

  15. A事務查詢數據未提交B事務修改數據

  16. A事務查詢數據未提交B事務查詢數據


  以上是A,B事務在併發情況下的所有組合,我們把以上異常情況做一個歸納,設計者們早就替我們總結了各自的概念含義,根據網上相關資料,能得到以下概念:


  • 丟失更新:撤銷一個事務時,把其他事務已提交的更新數據覆蓋(AB事務併發執行,A事務執行更新後,提交;B事務在A事務更新後,B事務結束前也做了對該行數據的更新操作,然後回滾,則兩次更新操作都丟失了)。

  • 髒讀:一個事務讀到另一個事務未提交的更新數據(AB事務併發執行,B事務執行更新後,A事務查詢B事務沒有提交的數據,B事務回滾,則A事務得到的數據不是數據庫中的真實數據。也就是髒數據,即和數據庫中不一致的數據)。

  • 不可重複讀:一個事務讀到另一個事務已提交的更新數據(AB事務併發執行,A事務查詢數據,然後B事務更新該數據,A再次查詢該數據時,發現該數據變化了)。

  • 覆蓋更新:這是不可重複讀中的特例,一個事務覆蓋另一個事務已提交的更新數據(即A事務更新數據,然後B事務更新該數據,A事務查詢發現自己更新的數據變了)。

  • 虛讀(幻讀)一個事務讀到另一個事務已提交的新插入的數據(AB事務併發執行,A事務查詢數據,B事務插入或者刪除數據,A事務再次查詢發現結果集中有以前沒有的數據或者以前有的數據消失了)。


   事務隔離級別的存在就是爲了防止以上現象發生的,根據資料查證:

    ANSI/ISO SQL定義的標準隔離級別如下:

可序列化(Serializable)

最高的隔離級別。

在基於鎖機制併發控制的DBMS實現可序列化要求在選定對象上的讀鎖和寫鎖保持直到事務結束後才能釋放。在SELECT 的查詢中使用一個“WHERE”子句來描述一個範圍時應該獲得一個“範圍鎖(range-locks)”。這種機制可以避免“幻影讀(phantom reads)”現象。

當採用不基於鎖的併發控制時不用獲取鎖。但當系統探測到幾個併發事務有“寫衝突”的時候,只有其中一個是允許提交的。這種機制的詳細描述見“'快照隔離”

可重複讀(Repeatable reads)

在可重複讀(REPEATABLE READS)隔離級別中,基於鎖機制併發控制的DBMS需要對選定對象的讀鎖(read locks)和寫鎖(write locks)一直保持到事務結束,但不要求“範圍鎖(range-locks)”,因此可能會發生“幻影讀(phantom reads)”

提交讀(Read committed)

在提交讀(READ COMMITTED)級別中,基於鎖機制併發控制的DBMS需要對選定對象的寫鎖(write locks)一直保持到事務結束,但是讀鎖(read locks)在SELECT操作完成後馬上釋放(因此“不可重複讀”現象可能會發生,見下面描述)。和前一種隔離級別一樣,也不要求“範圍鎖(range-locks)”。

簡而言之,提交讀這種隔離級別保證了讀到的任何數據都是提交的數據,避免讀到中間的未提交的數據,髒讀(dirty reads)。但是不保證事務重新讀的時候能讀到相同的數據,因爲在每次數據讀完之後其他事務可以修改剛纔讀到的數據。

未提交讀(Read uncommitted)

未提交讀(READ UNCOMMITTED)是最低的隔離級別。允許髒讀(dirty reads),事務可以看到其他事務“尚未提交”的修改。

通過比低一級的隔離級別要求更多的限制,高一級的級別提供更強的隔離性。標準允許事務運行在更強的事務隔離級別上。(如在可重複讀(REPEATABLE READS)隔離級別上執行提交讀(READ COMMITTED)的事務是沒有問題的)


另外以上只是數據庫層面的隔離級別,在一些應用層面也有針對以上情況定義出相應的隔離級別,例如Spring的隔離級別定義,大家有興趣可以去查看相關資料。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章