Mysql 事務 - 多版本併發控制(MVCC)的實現
我們知道,在 Mysql 的 讀提交,可重複讀
隔離級別下,Mysql 內部是通過一致性 視圖
來實現事務的併發控制的,也是數據庫系統中所描述的 多版本併發控制 (Multi-Version Concurrency Control)
可能起初學習的時候會把 客觀鎖
和 多版本併發控制
這兩個概念混淆。大家基本可以看做 樂觀鎖
是一種 思想
和控制併發的 方式
,而具體的實現,我們使用了 多版本併發
的方法
什麼是多版本併發控制
多版本併發控制,是控制事務併發的有效手段,通過對數據添加不同的 版本號
來控制每一個事務應該看到什麼樣的 數據 (視圖)
。例如,事務 1 在執行的時候,只能看到版本號爲 1 或 0 的數據,其他版本號的數據,不可以讀取
Mysql 中的 MVCC
在 Mysql 中,使用多版本併發控制來實現 讀提交和可重讀
隔離級別。簡單的來說,在 讀提交
隔離級別下,讀取數據時獲取對應的版本信息(視圖)是在每個 SQL 執行的時候,並不是在事務開始的時候;可重讀
隔離級別下,在事務一開始,就會拿到整個事務的一致性視圖。所以,在 可重讀
隔離級別下,已開啓的事務相對其他事務都是隔離開來的
版本號
Mysql 中,每開啓一個事務,系統內部會生成 系統版本號
,每個 系統版本號
是遞增切不重複的,系統版本號
同時又是對應事務的 事務版本號
爲了實現 MVCC,Mysql 在每個數據行的後面,都會添加兩個隱藏的列,一個是 創建版本號
,一個是 刪除版本號
。 創建版本號
指的是該條事務被創建時的 事務版本號
, 刪除版本號
指的是數據被刪除時候的 事務版本號
,表示快照已被刪除
MVCC 使用到的快照,都被存儲在 Mysql 的 Undo log 中,通過回滾指針,把每一個數據的快照都串聯起來
具體實現
多版本併發控制的具體實現,針對於 增刪查改
操作,每個操作都有會對應 創建版本號
和 刪除版本號
的判斷和更新邏輯
-
INSERT
在插入數據的時候,將創建版本號
設置爲當前事務版本號
,刪除版本號表示未定義
-
DELETE
刪除時,把要刪除數據的刪除版本號
設置爲當前事務的系統版本號
-
SELECT
在查詢的時候,我們知道,Mysql 會分配一個事務版本號
給當前事務,那麼讀取數據的創建版本號
必須小於等於當前事務版本號
,如果大於,則表示新的事務
正在修改他的內容,不能讀取。並且讀取數據的刪除版本號
必須大於當前事務版本號或未定義
,如果小於等於當前事務版本號則表示數據已被刪除,不可讀取 -
UPDATE
更新操作,可以看做是先刪除再插入
。把當前事務的系統版本號
作爲更新前數據的刪除版本號
,更新後數據的創建版本號
設置爲當前事務的系統版本號
,更新後數據的刪除版本號設置爲未定義
上述的具體實現過程邏輯性比較強,需要細細思考並且理解這麼做的目的
討論的範圍僅在 InnoDB 數據引擎