原理
MySQL預設的隔離級别是可重複讀,即:事務A在讀到一條資料之後,此時事務B對該資料進行了修改并送出,那麼事務A再讀該資料,讀到的還是原來的内容。 那麼MySQL可重複讀是如何實作的呢?
使用的的一種叫MVCC的控制方式 ,即Mutil-Version Concurrency Control,多版本并發控制,類似于樂觀鎖的一種實作方式
實作方式
InnoDB在每行記錄後面儲存兩個隐藏的列來,分别儲存了這個行的建立時間和行的删除時間。這裡存儲的并不是實際的時間值,而是系統版本号,當資料被修改時,版本号加1
在讀取事務開始時,系統會給目前讀事務一個版本号,事務會讀取版本号<=目前版本号的資料
此時如果其他寫事務修改了這條資料,那麼這條資料的版本号就會加1,進而比目前讀事務的版本号高,讀事務自然而然的就讀不到更新後的資料了
增删改查
假設初始版本号為1:
INSERT
insert into user (id,name) values (1,'Tom');
id | name | create_version | delete_version |
1 | Tom | 1 |
下面模拟一下文章開頭的場景:
SELECT (事務A)
select * from user where id = 1;
此時讀到的版本号為1
UPDATE(事務B)
update user set name = 'Jerry' where id = 1;
在更新操作的時候,該事務的版本号在原來的基礎上加1,是以版本号為2。
先将要更新的這條資料标記為已删除,并且删除的版本号是目前事務的版本号,然後插入一行新的記錄
id | name | create_version | delete_version |
1 | Tom | 1 | 2 |
1 | Jerry | 2 |
SELECT (事務A)
此時事務A再重新讀資料:
select * from user where id = 1;
由于事務A一直沒送出,是以此時讀到的版本号還是為1,是以讀到的還是Tom這條資料,也就是可重複讀
DELETE
delete from user where id = 1;
在删除操作的時候,該事務的版本号在原來的基礎上加1,是以版本号為3
删除時,将目前版本号作為删除版本号
id | name | create_version | delete_version |
1 | Jerry |