MySQL隔離等級,mysql隔離
1. read uncommitted,讀未提交。事務A能讀取到事務B已修改但未提交的資料。髒讀
2. read committed,讀已提交。事務A只能讀取到事務B已經提交的資料,但由於事務讀取到的是它每次SELECT前的資料快照,因此同一事務多次SELECT的結果可能不同。不可重複讀取。大多數關聯式資料庫(如Oracle)的預設隔離等級
3. repeatable read,可重複讀。事務A只能讀取到事務B已經提交的資料,且同一事務每次讀取到的資料均相同。這是因為事務讀取到的是事務開始時的資料快照,同一事務中只有一份且保持不變直到事務結束。但是,由於資料快照產生於事務開始時,若不同事務已修改而未提交的資料存在衝突(主鍵/唯一鍵衝突等),則後執行修改的事務會被掛起直到先執行修改的事務提交,但讀取不到造成衝突的資料,即幻讀
例如:表T有唯一鍵UK,事務A先向T插入UK=x但不提交,事務B再向T插入UK=x,此時事務B會被掛起;若事務A提交,此時事務B會因為唯一鍵衝突而報錯;若事務A刪除UK=x後提交,此時事務B的插入操作會成功;然而直到事務B提交之前,它都SELECT不到由事務A插入的UK=x。這是MySQL的預設隔離等級
4. serializable,序列化。事務必須串列執行,完全隔離
綜上:
首先,隔離等級是針對事務的SELECT操作而言的
其次,隔離等級是按照不隔離(髒讀)=>不可重複讀取=>可重複讀但存在幻讀=>完全序列化(禁用並發,解決幻讀),逐步加強隔離的程度的
另:
網上對幻讀的理解存在很多錯誤的地方。如:
有些文章引用《高效能MySQL》中所講,MySQL的InnoDB引擎通過MVCC(多版本並發控制)在repeatable read級就已解決了幻讀的問題。實際是錯誤的,MVCC採用類似樂觀鎖的機制從原理上就無法解決幻讀,同時從上面的例子中也可以看出,幻讀問題在repeatable read級並未解決
有些文章採用了類似這樣的描述:當事務(A)讀取了一定範圍的資料後,另一個事務(B)在這個範圍中插入一些資料,當原事務(A)在這個範圍內更新資料的時候,就會“驚奇”地發現這些資料,如同“幻影”一般。這種描述很模糊,什麼叫“驚奇”,什麼叫“幻影”?結合前面所舉的例子可以看出,事務A之所以會“驚奇”地感知到這些資料,是因為它SELECT不到這些由事務B更新的資料,但這些資料會影響到A的操作,如同“幻影”一樣,看不到它,但它卻已經存在
最後,總結一下便於記憶,對於事務而言:
“讀未提交”是指不管其它事務是否提交都能讀到它們的資料
“讀已提交”是指只有當其它事務提交之後才能讀到它們的資料
“可重複讀”是指只有當自己提交了之後才能讀到其它事務提交的資料
“序列化”是指事務逐個執行,當前事務提交之前,其它都被掛起