mysql 可重複讀。

一、可重複讀

我們先看看現象,再分析原理。我的mysql版本是5.5。

下面是一張表,只有一條數據,並且我開啓了事物

此時,另一個事物將record加1,因此我在開啓一個命令行客戶端,執行下面的命令:

成功加1之後,實際上,數據庫中record肯定是2。

然後回到之前的客戶端,再查一次:

沒毛病,record還是1,果然是可重複讀。有些人以爲mysql的可重複讀是通過行鎖實現的,

從上面可以知道,肯定不是,如果是的話,第一次select * from test的時候,id=1的記錄就會加行鎖,我都加行鎖了,我還沒提交,另外的事物是怎麼update成功的。

結論就是mysql使用的MVCC(多版本併發控制),MVCC詳解可以看:https://blog.csdn.net/whoamiyang/article/details/51901888

我們繼續,我之前的第一個事物還沒提交,不過提交之前,我也想加1;

加完之後我再查一下,額,record是3,好像很奇怪,但也不奇怪。

其實,update test set record=record+1 where id=1;這條語句中,在加1之前,他知道自己等於2,然後2+1=3。

也就是說,update時讀取數據是最新版本的數據,而select是到當前事物版本爲止的數據。當更新成功之後,當前版本即爲最新版本,再次select,讀取的是最新的數據。

在這裏討論下樂觀鎖的必要性。下面是樂觀鎖的實現,實現樂觀鎖,我們一般會這麼做

 update test set record=record+1 where id=1 and record=1;

如果不用樂觀鎖,你用select讀取到的值其實根本不準確。除非你開啓悲觀鎖,像下面這樣:

select * from test where id=1 for update;

這樣可以讀取到最新的內容,同時在你當前的事物提交之前,其他事物的update此條記錄將會鎖等待。

故事到此,還沒有結束,此時我們開啓事物三,也做加1操作看會發生什麼。

結果是,鎖等待超時,也就是說(事物一)在更新完後,會加行鎖,這個應該比較好理解。事物中,剛開始查詢的時候是不會加行鎖的,但是當有更新操作之後,會加行鎖,直到事物提交。

http://hedengcheng.com/?p=771http://hedengcheng.com/?p=844這兩篇博文詳細的介紹了mysql中的這些問題,有興趣可以讀一讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章