1. 程式人生 > 程式設計 >鋼筋之Mysql隱式提交和事務隔離級別的關係

鋼筋之Mysql隱式提交和事務隔離級別的關係

前言

筆者自詡對Mysql的知識積累已經很不錯了,現在看來不過是對CRUD操作比較熟悉罷了。

用了那麼久的Mysql,直到前幾日才知道隱式提交和事務隔離級別的聯絡(內幕)。

那麼,什麼是隱式提交?

  • 顧名思義,就是偷偷的提交事務(手動狗頭)。

  • 講道理在Mysql中,開啟一個事務後,需要使用commit關鍵字進行提交事務,這種提交方式叫做顯式提交。但是,我們在當前事務中輸入某些語句之後,會造成當前事務悄悄的提交,那麼這種導致事務悄悄提交的情況,我們稱為隱藏提交。

  • 那麼,觸發隱式提交的語句有哪些?

    • 使用createalterdelete語句去修改資料庫、表、檢視、儲存過程等資料庫物件的時候,就會隱式提交當前事務。

    • 使用ALTER USERCREATE USERDROP USERGRANTRENAME USERREVOKESET PASSWORD等語句,也會觸發隱式提交。

    • 當然有很多操作多會造成隱式提交,經常使用的則是對資料庫表的增、刪、改操作。

      delete ... from
      update  set  from
      insert into ....
      複製程式碼

事務併發帶來的問題

在筆者之前的知識體系中,只是知道事務併發的概念,卻不知是Mysql為什麼會發生事務的併發。請原諒筆者,到現在才知道事務的併發,是因為Mysql的C/S架構引起的…..

  • 事務併發誘因:

    講道理,Mysql是一個C/S架構,即客戶端/伺服器架構。所以,在使用過程中,肯定會出現多個客戶端訪問伺服器的場景。其中,每一個客戶端向服務端發起訪問,可以稱為建立一次資料庫連線(session會話)。而每一個連線都可以發起資料庫的事務。

    所以,不同的資料庫連線之間的事務,有可能是併發執行的。

我們都知道,一旦產生併發有可能會對共享資料的狀態,產生巨大的影響。

對於一次資料庫連線而言,當兩個事務同時操作同一種表的資料的時候,可能會產生以下問題:

create table X (
  id int(10),name varchar(10)
);
insert into X values(1,'張三');
複製程式碼
  • 骯讀/寫:一個事務能夠讀取/修改,另一個事務未提交的資料。

  • 不可重複讀:同一個事務內,根據同一個條件對同一個行記錄進行查詢,但是搜出來的結果卻不一致。

    企業微信20190808033854.png

    • 在資料庫連線1中,事務T1根據查詢條件id = 1,查詢行記錄name的值為張三,且T1未提交。之後,在另外一個資料庫連線中,根據條件id = 1,把行記錄name的值更新為李四。

      緊接著,再次查詢行記錄name的值,結果顯示為李四。這種情況,稱為不可重複讀。

      注意:在上圖的右邊更新語句,觸發了隱式提交。

  • 幻讀:同一個事務內,多次查詢相同的條件返回的結果集不一樣。

    企業微信幻讀.png

    • 在資料庫連線1中,事務T1先根據查詢H的所有記錄,這時返回結果為張三。之後,另外一個事務T2對錶插入李四這條記錄。此時事務T1再次查詢H表的所有記錄,返回的結果為張三和李四,此時發生這種情況稱為幻讀。

寫到這裡,併發帶來的問題差不多描述完了。

那麼,如何解決事務併發所帶來的問題呢?事務的隔離級別,瞭解一下!

事務的隔離級別

如果,在事務隔離性方面,直接一杆子打死。要求,所有的併發事務都必須序列化執行(一個接一個,即不允許併發),那麼這樣做會造成執行效率過低。

所以,在效能和隔離性方面,我們需要一種折中的辦法,即允許併發問題的出現(髒讀、不可重複讀、幻讀),根據出現的問題,設定隔離強度。

在SQL標準中,具有四種隔離級別,分別是讀已提交讀未提交可重複讀可序列化

  • READ UNCOMMITTED:可能發生髒讀、不可重讀讀、幻讀
  • READ COMMITTED:解決髒讀,可能會發生不可重複讀、幻讀
  • REPEATABLE READ:解決髒讀、不可重複讀,可能發生幻讀
  • SERIALIZABLE:序列化執行,並不會發生併發問題。即,解決髒讀,不可重複讀、幻讀。

上述的四種隔離級別,是所有資料庫通用的標準。因為不同資料庫,隔離級別的支援情況並不一樣。

但是,Mysq包含且支援四種上述的四種隔離級別。

唯一不同的是,Mysql在可重複讀(REPEATABLE READ)的隔離級別下,是可以解決幻讀問題。所以,Mysql的預設隔離級別為可重複讀!

總結

  • 根據事務併發帶來的問題的嚴重性,可以適度選擇相應的隔離級別來解決。

  • 髒寫是併發事務帶來的最最最嚴重的問題,所以四種隔離級別中,直接禁止髒寫的出現。

  • 在Mysql標準中的可重複讀,是可以解決幻讀問題。

  • 幻讀主要強調,使用同一個條件多次進行查詢後,返回之前查詢結果中,沒有獲取到的記錄。

    比如這種場景,算不算幻讀?

    • 事務T1,第一次查詢得到結果集合:A、B、C、D
    • 期間,事務T2,刪除了C、D記錄
    • 事務T2,第二次查詢得到結果集合:A、B

    其實,上述情況屬於不可重複讀,而不是幻讀。