mysql事務的隔離級別及原理實現和spring的事務隔離級別.

事務隔離級別介紹

隔離級別 髒讀 不可重複讀 幻讀
未提交讀(Read uncommitted) 可能 可能 可能
已提交讀(Read committed) 不可能 可能 可能
可重複讀(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能


Read uncommitted 讀未提交
公司發工資了,把50000元打到我的賬號上,但是該事務並未提交,而我正好去查看賬戶,發現工資已經到賬,是50000元整,非常高興。可是不幸的是,領導發現發給的工資金額不對,是2000元,於是迅速回滾了事務,修改金額後,將事務提交,最後我實際的工資只有2000元,空歡喜一場。
髒讀是兩個併發的事務,“事務A:領導發工資”、“事務B:我查詢工資賬戶”,事務B讀取了事務A尚未提交的數據。
當隔離級別設置爲Read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。

原理

  • 事務對當前被讀取的數據不加鎖;
  • 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放。

 

表現:

事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,能讀到事務2對該記錄的修改版本,即使該修改尚未被提交。 事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。


Read committed 讀提交
我拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時老婆也正好在網上轉賬,把工資卡的2000元轉到她賬戶,並在我之前提交了事務,當我扣款時,系統檢查到工資卡已經沒有錢,扣款失敗,十分納悶,明明卡里有錢,爲何......
不可重複讀是兩個併發的事務,“事務A:消費”、“事務B:老婆網上轉賬”,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
當隔離級別設置爲Read committed時,避免了髒讀,但是可能會造成不可重複讀。

實現

  • 事務對當前被讀取的數據加 行級共享鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共享鎖;
  • 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

表現:

  • 事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的只能是事務2對其更新前的版本,要不就是事務2提交後的版本。
  • 事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。

 


Repeatable read 重複讀
當隔離級別設置爲Repeatable read時,可以避免不可重複讀。當我拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),我老婆就不可能對該記錄進行修改,也就是不能在此時轉賬。
雖然Repeatable read避免了不可重複讀,但還有可能出現幻讀。例如:老婆工作在銀行部門,她時常通過銀行內部系統查看我的信用卡消費記錄。有一天,她正查詢到我當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)爲80元,而我此時正好在外面喫完大餐後在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後老婆將我的當月信用卡消費的明細打印到A4紙上,卻發現消費總額爲1080元,老婆很詫異,以爲出現了幻覺,幻讀就這樣產生了。

原理

  • 事務在讀取某數據的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放;
  • 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

表現:

  • 事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的仍然是第一次讀取的那個版本。
  • 事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。


Serializable (串行化):

可避免髒讀、不可重複讀、幻讀的發生

原理

  • 事務在讀取數據時,必須先對其加 表級共享鎖 ,直到事務結束才釋放;
  • 事務在更新數據時,必須先對其加 表級排他鎖 ,直到事務結束才釋放。

表現:

  • 事務1正在讀取A表中的記錄時,則事務2也能讀取A表,但不能對A表做更新、新增、刪除,直到事務1結束。
  • 事務1正在更新A表中的記錄時,則事務2不能讀取A表的任意記錄,更不可能對A表做更新、新增、刪除,直到事務1結束。

 

 

spring的事務隔離級別.

 

1、isolation_default

使用數據庫默認的事務隔離級別

2、isolation_read_uncommitted

允許讀取尚未提交的修改,可能導致髒讀、幻讀和不可重複讀

3、isolation_read_committed

允許從已經提交的事務讀取,可防止髒讀、但幻讀,不可重複讀仍然有可能發生

4、isolation_repeatable_read

對相同字段的多次讀取的結果是一致的,除非數據被當前事務自生修改。可防止髒讀和不可重複讀,但幻讀仍有可能發生

5、isolation_serializable

完全服從acid隔離原則,確保不發生髒讀、不可重複讀、和幻讀,但執行效率最低。

幾種常用數據庫的默認隔離級別

MySQL

mysql默認的事務處理級別是'REPEATABLE-READ',也就是可重複讀。

Oracle

oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。

默認系統事務隔離級別是READ COMMITTED,也就是讀已提交。

SQL Server

默認系統事務隔離級別是read committed,也就是讀已提交

 

髒數據,髒讀,不可重複讀,幻覺讀


 髒讀: 指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個            數據,然後使用了這個數據。因爲這個數據是還沒有提交的數據, 那麼另外一個事務讀到的這個數據是髒數據,依據髒數據            所做的操作可能是不正確的。
   
不可重複讀: 指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。
                    那麼,在第一個事務中的兩次讀數據之間,由於第二個事務的修改,那麼第一個事務兩次讀到的數據
                    可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱爲是不可重複讀。
           
 幻覺讀: 指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及
              到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,
              以後就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章