概述
為了提高並發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 本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須注明文章來源,且在文章開頭明顯處給明鏈接。 《歡迎交流討論》 |