概述
為了提高併發MySQL加入了多版本併發控制,它把舊版本記錄儲存在了共享表空間(undolog),當事務提交之後將重做日誌寫入磁碟(前提innodb_flush_log_at_trx_commit為1)清空undolog,在5.6版本之後unodlog可以獨立出共享表空間,引入MVCC的目的就是減少鎖的掙用,通過閱讀高效能mysql這本書的解釋是MVCC是行級鎖的一個變種,使大多數的讀操作可以不用加鎖,寫操作也只鎖定必要的行。。
正文
多版本併發控制只針對innodb的repeatable read和read committed這兩種隔離級別。多版本併發控制的原理就是在每個記錄行後面增加兩個標示列用來儲存該行的狀態,分別儲存改行的新系統版本號和刪除系統版本號。系統的版本號會隨著每增加一個事務遞增。
TABLE
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
|
有四個事務:select(trx=2),insert(trx=3),delete(trx=4),update(trx=5)
現在這四個事務同時對該行進行操作,演示SELECT的可重複讀,假設四個操作在SLECT提交之前都未提交,當然SELECT是能檢視到四個操作的記錄的。
SELECT:
SELET會根據以下兩個條件去查詢記錄,下面兩個條件需要同時滿足:
1.只查詢行的系統版本號小於或等於當前事務版本號的記錄行。
2.刪除版本號為空或者大於當前事務版本號的記錄行。
BEGIN TRAN SELECT NAME FROM TABLE WHERE ID=1
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
|
WAIT 10 MINUTE SELECT NAME FROM TABLE WHERE ID=1
COMMIT
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
4 |
根據SELECT 的查詢條件INSERT記錄的事務版本號大於當前版本號所以不會被查到;DELETE的事務刪除版本號大於當前版本號,所以該行會被查出;UPDATE第一行的事務的版本號小於當前版本號而刪除版本號大於當前版本號,可以被查到,第二行因為事務版本號大於當前版本號所以不滿足,最終SELECT查詢的記錄是UPDATE操作的第一條記錄;SELECT兩次查詢的結果一致,滿足可重複讀隔離級別。當然在這裡除了INSERT操作,其它的操作都無法在SELECT提交之前提交。
INSERT:
INSERT INTO TABLE(ID,NAME) VALUES(2,'B');
ID |
NAME |
Trx_id |
De_Trx_id |
2 |
b |
2 |
|
DELETE:
DELETE FROM TABLE WHERE ID=1;
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
3 |
UPDATE:
BEGIN TRAN UPDATE TABLE SET NAME='B' WHERE ID=1 COMMIT
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
4 |
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
b |
4 |
|
注意:多版本併發控制不支援myisam儲存引擎。
總結
在快取中有一個用於維護鎖的資源,對鎖的維持需要消耗mysql的資源,多版本併發控制它就是減少了用於維持鎖資源的消耗來提高效能,所以日誌的寫操作都是先undo再redo。
備註: 作者:pursuer.chen 部落格:http://www.cnblogs.com/chenmh 本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明連結。 《歡迎交流討論》 |