mysql事務基礎概念

事務介紹

MySQL 是一個伺服器/客戶端架構的軟體,對於同一個伺服器來說,可以有若干個客戶端與之連線,每個客戶端與伺服器連線上之後,就可以稱之為一個會話( Session )。我們可以同時在不同的會話裡輸入各種語句,這些語句可以作為事務的一部分進行處理。不同的會話可以同時傳送請求,也就是說伺服器可能同時在處理多個事務,這樣子就會導致不同的事務可能同時訪問到相同的記錄。我們前邊說過事務有一個特性稱之為隔離性,理論上在某個事務對某個資料進行訪問時,其他事務應該進行排隊,當該事務提交之後,其他事務才可以繼續訪問這個資料。但是這樣子的話對效能影響太大,所以設計資料庫的大叔提出了各種隔離級別,來最大限度地提升系統併發處理事務的能力,但是這也是以犧牲一定的隔離性來達到的。

事務是資料庫最為重要的機制之一,凡是使用過資料庫的人,都瞭解資料庫的事務機制,也對ACID四個基本特性如數家珍。但是聊起事務或者ACID的底層實現原理,往往言之不詳,不明所以。在MySQL中的事務是由儲存引擎實現的,而且支援事務的儲存引擎不多,我們主要講解InnoDB儲存引擎中的事務。所以,今天我們就一起來分析和探討InnoDB的事務機制,希望能建立起對事務底層實現原理的具體瞭解。

mysql事務基礎概念

四大特性

資料庫事務具有ACID

四大特性

。ACID是以下4個詞的縮寫:

原子性(atomicity)

:事務最小工作單元,要麼全成功,要麼全失敗 。

一致性(consistency):

事務開始和結束後,資料庫的完整性不會被破壞 。

隔離性(isolation) :

不同事務之間互不影響,四種隔離級別為RU(讀未提交)、RC(讀已提交)、RR(可重複讀)、SERIALIZABLE (序列化)。

永續性(durability) :

事務提交後,對資料的修改是永久性的,即使系統故障也不會丟失 。

隔離級別

1)未提交讀(READ UNCOMMITTED/RU)

髒讀:一個事務讀取到另一個事務未提交的資料。

如果一個事務讀到了另一個未提交事務修改過的資料,那麼這種隔離級別就稱之為未提交讀(英文名:READ UNCOMMITTED ),示意圖如下:

mysql事務基礎概念

如上圖, Session A 和Session B 各自開啟了一個事務, Session B 中的事務先將id 為1 的記錄的列c更新為‘關羽’ ,然後Session A 中的事務再去查詢這條id 為1 的記錄,那麼在未提交讀的隔離級別下,查詢結果就是‘關羽’ ,也就是說某個事務讀到了另一個未提交事務修改過的記錄。但是如果Session B 中的事務稍後進行了回滾,那麼Session A 中的事務相當於讀到了一個不存在的資料,這種現象就稱之為髒讀,就像這個樣子

mysql事務基礎概念

髒讀違背了現實世界的業務含義,所以這種READ UNCOMMITTED 算是十分不安全的一種隔離級別。

2)已提交讀(READ COMMITTED/RC)

不可重複讀:一個事務因讀取到另一個事務已提交的update。導致對同一條記錄讀取兩次以上的結果不一致。

如果一個事務只能讀到另一個已經提交的事務修改過的資料,並且其他事務每對該資料進行一次修改並提交後,該事務都能查詢得到最新值,那麼這種隔離級別就稱之為已提交讀(英文名: READCOMMITTED ),如圖所示:

mysql事務基礎概念

從圖中可以看到,第4步時,由於Session B 中的事務尚未提交,所以Session A 中的事務查詢得到的結果只是‘劉備’ ,而第6步時,由於Session B 中的事務已經提交,所以Session B 中的事務查詢得到的結果就是‘關羽’ 了。對於某個處在在已提交讀隔離級別下的事務來說,只要其他事務修改了某個資料的值,並且之後提交了,那麼該事務就會讀到該資料的最新值,比方說:

mysql事務基礎概念

我們在Session B 中提交了幾個隱式事務,這些事務都修改了id 為1 的記錄的列c的值,每次事務提交之後, Session A 中的事務都可以檢視到最新的值。這種現象也被稱之為不可重複讀。

3)可重複讀(REPEATABLE READ/RR)

幻讀:一個事務因讀取到另一個事務已提交的insert資料。導致對同一張表讀取兩次以上的結果不一致。

在一些業務場景中,一個事務只能讀到另一個已經提交的事務修改過的資料,但是第一次讀過某條記錄後,即使其他事務修改了該記錄的值並且提交,該事務之後再讀該條記錄時,讀到的仍是第一次讀到的值,而不是每次都讀到不同的資料。那麼這種隔離級別就稱之為可重複讀(英文名: REPEATABLEREAD ),如圖所示:

mysql事務基礎概念

從圖中可以看出來, Session A 中的事務在第一次讀取id 為1 的記錄時,列c 的值為‘劉備’ ,之後雖然Session B 中隱式提交了多個事務,每個事務都修改了這條記錄,但是Session A 中的事務讀到的列c 的值仍為‘劉備’ ,與第一次讀取的值是相同的。

4)序列化(SERIALIZABLE)

以上3種隔離級別都允許對同一條記錄進行讀-讀、讀-寫、寫-讀的併發操作,如果我們不允許讀-寫、寫-讀的併發操作,可以使用SERIALIZABLE 隔離級別,示意圖如下:

mysql事務基礎概念

如圖所示,當Session B 中的事務更新了id 為1 的記錄後,之後Session A 中的事務再去訪問這條記錄時就被卡住了,直到Session B 中的事務提交之後, Session A 中的事務才可以獲取到查詢結果。

mysql事務基礎概念

mysql教程書籍,一本搞懂mysql事務

檢視