文章已收錄Github精選,歡迎Star: https://github.com/yehongzhi/learningSummary
髒讀、不可重複讀、幻讀
在現代關系型資料庫中,事務機制是非常重要的,假如在多個事務并發操作資料庫時,如果沒有有效的機制進行避免就會導緻出現髒讀,不可重複讀,幻讀。
髒讀
1、在事務A執行過程中,事務A對資料資源進行了修改,事務B讀取了事務A修改後的資料。
2、由于某些原因,事務A并沒有完成送出,發生了RollBack操作,則事務B讀取的資料就是髒資料。
這種讀取到另一個事務未送出的資料的現象就是髒讀(Dirty Read)。

不可重複讀
事務B讀取了兩次資料資源,在這兩次讀取的過程中事務A修改了資料,導緻事務B在這兩次讀取出來的資料不一緻。
這種在同一個事務中,前後兩次讀取的資料不一緻的現象就是不可重複讀(Nonrepeatable Read)。
幻讀
事務B前後兩次讀取同一個範圍的資料,在事務B兩次讀取的過程中事務A新增了資料,導緻事務B後一次讀取到前一次查詢沒有看到的行。
幻讀和不可重複讀有些類似,但是幻讀強調的是集合的增減,而不是單條資料的更新。
第一類更新丢失
事務A和事務B都對資料進行更新,但是事務A由于某種原因事務復原了,把已經送出的事務B的更新資料給覆寫了。這種現象就是第一類更新丢失。
第二類更新丢失
其實跟第一類更新丢失有點類似,也是兩個事務同時對資料進行更新,但是事務A的更新把已送出的事務B的更新資料給覆寫了。這種現象就是第二類更新丢失。
事務隔離級别
為了解決以上的問題,主流的關系型資料庫都會提供四種事務的隔離級别。事務隔離級别從低到高分别是:讀未送出、讀已送出、可重複讀、串行化。事務隔離級别等級越高,越能保證資料的一緻性和完整性,但是執行效率也越低。是以在設定資料庫的事務隔離級别時需要做一下權衡,MySQL預設是可重複讀的級别。
讀未送出
讀未送出(Read Uncommitted),是最低的隔離級别,所有的事務都可以看到其他未送出的事務的執行結果。隻能防止第一類更新丢失,不能解決髒讀,可重複讀,幻讀,是以很少應用于實際項目。
讀已送出
讀已送出(Read Committed), 在該隔離級别下,一個事務的更新操作結果隻有在該事務送出之後,另一個事務才可能讀取到同一筆資料更新後的結果。可以防止髒讀和第一類更新丢失,但是不能解決可重複讀和幻讀的問題。
可重複讀
可重複讀(Repeatable Read),MySQL預設的隔離級别。在該隔離級别下,一個事務多次讀同一個資料,在這個事務還沒結束時,其他事務不能通路該資料(包括了讀寫),這樣就可以在同一個事務内兩次讀到的資料是一樣的。可以防止髒讀、不可重複讀、第一類更新丢失、第二類更新丢失的問題,不過還是會出現幻讀。
串行化
串行化(Serializable),這是最高的隔離級别。它要求事務序列化執行,事務隻能一個接着一個地執行,不能并發執行。在這個級别,可以解決上面提到的所有并發問題,但可能導緻大量的逾時現象和鎖競争,通常不會用這個隔離級别。
總結
下面我們對事務的隔離級别和對并發問題的解決情況,請看下圖:
這篇文章就講到這裡了,感謝大家的閱讀,希望看完大家能有所收獲!
我是一個努力讓大家記住的程式員。我們下期再見!!!
能力有限,如果有什麼錯誤或者不當之處,請大家批評指正,一起學習交流!