先說下我自己的理解,總結為圖如下:
MVCC的全稱是“多版本並發控制”。這項技術使得InnoDB的事務隔離級別下執行一致性讀操作有了保證,換言之,就是為了查詢一些正在被另一個事務更新的行,並且可以看到它們被更新之前的值。這是一個可以用來增強並發性的強大的技術,因為這樣的一來的話查詢就不用等待另一個事務釋放鎖。這項技術在數據庫領域並不是普遍使用的。一些其它的數據庫產品,以及mysql其它的存儲引擎並不支持它。
mysql的innodb采用的是行鎖,而且采用了多版本並發控制來提高讀操作的性能。
什么是多版本並發控制呢 ?其實就是在每一行記錄的后面增加兩個隱藏列,記錄創建版本號和刪除版本號,
而每一個事務在啟動的時候,都有一個唯一的遞增的版本號。
在InnoDB中,給每行增加兩個隱藏字段來實現MVCC,兩個列都用來存儲事務的版本號,每開啟一個新事務,事務的版本號就會遞增。
於是乎,默認的隔離級別(REPEATABLE READ)下,增刪查改變成了這樣:
- SELECT
- 讀取創建版本小於或等於當前事務版本號,並且刪除版本為空或大於當前事務版本號的記錄。這樣可以保證在讀取之前記錄是存在的。
- INSERT
- 將當前事務的版本號保存至行的創建版本號
- UPDATE
- 新插入一行,並以當前事務的版本號作為新行的創建版本號,同時將原記錄行的刪除版本號設置為當前事務版本號
- DELETE
- 將當前事務的版本號保存至行的刪除版本號
在插入操作時 : 記錄的創建版本號就是事務版本號。
比如我插入一條記錄, 事務id 假設是1 ,那么記錄如下:也就是說,創建版本號就是事務版本號。
id | name | create version | delete version |
1 | xttblog | 1 |
在更新操作的時候,采用的是先標記舊的那行記錄為已刪除,並且刪除版本號是事務版本號,然后插入一行新的記錄的方式。
比如,針對上面那行記錄,事務Id為2 要把name字段更新。
1 |
|
id | name | create version | delete version |
1 | xttblog | 1 | 2 |
1 | xttblog.com | 2 |
刪除操作的時候,就把事務版本號作為刪除版本號。比如:
1 |
|
id | name | create version | delete version |
1 | xttblog.com | 2 | 3 |
查詢操作:從上面的描述可以看到,在查詢時要符合以下兩個條件的記錄才能被事務查詢出來:
- 刪除版本號 大於 當前事務版本號,就是說刪除操作是在當前事務啟動之后做的。
- 創建版本號 小於或者等於 當前事務版本號 ,就是說記錄創建是在事務中(等於的情況)或者事務啟動之前。
這樣就保證了各個事務互不影響。從這里也可以體會到一種提高系統性能的思路,就是:通過版本號來減少鎖的爭用。另外,只有read-committed和 repeatable-read 兩種事務隔離級別才能使用mVcc read-uncommited由於是讀到未提交的,所以不存在版本的問題。而serializable 則會對所有讀取的行加鎖。
快照讀和當前讀
快照讀:讀取的是快照版本,也就是歷史版本
當前讀:讀取的是最新版本
普通的SELECT就是快照讀,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是當前讀。
鎖定讀
在一個事務中,標准的SELECT語句是不會加鎖,但是有兩種情況例外。SELECT … LOCK IN SHARE MODE 和 SELECT … FOR UPDATE。
1 |
|
給記錄假設共享鎖,這樣一來的話,其它事務只能讀不能修改,直到當前事務提交
1 |
|
給索引記錄加鎖,這種情況下跟UPDATE的加鎖情況是一樣的
一致性非鎖定讀
consistent read (一致性讀),InnoDB用多版本來提供查詢數據庫在某個時間點的快照。如果隔離級別是REPEATABLE READ,那么在同一個事務中的所有一致性讀都讀的是事務中第一個這樣的讀讀到的快照;如果是READ COMMITTED,那么一個事務中的每一個一致性讀都會讀到它自己刷新的快照版本。Consistent read(一致性讀)是READ COMMITTED和REPEATABLE READ隔離級別下普通SELECT語句默認的模式。一致性讀不會給它所訪問的表加任何形式的鎖,因此其它事務可以同時並發的修改它們。
悲觀鎖和樂觀鎖
悲觀鎖,正如它的名字那樣,數據庫總是認為別人會去修改它所要操作的數據,因此在數據庫處理過程中將數據加鎖。其實現依靠數據庫底層。
樂觀鎖,如它的名字那樣,總是認為別人不會去修改,只有在提交更新的時候去檢查數據的狀態。通常是給數據增加一個字段來標識數據的版本。
MVCC實現一致性非鎖定讀,這就有保證在同一個事務中多次讀取相同的數據返回的結果是一樣的,解決了不可重復讀的問題。