MySQL最牛的RR隔離級別,是如何基於ReadView機制實現的?

前言

面試高頻題,首先要理解ReadView,而後要區別可重複讀和提交讀ReadView的不一樣點面試

ReadView

m_ids:表示在生成READVIEW時當前系統中活躍的讀寫事務的事務id列表,活躍的是指當前系統中那些還沒有提交的事務;
min_trx_id:表示在生成READVIEW時當前系統中活躍的讀寫事務中最小的事務id,也就是m_ids中的最小值;
max_trx_id:表示生成READVIEW時系統中應該分配給下一個事務的事務id值,因爲事務id通常是遞增分配的,因此max_trx_id就是m_ids中最大的那個id再加上1;
creator_trx_id:表示生成該READVIEW的事務id,因爲只有在對錶中記錄作改動(增刪改)時纔會爲事務分配事務id,因此在一個讀取數據的事務中的事務id默認爲0;post

讀取規則

一、版本的trx_id==READVIEW中的creator_trx_id,表示當前讀事務正在讀取被本身修改過的記錄,該版本能夠被當前事務訪問;
二、版本trx_id < min_trx_id,代表生成該版本的事務在當前事務生成READVIEW前已經提交了,因此該版本能夠被當前事務訪問;
三、版本的trx_id > max_trx_id,代表生成該版本的事務在當前事務生成READVIEW後纔開啓的,該版本不可被當前事務訪問;
四、版本的trx_id在READVIEW的min_trx_id和max_trx_id之間,那就須要判斷一下trx_id屬性值是否是在m_ids中。若是在這個範圍內,說明建立READVIEW時該事務還處於活躍狀態,該版本不能夠被當前事務訪問;若是不在,說明建立READVIEW時生成該版本的事務已經被提交,該版本能夠被當前事務訪問;學習

原理

基於ReadView機制能夠實現RC隔離級別,即每次查詢的時候都生成一個ReadView,這樣的話,只要在此次查詢以前有別的事務提交了( m_ids 列表發生變換),那麼別的事務更新的數據,是能夠看到的。spa

那麼若是是RR級別呢?RR級別下,這個事務讀一條數據,不管讀多少次,都是一個值,別的事務修改數據以後哪怕提交了,也是看不到人家修改的值的,這就避免了不可重複讀的問題。同時若是別的事務插入了一些新的數據,也是讀不到的,這樣就能夠避免幻讀的問題。指針

例子

首先假設有一條數據是事務id=50的一個事務插入的,同時此時有事務A和事務B同時在運行,事務A的id是60,事務B的id是70,以下圖所示:視頻

這個時候,事務A發起了一個查詢,它就是第一次查詢就會生成一個ReadView,此時ReadView裏的creator_trx_id是60,min_trx_id是60,max_trx_id是71,m_ids是[60, 70],此時ReadView以下圖所示: blog

這個時候事務A基於這個ReadView去查這條數據,會發現這條數據的trx_id爲50,是小於ReadView裏的min_trx_id的,說明它發起查詢以前,早就有事務插入這條數據還提交了,因此此時能夠查到這條原始值的,以下圖: 教程

接着就是事務B此時更新了這條數據的值爲值B,此時會修改trx_id爲70,同時生成一個undo log,並且關鍵是事務B此時它還提交了,也就是說此時事務B已經結束了,以下圖所示: 事務

事務A去查詢這條數據的值,會驚訝的發現此時數據的trx_id是70了,由於在RR級別,ReadView不會改變,根據ReadView的讀取規則能夠知道事務A不能查到txr_id=70對應的數據,而是會順着undo指針找到原始值,因此事務A在事務B修改數據的先後讀取的數據是同樣的。rem

參考:《2020最新Java基礎精講視頻教程和學習路線!》
連接:https://juejin.cn/post/693721...

相關文章
相關標籤/搜索