1.丟失更新
A事務撤銷時,把已經提交的B事務的更新數據覆蓋了。
2.臟讀
臟讀發生在一個事務A讀取了被另一個事務B修改,但是還未提交的數據。
假如B回退,則事務A讀取的是無效的數據。
3.不可重復讀
指在一個事務A內,多次讀同一個數據,但是事務A沒有結束時,另外一個事務B則修改了該數據。
那么事務A在 B事務修改數據之后再次讀取該數據, A事務讀到的數據可能和第一次讀到的數據不一樣。
這就發生了在一個事務內兩次讀到的數據不一樣,這就被稱作不可重復讀。
幻讀 (針對insert,delete操作)
幻讀發生在當兩個完全相同的查詢執行時,第二次查詢所返回的結果集跟第一個查詢不相同。
隔離級別
Read UnCommitted(讀未提交) - 解決丟失更新
最低的隔離級別。一個事務可以讀取另一個事務並未提交的更新結果。
Read Committed(讀提交) - 解決丟失更新,臟讀
大部分數據庫采用的默認隔離級別。一個事務的更新操作結果只有在該事務提交之后,另一個事務才可以的讀取到同一筆數據更新后的結果。
Repeatable Read(重復讀) - 解決丟失更新,臟讀,不可重復讀
mysql的默認級別。整個事務過程中,對同一筆數據的讀取結果是相同的,不管其他事務是否在對共享數據進行更新,也不管更新提交與否。
Serializable(序列化) - 解決丟失更新,臟讀,不可重復讀,幻讀
最高隔離級別。所有事務操作依次順序執行。注意這會導致並發度下降,性能最差。通常會用其他並發級別加上相應的並發鎖機制來取代它。
解決上述數據操作不一致的問題,數據庫通過鎖機制來解決。按鎖對象來分分為行級鎖和表級鎖;根據並發事務鎖定的關系上看:分為共享鎖和獨占鎖。為了更改數據,數據庫必須在進行更改的行上施加行獨占鎖定,一般的insert update delete都會隱式采用必要的行鎖定。基於鎖機制,數據庫面提供了4級事務隔離級別,用戶只需要設置事務的隔離級別,就會分析事務的sql語句並自動選擇合適的鎖。值得注意的是,隔離級別越高,數據庫的並發性能越差,即事務的隔離級別與數據庫的並發性能成負相關關系。
隔離級別具體具體內容如下圖所示:
不可重復讀和幻讀的區別已經如何解決
不可重復讀:A事務在執行過程中,B事務對數據進行了修改或刪除,導致A兩次讀取的數據不一致;
重點在於update和delete(鎖行即可解決),
幻讀:A事務在執行過程中,B事務新增了符合A事務要查詢的數據,導致A兩次讀取的數據不一致;
重點在於insert(需要鎖表解決)。
如果使用鎖機制來實現這兩種隔離級別,在可重復讀中,該sql第一次讀取到數據后,就將這些數據加鎖,其它事務無法修改這些數據,就可以實現可重復讀了。但這種方法卻無法鎖住insert的數據,所以當事務A先前讀取了數據,或者修改了全部數據,事務B還是可以insert數據提交,這時事務A就會發現莫名其妙多了一條之前沒有的數據,這就是幻讀,不能通過行鎖來避免。需要Serializable隔離級別 ,讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,這么做可以有效的避免幻讀、不可重復讀、臟讀等問題,但會極大的降低數據庫的並發能力。
所以說不可重復讀和幻讀最大的區別,就在於如何通過鎖機制來解決他們產生的問題。