Mysql數據庫事務隔離級別


事務(transaction)是數據庫管理系統的執行單位,可以是一個數據庫操作(如Select操作)或者是一組操作序列。事務ACID屬性,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。

 
數據庫事務隔離級別共4個,由低到高依次為Readuncommitted、Readcommitted、Repeatableread、Serializable。
Isolation level Dirty reads Non-repeatable reads Phantoms
Read Uncommitted may occur may occur may occur
Read Committed don't occur may occur may occur
Repeatable Read don't occur don't occur may occur
Serializable don't occur don't occur don't occur
 
Read Uncommitted讀未提交
 
A事務 B事務
讀余額為2000元  
  轉出1000元
再次讀余額為1000元  
  發現不對,回滾轉出的1000元
再次讀余額為2000元,很納悶  
 
 
 
 
 
 
 
 
 
總結:B事務還沒提交,A事務就能實時讀到數據,出現臟讀
 
.Read Committed讀提交

Read committed 是一個很受歡迎的隔離級別. 像Oracle 11g, PostgreSQL, SQL Server 2012, MemSQL等都是默認此隔離級別的。 

  2.1 它保證了下面兩種情況:

  1. When reading from the database, you will only see data that has been committed (no dirty reads).

 

 

  如上圖所示,User1只會讀取到User2已經提交了的數據。

  for every object that is written, the database remembers both the old committed value and the new value set by the transaction that currently holds the write lock.

  While the transaction is ongoing, any other transactions that read the object are simply given the old value. Only when the new value is committed do transactions switch over to reading the new value.

  (當每個對象在寫的時候,數據庫會記住已經被提交的舊值和當前事務持有寫鎖設置的新值。當一個事務還在進行中,那么其他事務讀取到的就是舊值。只有當新值被提交的時候才會被其他事務讀取到。)

 

  2. When writing to the database, you will only overwrite data that has been committed (no dirty writes).

  Most commonly, databases prevent dirty writes by using row-level locks: when a transaction wants to modify a particular object (row or document), it must first acquire a lock on that object.

  It must then hold that lock until the transaction is com‐ mitted or aborted. Only one transaction can hold the lock for any given object; if another transaction wants to write to the same object,

  it must wait until the first transaction is committed or aborted before it can acquire the lock and continue. This locking is done automatically by databases in read committed mode (or stronger iso‐ lation levels). 

  (通常數據庫避免臟寫是使用了行級鎖,當一個事務想要去修改數據時,它會首先得到這個數據對象的鎖,直到事務提交或者回滾。而且只有一個事務能夠持有這個鎖;

  如果其他事務想要去寫相同的數據對象,它必須等到上一個事務提交或者回滾然后去得到這把鎖。這種鎖機制是數據庫在read committed或者更高的隔離級別下自動做到的。)

 

  2.2 雖然RC隔離級別下能夠防止臟讀和臟寫,但是會出現不可重復讀或者讀傾斜(nonrepeatable read or read skew ),如下圖情況

正是因為事務可以讀取到另一個事務已經提交的數據,所以Alice讀取到的數據在有Transfer和沒有Transfer兩種情況下,會不一樣。

為了解決這種問題,數據庫提供了snapshot isolation (快照隔離),也就是multi-version concurrency control (MVCC) 。

籠統點說,就是事務12的所有快照讀只會讀取created by版本號小於等於自己的快照數據。

這兒有一篇形象點的關於MVCC的文章:https://blog.csdn.net/whoamiyang/article/details/51901888

 
.Repeatableread可重復讀(在mysql中也就是snapshot isolation)
 
  在RR隔離級別下基於MVCC解決了不可重復讀的問題,但是事務的修改其實是已經發生了的,如果當前事務對讀到的數據做出寫操作,那么可能就會發生問題。

  Alice和Bob都是基於快照讀去做自己的邏輯操作,這就導致寫傾斜(write skew )。

  其實在RR隔離級別下,Lost updates、Write skew、Phantom reads都是有可能發生的,

  在禁用innodb_locks_unsafe_for_binlog(5.6版本已棄用)的情況下,在搜索和掃描index的時候使用的next-keylocks可以避免幻讀。

  我的理解是,在一個事務開啟但沒有結束之前,SELECT FOR UPDATE(當前讀) 會給查詢到的數據行加上next-key locks,對於同一張表而言,事務之間就是串行化的了。

  具體的加鎖細節還需要區分查詢條件,以及索引的設置等,關於mysql數據庫事務鎖分析的:http://hedengcheng.com/?p=771https://my.oschina.net/u/3159571/blog/3060513/print

  對於SELECT FOR UPDATE(當前讀)如果沒有查詢到數據,那么不同事務間的SELECT操作將不會阻塞,因為gap鎖和gap鎖是允許共存的,只是gap鎖會阻塞DML語句的執行。

 
.Serializable序列化
 
A事務 B事務
代碼A1  
代碼A2  
  代碼B1
  代碼B2
 
 
 
 
 
 
  A事務先開始,就一條一條執行,直到事務結束,才開始B事務,一條一條執行,直到事務結束。解決了所有問題,但是代價最高,性能很低,一般很少使用。
  Implementation of two-phase
    •  If transaction A has read an object and transaction B wants to write to that object, B must wait until A commits or aborts before it can continue.(This ensures that B can’t change the object unexpectedly behind A’s back.)

    •  If transaction A has written an object and transaction B wants to read that object, B must wait until A commits or aborts before it can continue.

  兩階段加鎖,寫操作不僅會阻塞其他的寫操作也會阻塞讀操作,快照隔離(MVCC)讀不會阻塞寫操作,寫操作也不會阻塞讀操作,這也是兩者關鍵的不同點。

  在mysql中兩階段加鎖就用來實現串行化隔離級別。

  兩階段分別是事務執行時期的加鎖階段和事務提交或者回滾的解鎖階段。

5總結:

Dirty reads

  One client reads another client’s writes before they have been committed. The read committed isolation level and stronger levels prevent dirty reads.

  (事務1讀取到另一個事務還沒有提交的寫操作數據,RC及其以上隔離級別能避免臟讀)

Dirty writes

  One client overwrites data that another client has written, but not yet committed. Almost all transaction implementations prevent dirty writes.

  (事務1覆蓋寫了其他事務還沒有提交的寫操作,通常所有的事務實現都能避免臟寫)

Read skew (nonrepeatable reads)

  A client sees different parts of the database at different points in time. This issue is most commonly prevented with snapshot isolation,

  which allows a transaction to read from a consistent snapshot at one point in time. It is usually implemented with multi-version concurrency control (MVCC). 

  (事務在不同時間點看到不同的數據。通常是用快照隔離去避免它,快照隔離允許一個事務讀取某個時間點的快照版本。它通常由MVCC實現。)

Lost updates

  Two clients concurrently perform a read-modify-write cycle. One overwrites the other’s write without incorporating its changes, so data is lost.

  Some implementations of snapshot isolation prevent this anomaly automatically, while others require a manual lock (SELECT FOR UPDATE).

  (兩個事務同時的循環去讀取-修改-寫。其中一個覆蓋寫了其他事務沒有合並的修改,所有導致數據丟失。有些實現基於快照讀可以自動避免修改丟失,然而有些就需要人為的加鎖(SELECT FOR UPDATE))

Write skew

  A transaction reads something, makes a decision based on the value it saw, and writes the decision to the database.

  However, by the time the write is made, the premise of the decision is no longer true. Only serializable isolation prevents this anomaly.

  (一個事務根據當前讀取到的數據做了一些決策,然后把這些決策寫入數據庫。然而到寫的時候,這個決策的前提不再正確了。僅僅只有serializable才能避免這種情況)

Phantom reads

  A transaction reads objects that match some search condition. Another client makes a write that affects the results of that search.

  Snapshot isolation prevents straightforward phantom reads, but phantoms in the context of write skew require special treatment, such as index-range locks. 

  (一個事務讀取到匹配某些搜索條件的對象。其他事務寫操作影響了這個搜索條件的結果。快照隔離能避免簡單的幻讀,但是在寫傾斜的上下文中幻讀需要特殊處理,比如index-range locks。)

注:文章中部分結論及圖片引自《Designing.Data-Intensive.Applications》。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM