MySql Read Commit 和 Repeatable Read非阻塞讀實現原理

讀提交和可重複讀

Read Commit

讀提交,事務可以讀取已經提交的數據。
存在的問題:事務前後讀取不一致。

Repeatable Read

可重複讀,事務前後讀取數據是一致的。
存在的問題:無法處理插入或者刪除的數據。

MySql如何實現讀提交和可重複讀的?

innodb的聚簇索引中有2個隱藏字段,叫做trx_id (transaction id),和roll_pointer
trx_id描述一個事務編號,roll_pointer指向當前數據行的上一個歷史版本,對於insert而言不存在歷史版本
同時存在一個ReadView對象,裏面有個隊列描述當前正在處理的事務id。當有事務讀取時,會先判斷讀取的行是否在這個隊列中,如果存在就不會讀取,會根據roll_pointer讀取上一個版本的數據。
例:當事務id爲100 的事務在修改id爲1的行時,ReadView中隊列會有[100]在裏面,這時另一個事務讀取id 爲1 的數據行會首先發現trx_id 100的 小明2號 數據,隨後會和ReadView的隊列元素比較,發現存在,則隨着roll_pointer去查詢trx_id爲60的數據行 小明1 ,發現60 不在隊列中,於是讀取值爲小明1。

在這裏插入圖片描述

Read Commit的問題復現:

以上圖爲例,當事務trx_id 爲 100 的事務修改 小明1 -> 小明2 時,此時未提交,於是另一個事務B在讀取時會讀取到 小明1,然後trx_id 爲100的事務提交,這時剛纔B又讀了一遍,發現值變成 小明2。

Repeatable Read 復現 Read Commit

當事務trx_id 爲 100 的事務修改 小明1 -> 小明2 時,此時未提交,於是另一個事務B在讀取時會讀取到 小明1,然後trx_id 爲100的事務提交,這時剛纔B又讀了一遍,值還是 小明1。

導致差異的原理

Read Commit在查詢時每次會生成新的ReadView,而Repeatable Read 則只會在第一次查詢時生成ReadView,隨後複用。
這導致Read Commit 每次查詢時那個隊列總是空的,就導致會讀取到剛更新的數據。

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