一致性視圖是啥時候建立的?
在上篇文章中涉及到了一個小小的問題,就是數據庫事務的一致性視圖是啥時候建立的?
這個問題還比較重要,如果沒搞清楚,可能會影響我們做實驗的結果,進而得出錯誤的結論,所以今天松哥和大家簡單聊一聊這個話題。
1. 錯誤演示
先給大家來一個錯誤演示。
我們打開兩個會話窗口,默認情況下隔離級別是可重復讀,我們來看下:
首先在 A 會話中查看當前 user 表,查看完成后開啟事務:
可以看到當前 age 是 101。
接下來在 B 會話中修改 age:
可以看到,B 會話已經修改成功。
接下來回到 A 會話查詢記錄:
可以看到,A 會話的記錄也變了。完整測試流程如下:
說好的可重復讀呢?
按理說,可重復讀就是別的事務對數據的操作不影響當前事務,但是上面這個案例似乎和我們理解的可重復讀有出入。
2. 分析
不知道小伙伴們是否還記得可重復讀的特點:
用戶在另外一個事務中執行同條 SELECT 語句數次,結果總是相同的。
從這個角度來說,第一小節的案例似乎也沒有問題,因為我們在 A 會話中執行 SELECT 語句多次,查到的結果也都是相同的,age 都是 102。
但是我們疑惑的是明明 B 會話的事務后開啟的,但是我們卻在 A 會話中讀取到了 B 的修改,這似乎不應該。
這里就涉及到一個問題,事務的一致性視圖是何時建立的?
事實上,我們執行的 begin 語句并不是一個事務真正的起點。執行完 begin 之后,接下來執行的第一句 SQL,事務才真正啟動。
我們稍微修改一下第一小節的案例:
在 A 會話中,事務開啟之后,立馬先執行一條 SELECT 語句,然后再去 B 會話中做修改,修改完成后再回到 A 會話繼續查詢,此時發現 B 中的修改對 A 并不可見,這個結果也符合用戶在另外一個事務中執行同條 SELECT 語句數次,結果總是相同的。
如果我們想要執行完 begin 之后,就立馬開啟事務,那么可以通過如下方式來執行:
- start transaction with consistent snapshot;
這個 SQL 執行完之后,事務立馬就啟動了。
接下來,回到第一小節的案例,我們修改一下事務啟動的命令:
此時,A 會話中事務的查詢就看不見 B 中的修改了。
3.小結
好啦,一個小小的案例,希望小伙伴們在做實驗的時候不要出錯。本文涉及到一個概念叫做一致性視圖,如果大家不熟悉可以參考上篇文章。