MVCC實現可重複讀驚天真相

2021-10-08 02:58:07 字數 1311 閱讀 4858

版本變化規則:

新事務執行系統版本號加一,也就是當前事務版本號;

刪除語句:執行後將新的系統版本號作為對應行資料的刪除標記;

更新語句:複製原來的資料作為新的一行,將新的版本號給資料行版本,並且將新的版本號作為原來資料行的刪除標記;

何為新事務:

begin之下,commit之上為同一事務,整個作為乙個事務,要麼全做,要麼全不做。在其他客戶端,也就是會話的begin之下,commit之上相對上面這個又是乙個新事務。

select

innodb檢查每行資料,確保他們符合兩個標準:

1、innodb只查詢版本早於當前事務版本的資料行(也就是資料行的版本必須小於等於事務的版本),這確保當前事務讀取的行都是事務之前已經存在的,或者是由當前事務建立或修改的行

2、行的刪除操作的版本一定是未定義的或者大於當前事務的版本號,確定了當前事務開始之前,行沒有被刪除

符合了以上兩點則返回查詢結果。

例項:假設系統版本開始為0,a客戶端開始乙個事務,執行一條插入語句,系統版本加一變為一,將系統版本作為插入生成的資料行的建立版本,也是資料行版本。

刪除:

a客戶端又開啟乙個事務,有兩條同樣的查詢語句,均是查詢剛剛插入的那條資料。a客戶端執行查詢語句,系統版本加一由原來的一變為二,當前事務版本為二。注意,重點來了,此刻在a客戶端執行第二條查詢語句之前b客戶端開啟了新事務,執行刪除語句刪除那天插入的資料,系統版本號由二變為三並將系統版本號作為當時插入的資料行的刪除標記。最後a客戶端執行了第二天同樣的查詢語句,由於還是同乙個事務裡面的,系統版本號和第一次執行查詢語句時一樣,為二,此時根據查詢規則:資料行版本小與或等於當前事務,資料行版本為一,當前事務版本為二,符合;資料刪除標記為空或者大於當前事務版本,資料刪除標記為三,大於當前事務版本號,符合,故最後能夠讀到原先插入的資料而不是被刪除了什麼都沒看到。

更新:

同樣在a客戶端執行第乙個查詢語句後,b客戶端執行更新語句更新該條資料,首先系統版本號為三,因為更新語句是刪除+複製更新插入,原先的資料的刪除標記變為三,複製更新插入的那條資料的建立版本為三,也就是新的資料行的行版本號為三,此時,a客戶端執行第二天查詢語句,由於不是新事務,跟第一執行的查詢是同乙個事務,仍然保持原來的當前事務版本為二:此時根據查詢規則:資料行版本小與或等於當前事務,資料行版本為一和三,當前事務版本為二,原先資料行符合;資料刪除標記為空或者大於當前事務版本,資料刪除標記為三,大於當前事務版本號,符合,故最後能夠讀到原先插入的資料而不是被更新後的資料。

總結:不可重複讀是刪除和更新造成的,例項很好地證明了可重複讀的實現能夠解決事務併發帶來的不可重複讀問題。

不可重複讀,可重複讀,幻讀,MVCC概念理解

是指在乙個事務內,多次讀同一資料。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料。那麼,在第乙個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第乙個事務兩次讀到的資料可能是不一樣的。這樣就發生了在乙個事務內兩次讀到的資料是不一樣的,因此稱為是不可重複讀。前提是非序列化 乙個事務在執行過程中...

事務可重複讀是怎麼實現的?

一 事務 t 啟動的時候會建立乙個檢視 read view,之後事務 t 執行期間,即使有其他事務修改了資料,事務 t 看到的仍然跟在啟動時看到的一樣。二 begin start transaction 命令並不是乙個事務的起點,在執行到它們之後的第乙個操作 innodb 表的語句,事務才真正啟動。...

MySQL是如何實現可重複讀的

photo by picography.co mysql實戰45講 筆記。可重複讀是指 乙個事務執行過程中看到的資料,總是跟這個事務在啟動時看到的資料是一致的。我們可以簡單理解為 在可重複讀隔離級別下,事務在啟動的時候就 拍了個快照 注意,這個快照是基於整個庫的。這時,你可能就會想,如果乙個庫有 1...