我們知道,mysql的innodb採用的是行鎖,而且採用了多版本併發控制來提高讀操作的效能。
什麼是多版本併發控制呢 ?其實就是在每一行記錄的後面增加兩個隱藏列,記錄建立版本號和刪除版本號,
而每一個事務在啟動的時候,都有一個唯一的遞增的版本號。
1、在插入操作時 : 記錄的建立版本號就是事務版本號。
比如我插入一條記錄, 事務id 假設是1 ,那麼記錄如下:也就是說,建立版本號就是事務版本號。
id | name | create version | delete version |
1 | test | 1 |
2、在更新操作的時候,採用的是先標記舊的那行記錄為已刪除,並且刪除版本號是事務版本號,然後插入一行新的記錄的方式。
比如,針對上面那行記錄,事務Id為2 要把name欄位更新
update table set name= 'new_value' where id=1;
id | name | create version | delete version |
1 | test | 1 | 2 |
1 | new_value | 2 |
3、刪除操作的時候,就把事務版本號作為刪除版本號。比如
delete from table where id=1;
id | name | create version | delete version |
1 | new_value | 2 | 3 |
4、查詢操作:
從上面的描述可以看到,在查詢時要符合以下兩個條件的記錄才能被事務查詢出來:
1) 刪除版本號 大於 當前事務版本號,就是說刪除操作是在當前事務啟動之後做的。
2) 建立版本號 小於或者等於 當前事務版本號 ,就是說記錄建立是在事務中(等於的情況)或者事務啟動之前。
這樣就保證了各個事務互不影響。從這裡也可以體會到一種提高系統效能的思路,就是:
通過版本號來減少鎖的爭用。
另外,只有read-committed和 repeatable-read 兩種事務隔離級別才能使用mVcc
read-uncommited由於是讀到未提交的,所以不存在版本的問題
而serializable 則會對所有讀取的行加鎖