溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

InnoDB MVCC實(shí)現(xiàn)原理及源碼解析

發(fā)布時(shí)間:2020-07-11 15:03:25 來源:網(wǎng)絡(luò) 閱讀:15464 作者:yzs的專欄 欄目:MySQL數(shù)據(jù)庫

1、原理介紹

數(shù)據(jù)多版本(MVCC)是MySQL實(shí)現(xiàn)高性能的一個(gè)主要的一個(gè)主要方式,通過對(duì)普通的SELECT不加鎖,直接利用MVCC讀取指版本的值,避免了對(duì)數(shù)據(jù)重復(fù)加鎖的過程。InnoDB支持MVCC多版本,其中RC和RR隔離級(jí)別是利用consistent read view方式支持的,即在某個(gè)時(shí)刻對(duì)事物系統(tǒng)打快照記下所有活躍讀寫事務(wù)ID,之后讀操作根據(jù)事務(wù)ID與快照中的事務(wù)ID進(jìn)行比較,判斷可見性。

2、InnoDB數(shù)據(jù)行結(jié)構(gòu)

行結(jié)構(gòu)中,除了用戶定義的列外還有3個(gè)系統(tǒng)列:DATA_ROW_ID、DATA_TRX_ID、DATA_ROLL_PTR,如果表沒有定義主鍵那么DATA_ROW_ID作為主鍵列,否則行結(jié)構(gòu)中沒有DATA_ROW_ID列。其中:

DATA_TRX_ID:修改該行數(shù)據(jù)的事務(wù)的ID

DATA_ROLL_PTR:指向該行回滾段的指針。

整個(gè)MVCC實(shí)現(xiàn),關(guān)鍵靠這2個(gè)字段來完成。

3、READ-VIEW原理流程
InnoDB MVCC實(shí)現(xiàn)原理及源碼解析
4、READ-VIEW解讀

1)read view是和SQL語句綁定的,在每個(gè)SQL語句執(zhí)行前申請(qǐng)或獲?。≧R隔離級(jí)別:事務(wù)第一個(gè)select申請(qǐng),之后都用這個(gè);RC隔離級(jí)別:每個(gè)select都會(huì)申請(qǐng))

2)read view結(jié)構(gòu)

struct read_view_t{  
    ulint       type;   /*!< VIEW_NORMAL, VIEW_HIGH_GRANULARITY */  
    undo_no_t   undo_no;/*!< 0 or if type is  
                VIEW_HIGH_GRANULARITY  
                transaction undo_no when this high-granularity  
                consistent read view was created */  
    trx_id_t    low_limit_no;  
                /*!< The view does not need to see the undo  
                logs for transactions whose transaction number  
                is strictly smaller (<) than this value: they  
                can be removed in purge if not needed by other  
                views */  
    trx_id_t    low_limit_id;  
                /*!< The read should not see any transaction  
                with trx id >= this value. In other words,  
                this is the "high water mark". */  
    trx_id_t    up_limit_id;  
                /*!< The read should see all trx ids which  
                are strictly smaller (<) than this value.  
                In other words,  
                this is the "low water mark". */  
    ulint       n_trx_ids;  
                /*!< Number of cells in the trx_ids array */  
    trx_id_t*   trx_ids;/*!< Additional trx ids which the read should  
                not see: typically, these are the read-write  
                active transactions at the time when the read  
                is serialized, except the reading transaction  
                itself; the trx ids in this array are in a  
                descending order. These trx_ids should be  
                between the "low" and "high" water marks,  
                that is, up_limit_id and low_limit_id. */  
    trx_id_t    creator_trx_id;  
                /*!< trx id of creating transaction, or  
                0 used in purge */  
    UT_LIST_NODE_T(read_view_t) view_list;  
                /*!< List of read views in trx_sys */  
};  

主要包括3個(gè)成員{low_limit_id,up_limit_id,trx_ids}。

low_limit_id:表示創(chuàng)建read view時(shí),當(dāng)前事務(wù)活躍讀寫鏈表最大的事務(wù)ID,即最近創(chuàng)建的除自身外最大的事務(wù)ID

up_limit_id:表示創(chuàng)建read view時(shí),當(dāng)前事務(wù)活躍讀寫鏈表最小的事務(wù)ID。

trx_ids:創(chuàng)建read view時(shí),活躍事務(wù)鏈表里所有事務(wù)ID

3)對(duì)于小于等于RC的隔離級(jí)別,每次SQL語句結(jié)束后都會(huì)調(diào)用read_view_close_for_mysql將read view從事務(wù)中刪除,這樣在下一個(gè)SQL語句啟動(dòng)時(shí),會(huì)判斷trx->read_view為NULL,從而重新申請(qǐng)。對(duì)于RR隔離級(jí)別,則SQL語句結(jié)束后不會(huì)刪除read_view,從而下一個(gè)SQL語句時(shí),使用上次申請(qǐng)的,這樣保證事務(wù)中的read view都一樣,從而實(shí)現(xiàn)可重復(fù)讀的隔離級(jí)別。

4)對(duì)于可見性判斷,分配聚集索引和二級(jí)索引。聚集索引:

 記錄的DATA_TRX_ID < view->up_limit_id:在創(chuàng)建read view時(shí),修改該記錄的事務(wù)已提交,該記錄可見

DATA_TRX_ID >= view->low_limit_id:當(dāng)前事務(wù)啟動(dòng)后被修改,該記錄不可見

DATA_TRX_ID 位于(view->up_limit_id,view->low_limit_id):需要在活躍讀寫事務(wù)數(shù)組查找trx_id是否存在,如果存在,記錄對(duì)于當(dāng)前read view是不可見的。

二級(jí)索引:

由于InnoDB的二級(jí)索引只保存page最后更新的trx_id,當(dāng)利用二級(jí)索引進(jìn)行查詢的時(shí)候,如果page的trx_id小于view->up_limit_id,可以直接判斷page的所有記錄對(duì)于當(dāng)前view是可見的,否則需要回clustered索引進(jìn)行判斷。

5)如果記錄對(duì)于view不可見,需要通過記錄的DB_ROLL_PTR指針遍歷history list構(gòu)造當(dāng)前view可見版本數(shù)據(jù)

6)start transaction和begin語句執(zhí)行后并沒有在innodb層分配事務(wù)ID、回滾段、read_view、將事務(wù)放到讀寫事務(wù)鏈表等,這個(gè)操作需要第一個(gè)SQL語句調(diào)用函數(shù)trx_start_low來完成,這個(gè)需要注意。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI