如何修改id 白卡 面試官 MVCC是如何實現的?

2021-10-14 20:42:49 字數 4024 閱讀 2595

mvcc即多版本併發控制,通過讀取指定版本的歷史記錄,並通過一些手段保證讀取的記錄值符合事務所處的隔離級別,在不加鎖的情況下解決讀寫衝突

如果小夥伴對mvcc不熟,估計看了這句話會有點懵,沒事,等看完這篇文章你就能看懂這句話了

對於使用innodb儲存引擎的表來說,聚集索引記錄中都包含下面2個必要的隱藏列

trx_id:乙個事務每次對某條聚集索引記錄進行改動時,都會把該事務的事務id賦值給trx_id隱藏列

roll_pointer:每次對某條聚集索引記錄進行改動時,都會把舊的版本寫入undo日誌中。這個隱藏列就相當於乙個指標,通過他找到該記錄修改前的資訊

如果乙個記錄的name從貂蟬被依次改為王昭君,西施,會有如下的記錄,多個記錄構成了乙個版本鏈

先回顧一下隔離級別的概念,這樣看後面的內容不至於發懵

√ 為會發生,×為不會發生

建立如下表

create table `account` (

`id` int(2) not null auto_increment,

`name` varchar(10) default null,

`balance` int(3) default '0',

primary key (`id`)

) engine=innodb auto_increment=4 default charset=utf8mb4;

表中的資料如下,設定隔離級別為讀已提交

不可重複讀是指在事務1內,讀取了乙個資料,事務1還沒有結束時,事務2也訪問了這個資料,修改了這個資料,並提交。緊接著,事務1又讀這個資料。由於事務2的修改,那麼事務1兩次讀到的的資料可能是不一樣的,因此稱為是不可重複讀。
表中的資料如下,設定隔離級別為可重複讀

仔細看這個例子和上面的例子在t3時間段的輸出,理解了什麼叫可重複讀了吧?當我們將當前會話的隔離級別設定為可重複讀的時候,當前會話可以重複讀,就是每次讀取的結果集都相同,而不管其他事務有沒有提交。

我當初做完這個實驗的時候,我都蒙蔽了,mysql是如何支援這兩種隔離級別的?我們接著往下看

為了判斷版本鏈中哪個版本對當前事務是可見的,mysql設計出了readview的概念。4個重要的內容如下

m_ids:在生成readview時,當前系統中活躍的事務id列表min_trx_id:在生成readview時,當前系統中活躍的最小的事務id,也就是m_ids中的最小值max_trx_id:在生成readview時,系統應該分配給下乙個事務的事務id值creator_trx_id:生成該readview的事務的事務id

當對表中的記錄進行改動時,執行insert,delete,update這些語句時,才會為事務分配唯一的事務id,否則乙個事務的事務id值預設為0。

max_trx_id並不是m_ids中的最大值,事務id是遞增分配的。比如現在有事務id為1,2,3這三個事務,之後事務id為3的事務提交了,當有乙個新的事務生成readview時,m_ids的值就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4

mvcc判斷版本鏈中哪個版本對當前事務是可見的過程如下

執行過程如下:

如果被訪問版本的trx_id=creator_id,意味著當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問

如果被訪問版本的trx_id被訪問版本的trx_id>=max_trx_id,表明生成該版本的事務在當前事務生成readview後才開啟,該版本不可以被當前事務訪問

被訪問版本的trx_id是否在m_ids列表中

4.1 是,建立readview時,該版本還是活躍的,該版本不可以被訪問。順著版本鏈找下乙個版本的資料,繼續執行上面的步驟判斷可見性,如果最後乙個版本還不可見,意味著記錄對當前事務完全不可見

4.2 否,建立readview時,生成該版本的事務已經被提交,該版本可以被訪問

看著圖有點懵?是時候來個例子了

建立如下表

create table `girl` (

`id` int(11) not null,

`name` varchar(255),

`age` int(11),

primary key (`id`)

) engine=innodb default charset=utf8;

read committed(讀已提交),每次讀取資料前都生成乙個readview下面是3個事務執行的過程,一行代表乙個時間點

先分析一下5這個時間點select的執行過程

系統中有兩個事務id分別為100,200的事務正在執行

執行select語句時生成乙個readview,mids=[100,200],min_trx_id=100,max_trx_id=201,creator_trx_id=0(select這個事務沒有執行更改操作,事務id預設為0)

最新版本的name列為西施,該版本trx_id值為100,在mids列表中,不符合可見性要求,根據roll_pointer跳到下乙個版本

下乙個版本的name列王昭君,該版本的trx_id值為100,也在mids列表內,因此也不符合要求,繼續跳到下乙個版本

下乙個版本的name列為貂蟬,該版本的trx_id值為10,小於min_trx_id,因此最後返回的name值為貂蟬

再分析一下8這個時間點select的執行過程

系統中有乙個事務id為200的事務正在執行(事務id為100的事務已經提交)

執行select語句時生成乙個readview,mids=[200],min_trx_id=200,max_trx_id=201,creator_trx_id=0

最新版本的name列為楊玉環,該版本trx_id值為200,在mids列表中,不符合可見性要求,根據roll_pointer跳到下乙個版本

下乙個版本的name列為西施,該版本的trx_id值為100,小於min_trx_id,因此最後返回的name值為西施

當事務id為200的事務提交時,查詢得到的name列為楊玉環。

repeatable read(可重複讀),在第一次讀取資料時生成乙個readview

可重複讀因為只在第一次讀取資料的時候生成readview,所以每次讀到的是相同的版本,即name值一直為貂蟬,具體的過程上面已經演示了兩遍了,我這裡就不重複演示了,相信你一定會自己分析了。

如何當好面試官

今年面試的人比較多,加起來快一百人了。由於面試任務比較多,也有越來越多的小夥伴加入了面試官的行列。總結一些面試相關的方 希望新晉面試官有些幫助,最終能高效面試。面試官的目標是為組織找到合適的人,一切行為都是圍繞這個主體來運作的。我們現在的面試還是類似於考試,這是一種能夠在短時間內高效選擇到合格面試者...

測試面試,面試官問如何測試電梯

面試官問你 怎麼測試電梯 回答思路 以電梯為例 1 那麼首先,你要反問面試官,需求是什麼樣的,比如測什麼樣的電梯,是普通電梯,觀光電梯,還是其他 2 如果回答沒有,那麼你的思路應該就是 沒有需求文件,但我了解電梯的基本業務功能,以此依據,從下面幾個方面進行分析 功能測試 單個功能,邏輯業務 功能互動...

面試官 如何控制多執行緒執行順序?

先看如下 public class test static thread thread2 newthread static thread thread3 newthread public static void main string args throws interruptedexception...