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

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


  • 原子性(Atomicity):事務做爲一個總體被執行,包含在其中的對數據庫的操做要麼所有被執行,要麼都不執行。併發

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

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

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


   咱們假設如今有A,B不一樣的兩個事務,而且假設事務A在事務B以前啓動,在併發執行時會出現的狀況無非只有兩個狀態提交跟未提交,咱們排列組合一下獲得:orm


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

  • 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的隔離級別定義,你們有興趣能夠去查看相關資料。

相關文章
相關標籤/搜索