MySQL事務隔離

ahiru?發表於2019-02-19

事務的基本屬性(ACID):

  • 原子性(Atomicity):事務是一個原子單位,要麼全部執行,要麼全部不執行
  • 一致性(Consistency):事務開始前和結束後,資料庫的完整性約束沒有被破壞。
  • 隔離性(Isolation):併發的事務是相互隔離的。
  • 永續性(Durability):事務完成後,該事務所對資料庫所做的更改持久的儲存在資料庫之中,並不會被回滾。

事務的併發問題:

髒讀:讀取了未提交的資料。例如事務1修改某個欄位的值,但未commit到資料庫,然後事務2讀取了該值,後來事務1撤銷了對該欄位的更新或者是更改該欄位的值才commit到資料庫。這樣事務2讀到的就是髒資料。

不可重複讀:在資料庫訪問中,一個事務範圍內的兩次相同的查詢卻返回了不同的資料。例如事務1讀取了某一資料,事務2讀取並修改了該資料,事務1為了對讀取值進行驗證而重新讀取,卻得到了不同的結果。

幻讀:事務1對錶中的資料進行修改,修改涉及了表中全部的資料行。同時,事務2想這個表插入了一行新資料。操作事務1的使用者就會發現表中還有沒有修改的資料行,彷彿出現了幻覺一樣。

MySQL事務隔離級別

MySQL事務隔離

MySQL預設的事務隔離級別為repeatable read(可重複讀)。

讀未提交

事務的最低隔離級別,在這種隔離級別下,一個事務可以讀取另一個事務未提交的資料。

例子:事務1設定隔離級別為讀未提交,查詢user表資料。

MySQL事務隔離

事務2設定隔離級別為讀未提交,修改user表id為1的score。

MySQL事務隔離

事務1能夠查詢到事務2修改的資料。

MySQL事務隔離

事務2對錶進行了回滾,撤銷修改。

MySQL事務隔離

事務1不知道事務2進行了回滾,此時事務1讀到的資料為髒資料。然後事務1對錶資料進行了修改。在事務1看來 score 應該為 60+50=110,但是修改後操作為60,資料不一致。

MySQL事務隔離

讀已提交

在一個事務修改資料過程中,如果該事務還沒提交,其他事務不能讀取該資料。

例子:事務2對錶中的資料進行修改,並提交。

MySQL事務隔離

事務1對錶的兩次查詢資料不一致,即產生了不可重複讀的問題。

MySQL事務隔離

在事務2修改表中資料但又未提交事務時,mysql對該欄位增加了x鎖,事務1不可修改資料。直到事務2提交事務後,事務1才能對該欄位進行修改。

MySQL事務隔離

可重複讀

在同一個事務內的查詢都是事務開始時刻一致的。

例子:事務1設定隔離級別為repeatable read,並查詢資料。

MySQL事務隔離

事務2設定隔離級別,更改資料並提交。

MySQL事務隔離

事務1再次查詢表資料,表資料不變。解決了不可重複讀問題,但不能解決幻讀

MySQL事務隔離

序列化

事務每次讀操作都需要獲得表級共享鎖,讀寫相互都會阻塞。

例子:事務1查詢表資料

MySQL事務隔離

事務2對錶資料可讀,但不可讀寫。因此不會出現幻讀的情況。

MySQL事務隔離

總結:

  1. 隔離級別為讀可提交時,寫資料會鎖住相應的行。
  2. 隔離級別為可重複讀時,如果檢索條件有索引(包括主鍵索引)的時候,預設加鎖方式是next-key 鎖;如果檢索條件沒有索引,更新資料時會鎖住整張表。一個間隙被事務加了鎖,其他事務是不能在這個間隙插入記錄的,這樣可以防止幻讀。
  3. 隔離級別為序列化時,讀寫資料都會鎖住整張表。

參考資料:

MySQL的四種事務隔離級別

MySQL 四種事務隔離級的說明


相關文章