[#0x0034] Isolation

  參考Wikipedia: http://en.wikipedia.org/wiki/Isolation_(database_systems)#Repeatable_reads_.28phantom_reads.29  

 

  Isolation的理想狀態是:the result of Transaction A is invisible to Transaction B until Transaction A is completed。不過這麼一來,只有Serializable級別才能滿足要求,即Transactions是一個接一個地執行,不允許Transactions的並行。如果想要Transactions的並行,那麼就不可能有絕對的isolation。爲此,ANSI/ISO制定的SQL標準給Isolation分了4個級別,由高到低分別是:

  • Serializable
  • Repeatable Read (Phantom Read)
  • Read Committed (Nonrepeatable Read)
  • Read Uncommitted (Dirty Read)

級別越高的,isolation性越好,而低級別的isolation會有各種各樣的併發問題(如上面括號中所示)。下面一一介紹。

 

1. Read Uncommitted

  Transaction 1可以查看Transaction 2未提交的操作結果,這會導致Dirty Read的問題,如下圖所示:

 

dirty read

Transaction 1的執行的第二個query會讀到Transaction 2中update的結果,如果Transaction 2 rollback的話,這個讀到的數據明顯是錯誤的。

 

2. Read Committed

  如果我們強制Transaction 1只能讀Transaction 2中已經commit的update,就可以解決Dirty Read的問題。強制的手段是:每次query(比如SELECT)時,都會獲取當前數據庫(或者可能只是query涉及的表)的一個snapshot,query從這個snapshot中獲得結果。沒有commit的update不會在snapshot中出現,所以就不會被query到。

  這樣允許Transaction 2並行執行,且不會影響Transaction 1。當Transaction 1 commit的時候,DBMS檢測是否有衝突(比如Transaction 1也update了Transaction 2中update的row),如果執行的結果等同於順序執行Transaction 1和 Transaction 2 ,則認爲沒有衝突。

  但這樣也會有問題:Nonrepeatable Read,即可能執行同一query兩次而出現不同的結果,我們認爲這是不符合一致性原則的。

nonrepeatable read

 

3. Repeatable Read

  解決Nonrepeatable Read問題的辦法是給Transaction 1中的SELECT涉及的行加一個read lock。

  鎖的排斥功能很明確:read locks不會block read locks,只block write locks;write locks block both read locks and write locks。

  不過會有新的問題:phantom read。

 

phantom read

 

當Transaction 1執行一個range query(範圍查詢,如like, between等)時,只會爲涉及到的row加read lock,如果插入一個新row在range之內,第二次range query還是會被讀出。

 

4. Serializable

  強制Transactions按順序執行,所以Transaction之間不可能衝突。強制的手段是給place a read lock on every row the transaction read;同時,如果有range query,還會添加一個range lock。明顯,Serializable會耗費很多的lock overhead。

  Serializable相當於在Transaction 1開始時(而不是query開始時)給當前數據庫(或是Transaction涉及的表)take a snapshot,Transaction 1中的所有query都從這一個snapshot中獲取結果。

 

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