好比咱們新建一個表,而後新建兩行數據,如今表的內容是這樣的
咱們新建一個事務,稱爲Query1。mysql
begin; select * from test1; ## 第一次查詢 select * from test1; ## 第二次查詢 commit;
而後執行第一次查詢的語句,查詢內容跟表內容同樣,正常。
而後咱們新建一個事務,執行update操做,咱們稱爲Query2sql
begin; update test1 set `name` = 'yunzhi' where id = 1; select * from test1; commit;
執行他Query2,此時查詢結果爲
而後再執行Query1的第二次查詢
咱們發現Query1的查詢和Query2的查詢的結果是不一樣的。併發
這就涉及到mysql的多版本併發控制技術, 簡稱MVCC(Multi-Version Concurrency Control)。
基於上邊的例子,咱們能夠理解爲當開啓一個事務的時候,會對事務設置一個版本號,且版本號逐個遞增,同時對每行數據進行新增,更新,刪除也會同步更新版本號同當前事務版本號。當在事務內進行查詢操做的時候,
默認執行快照讀操做,快照讀只能查詢到小於等於當前版本的數據。
讓咱們覆盤一下剛纔的操做。
咱們認爲新增數據時version = 1;因此每行數據版本號爲1。
咱們在新建Query1事務的時候,version = 2;spa
begin; ## version = 2; select * from test1; ## 第一次查詢 select * from test1; ## 第二次查詢 commit;
咱們再新建Query2事務的時候,version = 3;code
begin; ## version = 3; update test1 set `name` = 'yunzhi' where id = 1; select * from test1; commit;
再執行Query1的第二次查詢時,事務
由於Query1的對應版本號爲2,沒法查到對應版本號爲3的'yunzhi'數據。同步
快照讀解決了不可重複讀問題。不可重複讀,即先後屢次讀取,數據內容不一致it
對於會對數據修改的操做(update、insert、delete)都會執行當前讀。假設要update一個記錄,另外一個事務已經delete這條數據而且commit了,這樣就會產生衝突,因此update的時候確定要知道最新的信息。
在執行修改數據的時候,首先會執行當前讀,而後把返回的數據加鎖,以後執行修改數據。加鎖是防止別的事務在這個時候對這條記錄作什麼,默認加的是排他鎖,也就是你讀都不能夠,這樣就能夠保證數據不會出錯了。
想要手動執行當前讀須要在後綴加for update
,如io
select * from test1 for update;
若是一個事務執行當前讀操做且不提交,另外一個事務是沒法執行當前讀操做的。這也說明了當前讀加了鎖。class
mysql查詢操做默認執行快照讀操做,修改數據會執行當前讀操做。