Mysql的隔離級別

Mysql的隔離級別

事務的基本要素

  1. 原子性(Atomicity):咱們學過化學,咱們知道,原子是構成物質的基本單位。放在Mysql的事務中,咱們能夠理解爲,一個事務要麼所有執行,要不所有不執行,不存在說一個事務中部分語句執行成功,部分語句執行不成功,存在不成功的語句將會所有回滾,全部語句看成是沒有執行過同樣。
  2. 一致性(Consistency):表示說事務的開始以前和開始以後,數據庫的完整性約束是沒有被破壞的,好比A要向B轉錢,不存在說A已經扣了款,B尚未收到款
  3. 持久性(Durability):事務完成以後,事務對數據庫所作的修改將所有保存在數據庫中。
  4. 隔離性(Isolation):表示在同一個時間內,只能有一個事務請求同一個數據,不一樣的事務之間彼此沒有任何干擾,就好比說事務A正在向銀行取錢,在A取錢的過程結束前,事務B不能向這張卡轉錢。

事務的併發問題

  1. 髒讀:表示說一個事務A讀取了事務B更新的數據,可是B發生錯誤回滾了,那麼A讀到的數據就是髒數據
  2. 不可重複讀:事務A屢次讀取同一數據,在此過程當中,事務B對這一數據進行了更改,所以事務A屢次讀取同一數據時,結果不一致
  3. 幻讀:表示當一個事務A屢次讀取一張分數表的總數時,事務B在這時候新增了一條分數,致使事務A兩次讀取的總數不一致。

注:不可重複度和幻讀很類似,很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住知足條件的行,解決幻讀須要鎖表。mysql

事務的隔離級別

事務隔離級別 髒讀 不可重複度 幻讀
讀未提交(read-uncommitted)
不可重複讀(read-committed)
可重複讀(repeatable-read)
串行化(serializable)

例子

mysql 默認的事務隔離級別是repeatable-readsql

select @@tx_isolation;

能夠經過上述的命令查看mysql當前的事務隔離級別數據庫

set session transaction isolation level read committed;

上述命令能夠設置事務隔離級別session

clipboard.png

讀未提交(read-uncommitted)
  • 開啓事務A,並查詢表數據

clipboard.png

  • 另外開啓事務B,並對ID爲1的hahah進行修改。

clipboard.png

  • 能夠看到事務B已經修改,可是事務還沒提交,這時候咱們回去事務A看看。

clipboard.png

-(忽略背景顏色哈)這時候咱們能夠發現,事務A的hahah的值也被修改了,也就是說事務A能夠查詢到事務B已經更新的數據,若是這時候事務B因爲某種緣由回滾了,全部的操做將會被銷燬,那麼事務A查詢到的數據就是髒數據。若是在這時候事務A執行了update peter_test1 set score=score-10 where id=1的話,其實hahah的score也是爲83,而不是73,由於事務B回滾了,可是其餘的應用並不知道。因此解決這種問題的辦法就是採用不可重複讀(讀已提交,read-committed)併發

  • 開啓不可重複讀

clipboard.png

事務A和事務B都設置好性能

  • 查看事務A的數據

clipboard.png

  • 修改事務B可是未提交

clipboard.png

這時候咱們回來看看事務A學習

clipboard.png

這時候的事務B未提交,事務A不能查詢到事務B已經更新的數據,這就解決了髒讀的問題spa

  • 提交事務B

clipboard.png

下面咱們來看看可重複讀code

  • 開啓事務,並設置當前事務模式爲repeatable read

clipboard.png

  • 事務A中查詢數據

clipboard.png

  • 在事務B中修改數據,並提交

clipboard.png

  • 查看事務A的數據

clipboard.png

由上圖能夠知道,儘管在事務B中提交了事務,可是在事務A的兩次查詢中的數據仍是同樣的。這就是能夠重複讀的效果,可是若是你在事務A中執行了update peter_test1 set score=score-10 where id=1;的話,hahah的數據並非變成了73,而是變成了63,由於事務B在提交事務以後數據已經變成了73。 事務

clipboard.png

可重複讀的隔離級別系愛是用了MVCC機制,A事務讀取的是記錄的快照版本,而非最新版本,B事務的更新是建立了一個新的版原本更新,不一樣的事務的讀和寫是分離的。(我也不是很清楚其中的意思,這不是我要了解的重點,日後再來學習哈)

下面咱們來看看串行化(serializable)

  • 我想要去計算整張表的score總數

clipboard.png

  • 在事務B開始以後,新增一條數據,其中score爲100,並提交

clipboard.png

  • 在事務A中從新計算整張表的score總數

clipboard.png

在事務A從新計算總數時,由於把事務B最新提交新增的值也給算進去了,因此兩次的計算結果是不同的。這就產生了幻讀。「串行化」是解決幻讀的一種方法

  • 設置當前事務模式爲serializable。

clipboard.png

  • 在事務A開始計算的時候,事務B新增數據

clipboard.png

由圖中咱們能夠看到,事務B並無執行生效

  • 咱們提交事務A

clipboard.png

  • 查看事務B

clipboard.png

因此能夠看到事務B在事務A執行完成以後,也就執行完成了。這也避免了幻讀的狀況

mysql中事務隔離級別爲serializable時會鎖表,所以不會出現幻讀的狀況,這種隔離級別的併發性極低,開發中不多會用到。

注意:隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也很大,對於大多數的應用程序,能夠優先考慮把數據庫的隔離級別設爲read-committed,它可以避免讀取髒數據,並且具備較好的併發性能,儘管他會致使不可重複讀,幻讀這些併發問題,可是在可能出現這種問題的個別場所,能夠又應用程序採用悲觀鎖或者樂觀鎖來控制

相關文章
相關標籤/搜索