標籤:
SQL標準定義了4類隔離等級,包括了一些具體規則,用來限定事務內外的那些改變時可見的,那些是不可見的。低層級的隔離級一般支援更高的並發處理,並擁有更低的系統開銷。
ReadUncommitted(讀取未提交內容)
在該隔離等級,所有事務都可以看到其他未提交事務的執行結構。本隔離等級很少用於實際應用,因為它的效能也不比其他層級好多少。讀取未提交的資料,也被稱之為髒讀(Dirty Read)
ReadCommitted(讀取提交內容)
這是大多數資料庫系統的預設隔離等級(但不是MySQL預設的)。它滿足了隔離的簡單定義:
一個事務只能看見已經提交事務所做的改變。這種隔離等級也支援所謂的不可重複讀取(Nonrepeatable Read),因為同一個事務的其他執行個體在該執行個體處理期間可能會有新的commit,所以同一select可能返回不同結果。
RepeatableRead(可重讀)
這是MySQL的預設交易隔離等級,它確保同一事務的多個執行個體在並發讀取資料時,會看到同樣的資料行。不過理論上,這會導致另一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀值當使用者讀取某一範圍的資料行時,另一個事務又在該範圍插入入了新行,當使用者再讀取該範圍的資料行時,會返現有新的“幻影”行。InnDB和Falcon儲存引擎通過多版本並發控制(MVCC)機制解決該問題。
Serializable(可序列化)
這是最高的隔離等級,它通過強制事務排序,使之不可能互相衝突,從而解決幻讀問題。簡言之,它是在每個讀的資料行上加了共用鎖定。在這個層級,可能導致大量的逾時現象和鎖競爭。
這四種隔離等級採用不同的鎖類型來實現,若讀取的是同一個資料的話,就容易發生問題。例如:
髒讀(Drity Read):
某個事務已更新一份資料,另一個事務在此時讀取了同一個分資料,由於某些原因,前一個RooBack了操作,則後一個事務所讀取的資料就會是不正確的。
不可重複讀取(Non-repeatable read):
在一個事務的兩次查詢之中資料不一致,這可能是兩次查詢過程之間插入了一個事務更新的原有資料。
幻讀(Phantom Read):
在一個事務的兩次查詢中資料條數不一致,例如有一個事務查詢了幾行資料,而另一個事務卻在此時插入了新的幾行資料,先前的事務在接下來的查詢中,就會發現有幾行資料是它先前所沒有的。
在MySQL中實現了這四種隔離等級,分別有可能產生如下問題:
隔離等級 |
髒讀 |
不可重複讀取 |
幻讀 |
讀未提交(Read uncommitted) |
會 |
會 |
會 |
讀已提交(Read committed) |
不會 |
會 |
會 |
可重複讀(Repeatable read) |
不會 |
不會 |
會 |
可序列化(Serializable) |
不會 |
不會 |
不會 |
查詢當前交易隔離等級:
SELECT @@tx_isolation;
設定交易隔離等級:
SET tx_isolation = ‘’;
開啟事務:
START transaction;
提交事務:
commit
復原事務:
rollback;
多版本並發控制(Multiversion ConcurrencyControll MVCC)
第一點:
MVCC並不是MySql專屬的,Oracle,PostgreSQL等都在使用。
MVCC並沒有簡單地使用行鎖,而是使用“行層級鎖”(row-level locking)。MVCC的基本原理是:
在事務中儲存資料的快照,這意味著在一個事物裡能夠看到資料一致的視圖,而不用擔心這個事務運行多長時間,同時也意味著在同一個時刻不同事務看到的相同表裡的資料可能是不同的。
MVCC的基本特徵:
· 每行資料都存在一個版本,每次資料更新時都更新該版本
· 修改時Copy出目前的版本隨意修改,個事務之間無幹擾
· 儲存時比較版本號碼,如果成功(commit),則覆蓋原記錄;失敗則放棄copy(rollback)
InnoDB儲存引擎MVCC的實現策略:
在每一行資料中額外儲存兩個隱藏欄位:當前行建立時的版本號碼和刪除時的版本號碼(可能為空白)。每個事務又有自己的版本號碼,這樣事務內執行CRUD操作時,就通過版本號碼的比較來達到資料版本控制的目的。具體做法見下面的。
---------------------------------------------------------
公眾號“程式員之路”,路漫漫其修遠兮,吾將上下而求索!
輕輕按住下面的它,讓我們結伴,共同成長!
SQL事務的四種隔離等級和MySQL多版本並發控制