注:不可重複度和幻讀很類似,很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住知足條件的行,解決幻讀須要鎖表。mysql
事務隔離級別 | 髒讀 | 不可重複度 | 幻讀 |
---|---|---|---|
讀未提交(read-uncommitted) | 是 | 是 | 是 |
不可重複讀(read-committed) | 否 | 是 | 是 |
可重複讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
mysql 默認的事務隔離級別是repeatable-readsql
select @@tx_isolation;
能夠經過上述的命令查看mysql當前的事務隔離級別數據庫
set session transaction isolation level read committed;
上述命令能夠設置事務隔離級別session
-(忽略背景顏色哈)這時候咱們能夠發現,事務A的hahah的值也被修改了,也就是說事務A能夠查詢到事務B已經更新的數據,若是這時候事務B因爲某種緣由回滾了,全部的操做將會被銷燬,那麼事務A查詢到的數據就是髒數據。若是在這時候事務A執行了update peter_test1 set score=score-10 where id=1
的話,其實hahah的score也是爲83,而不是73,由於事務B回滾了,可是其餘的應用並不知道。因此解決這種問題的辦法就是採用不可重複讀(讀已提交,read-committed)併發
事務A和事務B都設置好性能
這時候咱們回來看看事務A學習
這時候的事務B未提交,事務A不能查詢到事務B已經更新的數據,這就解決了髒讀的問題spa
下面咱們來看看可重複讀code
由上圖能夠知道,儘管在事務B中提交了事務,可是在事務A的兩次查詢中的數據仍是同樣的。這就是能夠重複讀的效果,可是若是你在事務A中執行了update peter_test1 set score=score-10 where id=1;
的話,hahah的數據並非變成了73,而是變成了63,由於事務B在提交事務以後數據已經變成了73。 事務
可重複讀的隔離級別系愛是用了MVCC機制,A事務讀取的是記錄的快照版本,而非最新版本,B事務的更新是建立了一個新的版原本更新,不一樣的事務的讀和寫是分離的。(我也不是很清楚其中的意思,這不是我要了解的重點,日後再來學習哈)
下面咱們來看看串行化(serializable)
在事務A從新計算總數時,由於把事務B最新提交新增的值也給算進去了,因此兩次的計算結果是不同的。這就產生了幻讀。「串行化」是解決幻讀的一種方法
由圖中咱們能夠看到,事務B並無執行生效
因此能夠看到事務B在事務A執行完成以後,也就執行完成了。這也避免了幻讀的狀況
mysql中事務隔離級別爲serializable時會鎖表,所以不會出現幻讀的狀況,這種隔離級別的併發性極低,開發中不多會用到。
注意:隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也很大,對於大多數的應用程序,能夠優先考慮把數據庫的隔離級別設爲read-committed,它可以避免讀取髒數據,並且具備較好的併發性能,儘管他會致使不可重複讀,幻讀這些併發問題,可是在可能出現這種問題的個別場所,能夠又應用程序採用悲觀鎖或者樂觀鎖來控制