事務(transaction)是數據庫管理系統的執行單位,能夠是一個數據庫操做(如Select操做)或者是一組操做序列。事務ACID屬性,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。html
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 |
A事務 | B事務 |
讀餘額爲2000元 | |
轉出1000元 | |
再次讀餘額爲1000元 | |
發現不對,回滾轉出的1000元 | |
再次讀餘額爲2000元,很納悶 |
Read committed 是一個很受歡迎的隔離級別. 像Oracle 11g, PostgreSQL, SQL Server 2012, MemSQL等都是默認此隔離級別的。 mysql
2.1 它保證了下面兩種狀況:sql
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.ui
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.this
(當每一個對象在寫的時候,數據庫會記住已經被提交的舊值和當前事務持有寫鎖設置的新值。當一個事務還在進行中,那麼其餘事務讀取到的就是舊值。只有當新值被提交的時候纔會被其餘事務讀取到。)spa
2. When writing to the database, you will only overwrite data that has been committed (no dirty writes)..net
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.3d
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的文章:http://www.javashuo.com/article/p-xzozrljn-bq.html
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://www.javashuo.com/article/p-gtvoathz-k.html。
A事務 | B事務 |
代碼A1 | |
代碼A2 | |
代碼B1 | |
代碼B2 |
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中兩階段加鎖就用來實現串行化隔離級別。
兩階段分別是事務執行時期的加鎖階段和事務提交或者回滾的解鎖階段。
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》。