MySQL髒讀、不可重複讀、幻讀
事務的特性:
- 原子性:指處於同一個事務中的多條語句是不可分割的。
- 一致性:事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。比如轉賬,轉賬前兩個賬戶餘額之和為2k,轉賬之後也應該是2K。
- 隔離性:指多執行緒環境下,一個執行緒中的事務不能被其他執行緒中的事務打擾
- 永續性:事務一旦提交,就應該被永久儲存起來。
事務隔離性問題:
如果不考慮事務的隔離性,會出現以下問題:
- 髒讀:指一個執行緒中的事務讀取到了另外一個執行緒中未提交的資料。
- 不可重複讀(虛讀):指一個執行緒中的事務讀取到了另外一個執行緒中提交的update的資料。
- 幻讀:指一個執行緒中的事務讀取到了另外一個執行緒中提交的insert的資料。
隔離級別:
隔離級別 | 髒讀(Dirty Read) | 不可重複讀(NonRepeatable Read) | 幻讀(Phantom Read) |
---|---|---|---|
未提交讀(Read uncommitted) | 可能 | 可能 | 可能 |
已提交讀(Read committed) | 不可能 | 可能 | 可能 |
可重複讀(Repeatable read) | 不可能 | 不可能 | 可能 |
可序列化(Serializable ) | 不可能 | 不可能 | 不可能 |
級別越高,資料越安全,但效能越低。
不可重複讀與幻讀比較相似,都是在一個事務中多次讀取到不同的資料。網路上的總結如下:
不可重複讀:所謂的虛讀,也就是大家經常說的不可重複讀,是指在資料庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一資料,事務T2讀取並修改了該資料,T1為了對讀取值進行檢驗而再次讀取該資料,便得到了不同的結果。
一種更易理解的說法是:在一個事務內,多次讀同一個資料。在這個事務還沒有結束時,另 一個事務也訪問該同一資料。那麼,在第一個事務的兩次讀資料之間。由於第二個事務的修改,那麼第一個事務讀到的資料可能不一樣,這樣就發生了在一個事務內 兩次讀到的資料是不一樣的,因此稱為不可重複讀,即原始讀取不可重複。
所謂幻讀,是指事務A讀取與搜尋條件相匹配的若干行。事務B以插入或刪除行等方式來修改事務A的結果集,然後再提交。
幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,比如這種修改涉及到表中的“全部資料行”。同時,第二個事務也 修改這個表中的資料,這種修改是向表中插入“一行新資料”。那麼,以後就會發生操作第一個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一 樣.一般解決幻讀的方法是增加範圍鎖RangeS,鎖定檢鎖範圍為只讀,這樣就避免了幻讀。簡單來說,幻讀是由插入或者刪除引起的。
大致的區別在於不可重複讀是由於另一個事務對資料的更改所造成的,而幻讀是由於另一個事務插入或刪除引起的。
不可重複讀(虛讀)和幻讀的差別:
從總的結果來看, 似乎兩者都表現為兩次讀取的結果不一致.
但如果你從控制的角度來看, 兩者的區別就比較大:
對於前者, 只需要鎖住滿足條件的記錄
對於後者, 要鎖住滿足條件及其相近的記錄