共計 2152 個字符,預計需要花費 6 分鐘才能閱讀完成。
MYSQL 中樂觀鎖的實現方法,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
什么是 MVCC
MVCC 即 Multi-Version Concurrency Control,中文翻譯過來叫多版本并發控制。
MVCC 是解決了什么問題
眾所周知,在 MYSQL 中,MyISAM 使用的是表鎖,InnoDB 使用的是行鎖。而 InnoDB 的事務分為四個隔離級別,其中默認的隔離級別 REPEATABLE READ 需要兩個不同的事務相互之間不能影響,而且還能支持并發,這點悲觀鎖是達不到的,所以 REPEATABLE READ 采用的就是樂觀鎖,而樂觀鎖的實現采用的就是 MVCC。正是因為有了 MVCC,才造就了 InnoDB 強大的事務處理能力。
MVCC 具體實現分析
InnoDB 的 MVCC, 是通過在每行記錄后面保存兩個隱藏的列來實現的, 這兩個列,分別保存了這個行的創建時間,一個保存的是行的刪除時間。這里存儲的并不是實際的時間值, 而是系統版本號(可以理解為事務的 ID),每開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的 ID. 下面看一下在 REPEATABLE READ 隔離級別下,MVCC 具體是如何操作的。
首先創建一張表:
create table yang( id int primary key auto_increment, name varchar(20) );
假設系統的版本號從 1 開始.
INSERT
InnoDB 為新插入的每一行保存當前系統版本號作為版本號。*** 個事務 ID 為 1:
start transaction; insert into yang values(NULL, yang insert into yang values(NULL, long insert into yang values(NULL, fei commit;
對應在數據中的表如下(后面兩列是隱藏列, 我們通過查詢語句并看不到)
SELECT
InnoDB 會根據以下兩個條件檢查每行記錄:
InnoDB 只會查找版本早于當前事務版本的數據行(也就是, 行的系統版本號小于或等于事務的系統版本號),這樣可以確保事務讀取的行,要么是在事務開始前已經存在的,要么是事務自身插入或者修改過的.
行的刪除版本要么未定義, 要么大于當前事務版本號(這可以確保事務讀取到的行,在事務開始之前未被刪除), 只有條件 1、2 同時滿足的記錄,才能返回作為查詢結果.
DELETE
InnoDB 會為刪除的每一行保存當前系統的版本號 (事務的 ID) 作為刪除標識.
看下面的具體例子分析: 第二個事務,ID 為 2:
start transaction; select * from yang; select * from yang; commit;
假設 1:
假設在執行這個事務 ID 為 2 的過程中, 剛執行到(1), 這時, 有另一個事務 ID 為 3 往這個表里插入了一條數據; 第三個事務 ID 為 3;
start transaction; insert into yang values(NULL, tian commit;
這時表中的數據如下:
然后接著執行事務 2 中的 (2), 由于 id= 4 的數據的創建時間(事務 ID 為 3), 執行當前事務的 ID 為 2, 而 InnoDB 只會查找事務 ID 小于等于當前事務 ID 的數據行, 所以 id= 4 的數據行并不會在執行事務 2 中的(2) 被檢索出來, 在事務 2 中的兩條 select 語句檢索出來的數據如下:
假設 2
假設在執行這個事務 ID 為 2 的過程中, 剛執行到(1), 假設事務執行完事務 3 后,接著又執行了事務 4;
第四個事務:
start transaction; delete from yang where id=1; commit;
此時數據庫中的表如下:
接著執行事務 ID 為 2 的事務 (2), 根據 SELECT 檢索條件可以知道, 它會檢索創建時間(創建事務的 ID) 小于當前事務 ID 的行和刪除時間 (刪除事務的 ID) 大于當前事務的行, 而 id= 4 的行上面已經說過, 而 id= 1 的行由于刪除時間 (刪除事務的 ID) 大于當前事務的 ID, 所以事務 2 的(2)select * from yang 也會把 id= 1 的數據檢索出來. 所以, 事務 2 中的兩條 select 語句檢索出來的數據都如下:
UPDATE
InnoDB 執行 UPDATE,實際上是新插入了一行記錄,并保存其創建時間為當前事務的 ID,同時保存當前事務 ID 到要 UPDATE 的行的刪除時間。
假設 3:
假設在執行完事務 2 的 (1) 后又執行, 其它用戶執行了事務 3,4, 這時,又有一個用戶對這張表執行了 UPDATE 操作:
第 5 個事務:
start transaction; update yang set name= Long where id=2; commit;
根據 update 的更新原則: 會生成新的一行, 并在原來要修改的列的刪除時間列上添加本事務 ID, 得到表如下:
繼續執行事務 2 的(2), 根據 select 語句的檢索條件, 得到下表:
還是和事務 2 中(1)select 得到相同的結果.
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業資訊頻道,感謝您對丸趣 TV 的支持。