[MySQL]事務的MVCC原理與幻讀

首先要了解MVCC,MVCC叫作多版本併發控制,實際上就是保存了數據在某個時間節點的快照併發

咱們每行數實際上隱藏了兩列,建立版本號,過時(刪除)版本號,每開始一個新的事務,版本號都會自動遞增編輯器

 

拿user表舉例子,假設咱們插入兩條數據,他們實際上應該長這樣 , 建立版本號是遞增的。spa

id name create_version delete_version
1 張三 1  
2 李四 2  

這時候假設小明去執行查詢,此時也是會默認開啓一個事務 當前版本就是 current_version=3索引

select * from user where id<=3;事務

 

同時,小紅在這時候開啓事務去修改id=1的記錄,小紅事務版本是 current_version=4io

update user set name='張三三' where id=1;table

小紅執行成功後的結果是這樣的原理

id name create_version delete_version
1 張三 1  
2 李四 2  
1 張三三 4  

 

同時 , 還有小黑在刪除id=2的數據,小黑的版本是 current_version=5,小黑執行後結果是這樣的。date

id name create_version delete_version
1 張三 1  
2 李四 2 5
1 張三三 4  

因爲MVCC的原理是查找建立版本小於或等於當前事務版本,刪除版本爲空或者大於當前事務版本,小明的真實的查詢應該是這樣select

select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

因此小明最後查詢到的id=1的名字仍是'張三',而且id=2的記錄也能查詢到。這樣作是爲了保證事務讀取的數據是在事務開始前就已經存在的,要麼是事務本身插入或者修改的

 

幻讀是這樣的 , 好比下面的增長用戶的例子 ,假定用戶名是惟一索引不容許重複

小明想要插入一條王五的數據 , 開啓事務current_version=6查詢名字爲 '王五'的記錄,發現不存在。

同時小紅開啓事務current_version=7插入一條 王五的數據,結果是這樣:

id Name create_version delete_version
1 張三 1  
2 李四 2  
3 王五 7  

小明執行插入名字'王五'的記錄,發現惟一索引衝突,沒法插入,查詢的時候分明看不到王五 , 可是插入老是說重複了 ,  這就是幻讀。

相關文章
相關標籤/搜索