mysql事務詳解-4種事務隔離級別該怎麼選擇

mysql事務詳解-4種事務隔離級別該怎麼選擇

事務要保證ACID,其中就有隔離性。

當我們有多個事務在執行的時候,如果保證每個事務都是隔離的,而不是數據混亂的呢?sql標準的四種隔離級別如下:

  • 讀未提交 RU(Read Uncommitted),在這個級別下,是所有數據共享的,A事務在執行的任何操作,B事務都能看見,不管有沒有提交。
  • 讀已提交 RC(Read Committed),在這個級別下,只有A事務提交的數據,B事務才能看見。提交前的數據對其他事務是不可見的。
  • 可重複讀 RR(Repeatable Read),在這個級別下,一個事務內讀取的數據都是重複的,也就是都是一致的,就算別的事務提交了數據,你讀取的還是原來的數據。
  • 串行化 (serializable), 對於同一行記錄,寫會加寫鎖,讀會加讀鎖。

事務隔離的原理

這些是怎麼做到的呢?因爲事務是具備回滾功能的,如果一旦事務出錯就會回滾整個事務。

用過github的應該都知道,github上的代碼是具備回滾功能的,如果上線之後發現bug,會回滾到上一個版本,github就是基於版本控制的。

事務同樣是基於版本控制的。有一個undo log回滾日誌來記錄這些版本。比如對於一行用戶數據:

{id: 1, name: 張三, mobile:13245678976, pwd: 123456}

事務1進行了修改手機號操作,這時候還沒有提交。數據庫就會有兩個版本的數據。這些都記錄在undo log裏面,這也就是所謂的MVCC的概念。

{id: 1, name: 張三, mobile:13245678976, pwd: 123456} 原始版本
{id: 1, name: 張三, mobile:12322223333, pwd: 123456} 事務1版本

事務2同時啓動,但是稍後進行查詢操作,獲取用戶信息,如果你是讀未提交級別,那麼讀取的是事務1版本數據:

{id: 1, name: 張三, mobile:12322223333, pwd: 123456} 事務1版本

如果你是其他級別,那麼你讀取的是原始版本數據:

{id: 1, name: 張三, mobile:13245678976, pwd: 123456} 原始版本

如果事務1已經提交了修改,那麼事務2在讀已提交級別下獲取的也是事務1版本數據。

這個是怎麼判斷的呢?

每個事務有自己的事務id,這個id是單調遞增的。在每行數據的版本上會記錄事務id。在事務啓動的時候,會維護一個已經啓動但沒有提交的事務的有序數組。有序也就是從小到大,排好序了。如果事務id小於這個數組中第一個id,那麼這個事務一定是一個已經提交的事務。如果事務id大於這個數組,那麼這個事務是在我之後啓動的事務。如果事務id在這個數組中,那麼他在我啓動的時候一定是未提交的。

拿上面的數據舉例,原始版本的事務id爲100,事務1的事務id爲101,事務2的事務id爲102。

{id: 1, name: 張三, mobile:13245678976, pwd: 123456} 原始版本 100
{id: 1, name: 張三, mobile:12322223333, pwd: 123456} 事務1版本 101

當事務2啓動後,事務數組爲[101],假設這時候事務1未提交。

如果是可重複讀級別下,那麼當查詢到最新版本事務id=101,在數組中,那麼不可見,接着查詢上一個版本,上一個版本事務id = 100,發現小於數組最小值,那麼這個值是正確的,取出這個版本的數據。

這樣就算後面有事務提交,但是它提交後的版本的事務id不滿足要求,那麼查看到的數據永遠都是同一個版本的數據,這也就是一致性讀

但是如果你在事務2中先更新了密碼再執行查詢,那麼就會有三個版本的數據

{id: 1, name: 張三, mobile:13245678976, pwd: 123456} 原始版本 100
{id: 1, name: 張三, mobile:12322223333, pwd: 123456} 事務1版本 101
{id: 1, name: 張三, mobile:12322223333, pwd: 123456789} 事務2版本 102

這時候查詢,事務數組爲[101,102]。

再可重複讀級別下,查詢到最新數據事務id=102,發現和自己的一樣,那麼是可見的。因爲是自己修改的,自己修改的不能不讓自己看到啊,所以這時候查詢到的數據會是最新數據。這也就是當前讀

可重複讀級別和讀已提交級別的區別如下:

  • 可重複讀是再事務開始時候創建一致性視圖,數組,這些東西,它只認事務啓動前提交的數據。
  • 讀已提交級別則是每次執行sql語句的時候創建一致性視圖,數組,這些東西,它認的是語句啓動前提交的數據。

這四個隔離級別,常用的就是讀已提交和可重複讀兩個級別。

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