再話可重復讀事務
在之前我們說到了可重復讀事務,由MVCC多版本控制來實現(xiàn)呛每,接下來我們再來探討一下事務的可重復讀是怎么實現(xiàn)的踩窖。
強調(diào):
- 在RR事務開啟的時候,有begin/start transaction 啟動的事務是在第一次查詢的時候創(chuàng)建一致性視圖晨横。當我們用start transaction with cinsistent snapshot語句的時候?qū)谑聞臻_啟的時候創(chuàng)建一致性視圖洋腮。
- 一致性視圖并不會拷貝數(shù)據(jù)庫的全部數(shù)據(jù)箫柳,因為有每一行都有它的版本號,事務開啟的時候可會有一個遞增的版本號啥供,在之前我們提到悯恍,當事務修改行數(shù)據(jù)的時候,會有一個undo log記錄當前數(shù)據(jù)伙狐,并且將事務的版本號賦給行版本涮毫。當我們需要計算出事務可見的狀態(tài)的時候,就是通過undo log來推算出來的贷屎。innodb利用數(shù)據(jù)的多版本特性快速的創(chuàng)建了一致性視圖罢防。
- 當事務開始的時候,會創(chuàng)建一個事務數(shù)組用來保存已經(jīng)啟動但是還沒有提交的活躍事務id豫尽,視圖數(shù)組中的最小id稱之為低水位線篙梢,最大的事務id+1稱之為高水位線。
從圖中可以看到美旧,第一個有效更新是事務 C渤滞,把數(shù)據(jù)從 (1,1) 改成了 (1,2)。這時候榴嗅,這個
數(shù)據(jù)的最新版本的 row trx_id 是 102妄呕,而 90 這個版本已經(jīng)成為了歷史版本。
第二個有效更新是事務 B嗽测,把數(shù)據(jù)從 (1,2) 改成了 (1,3)绪励。這時候,這個數(shù)據(jù)的最新版本(即
row trx_id)是 101唠粥,而 102 又成為了歷史版本疏魏。
你可能注意到了,在事務 A 查詢的時候晤愧,其實事務 B 還沒有提交大莫,但是它生成的 (1,3) 這
個版本已經(jīng)變成當前版本了。但這個版本對事務 A 必須是不可見的官份,否則就變成臟讀了只厘。
好,現(xiàn)在事務 A 要來讀數(shù)據(jù)了舅巷,它的視圖數(shù)組是 [99,100]羔味。當然了,讀數(shù)據(jù)都是從當前版
本讀起的钠右。所以赋元,事務 A 查詢語句的讀數(shù)據(jù)流程是這樣的:
這樣執(zhí)行下來,雖然期間這一行數(shù)據(jù)被修改過,但是事務 A 不論在什么時候查詢们陆,看到這
行數(shù)據(jù)的結(jié)果都是一致的寒瓦,所以我們稱之為一致性讀。
這個判斷規(guī)則是從代碼邏輯直接轉(zhuǎn)譯過來的坪仇,但是正如你所見杂腰,用于人肉分析可見性很麻
煩。
所以椅文,我來給你翻譯一下喂很。一個數(shù)據(jù)版本,對于一個事務視圖來說皆刺,除了自己的更新總是可
見以外少辣,有三種情況:
- 版本未提交,不可見羡蛾;
- 版本已提交漓帅,但是是在視圖創(chuàng)建后提交的,不可見痴怨;
- 版本已提交忙干,而且是在視圖創(chuàng)建前提交的,可見浪藻。
現(xiàn)在捐迫,我們用這個規(guī)則來判斷圖 4 中的查詢結(jié)果,事務 A 的查詢語句的視圖數(shù)組是在事務A 啟動的時候生成的爱葵,這時候:找到 (1,3) 的時候施戴,判斷出 row trx_id=101,比高水位大萌丈,處于紅色區(qū)域赞哗,不可見;接著辆雾,找到上一個歷史版本懈玻,一看 row trx_id=102,比高水位大乾颁,處于紅色區(qū)域,不可見艺栈;再往前找英岭,終于找到了(1,1),它的 row trx_id=90湿右,比低水位小诅妹,處于綠色區(qū)域,可見。你看吭狡,去掉數(shù)字對比后尖殃,只用時間先后順序來判斷,分析起來是不是輕松多了划煮。所以送丰,后面我們就都用這個規(guī)則來分析。
更新邏輯
前面說的一致性讀并不對更新語句有效弛秋,當事務中的更新語句是器躏,其看到的數(shù)據(jù)必須是當前的最新值,不然其他事務的操作就會被掩蓋掉蟹略。更新數(shù)據(jù)的時候都是先讀后寫的登失,這個都就是當前讀。除了update語句挖炬,我們也可以讓select語句變成當前讀揽浙。
select * from t where id=1 for update//寫鎖
select * from t where id =1 lock in share mode//讀鎖
一致性視圖
在mysql中利用一致性視圖來實現(xiàn)可重復讀和讀提交。對于讀提交意敛,每次查詢操作都會更新視圖數(shù)組馅巷。
事務的可重復讀是怎么實現(xiàn)的?
事務的可重復讀的核心是一致性讀空闲,一致性讀是通過創(chuàng)建一致性視圖和MVCC來實現(xiàn)的令杈,而對于更新操作,只能用當前讀碴倾。