總結
資料庫在并發的情況下,可能會出現:
- 髒讀
- 不可重複讀 --> 原因:UPDATE操作
- 幻讀 --> 原因:INSERT/DELETE操作
為了避免以上問題,資料庫事務增加隔離級别,來保證資料的準确性。隔離級别從低到高有4個級别:
- 讀未送出 Read uncommitted
- 讀送出(不可重複讀)Read committed
- 重複讀 Repeatable read
- 序列化 Serializable

值得一提的是:大多數資料庫預設的事務隔離級别是Read committed,比如Sql Server , Oracle。Mysql的預設隔離級别是Repeatable read。
一、并發問題
1、髒讀
事務T1正在操作一條資料,此時事務T2擷取該條資料紀錄,如果T1異常,事務復原,T2讀取到的資料就是髒資料,這種現象稱為髒讀。
2、不可重複讀
事務T1多次讀取某條記錄,在讀取間隔中,事務T2更新了該技術的資料,當T1再次讀取該記錄時,擷取到的資料不一緻,這種現象稱為不可重複讀。産生的原因主要是資料的更新。
3、幻讀
事務T1批量處理多條記錄,此時事務T2新增或删除了一條或多條記錄,當T1處理完成,查詢處理結果,會發現有記錄沒有處理(T2新增的)或者發現記錄少了(T2删除的),會有一種幻覺的感覺,這種現象稱為幻讀。主要是資料的新增或删除導緻。
二、隔離級别
1、讀未送出(Read uncommitted)
①定義:就是一個事務讀取到其他事務未送出的資料,是級别最低的隔離機制。
②缺點:會産生髒讀、不可重複讀、幻讀。
③髒讀案例:老闆要給程式員發工資,程式員的工資是3.6萬/月。但是發工資時老闆不小心按錯了數字,按成3.9萬/月,該資料已經儲存了,但是事務還沒有送出。就在這時,程式員去檢視自己這個月的工資,發現比往常多了3千元,以為漲工資了非常高興。但是老闆及時發現了不對,馬上復原差點就送出了的事務,将數字改成3.6萬再送出。分析——> 實際程式員這個月的工資還是3.6萬,但是程式員看到的是3.9萬。他看到的是老闆還沒送出事務時的資料。這就是髒讀。
④解決方案:采用更進階的隔離機制,如讀送出。
2、讀送出-不可重複讀(Read committed)
①定義:就是一個事務讀取到其他事務送出後的資料。Oracle預設隔離級别。
②缺點:會産生不可重複讀、幻讀。
③不可重複讀案例:程式員拿着信用卡去享受生活(卡裡當然是隻有3.6萬),當他埋單時(程式員事務開啟),收費系統事先檢測到他的卡裡有3.6萬(第一次讀),就在這個時候!!程式員的妻子要把錢全部轉出充當家用,并送出。當收費系統準備扣款時,再檢測卡裡的金額(第二次讀),發現已經沒錢了(第二次檢測金額當然要等待妻子轉出金額事務送出完)。程式員就會很郁悶,明明卡裡是有錢的…分析——>這就是讀送出,若有事務對資料進行更新(UPDATE)操作時,讀操作事務要等待這個更新操作事務送出後才能讀取資料,可以解決髒讀問題。但在這個事例中,出現了一個事務範圍内兩個相同的查詢卻傳回了不同資料,這就是不可重複讀。
④解決方案:采用更進階的隔離機制,如可重複讀。
3、可重複讀(Repeatable read)
0.解決不可重複讀案例:程式員拿着信用卡去享受生活(卡裡當然是隻有3.6萬),當他埋單時(事務開啟,不允許其他事務的UPDATE修改操作),收費系統事先檢測到他的卡裡有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就可以扣款了。分析——>重複讀可以解決不可重複讀問題。寫到這裡,應該明白的一點就是,不可重複讀對應的是修改,即UPDATE操作。但是可能還會有幻讀問題。因為幻讀問題對應的是插入INSERT操作,而不是UPDATE操作。
①定義:就是一個事務對同一份資料讀取到的相同,不在乎其他事務對資料的修改。MySQL預設的隔離級别。
②缺點:會産生幻讀。
③幻讀案例:程式員某一天去消費,花了2千元,然後他的妻子去檢視他今天的消費記錄(全表掃描FTS,妻子事務開啟),看到确實是花了2千元,就在這個時候,程式員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,并送出。當妻子列印程式員的消費記錄清單時(妻子事務送出),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。。
④解決方案:采用更進階的隔離機制,序列化。