欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL的多版本并發(fā)控制MVCC的實(shí)現(xiàn)

 更新時(shí)間:2021年12月27日 15:40:07   作者:扭轱轆胖虎  
MVCC就是多版本并發(fā)控制,本文主要介紹了MySQL的多版本并發(fā)控制MVCC的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

什么是MVCC

MVCC就是多版本并發(fā)控制。

MySQL的事務(wù)型存儲(chǔ)引擎通過(guò)多版本并發(fā)控制(MVCC)來(lái)提升并發(fā)性能。

可以認(rèn)為MVCC是行級(jí)鎖的一個(gè)變種,但是它在大多數(shù)情況下避免了加鎖操作,同時(shí)實(shí)現(xiàn)非阻塞的讀操作,因此開(kāi)銷(xiāo)更低。

MVCC是通過(guò)保存數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)的快照來(lái)實(shí)現(xiàn)的,核心思想就是保存數(shù)據(jù)的歷史版本,通過(guò)對(duì)數(shù)據(jù)行的多個(gè)版本管理來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的并發(fā)控制。

這樣我們就可以通過(guò)比較版本號(hào)決定數(shù)據(jù)是否顯示出來(lái),讀取數(shù)據(jù)的時(shí)候不需要加鎖也可以保證事務(wù)的隔離效果。

MVCC的實(shí)現(xiàn)

實(shí)際上,InnoDB 會(huì)在每行記錄后面增加三個(gè)隱藏字段:

  • ROW_ID:行ID,隨著插入新行而單調(diào)遞增,如果有主鍵,則不會(huì)包含該列。
  • TRX_ID:記錄插入或更新該行的事務(wù)的事務(wù)ID。
  • ROLL_PTR:回滾指針,指向 undo log 記錄。每次對(duì)某條記錄進(jìn)行改動(dòng)時(shí),該列會(huì)存一個(gè)指針,可以通過(guò)這個(gè)指針找到該記錄修改前的信息。當(dāng)某條記錄被多次修改時(shí),該行記錄會(huì)存在多個(gè)版本,通過(guò) ROLL_PTR 鏈接形成一個(gè)類(lèi)似版本鏈的概念。

以 RR 級(jí)別為例:

每開(kāi)啟一個(gè)事務(wù)時(shí),系統(tǒng)會(huì)給該事務(wù)分配一個(gè)事務(wù) Id,在該事務(wù)執(zhí)行第一 個(gè) select 語(yǔ)句的時(shí)候,會(huì)生成一個(gè)當(dāng)前時(shí)間點(diǎn)的事務(wù)快照 ReadView,主要包含以下幾個(gè)屬性:

  • m_ids:表示生成ReadView時(shí),當(dāng)前系統(tǒng)中未提交的讀寫(xiě)事務(wù)的事務(wù)id列表。
  • min_trx_id:表示生成ReadView時(shí),當(dāng)前系統(tǒng)中未提交的讀寫(xiě)事務(wù)中最小的事務(wù)id,也就是m_ids中的最小值。
  • max_trx_id:表示生成ReadView時(shí),系統(tǒng)中應(yīng)該分配給下一個(gè)事務(wù)的id值。
  • creator_trx_id:表示生成ReadView時(shí),該事務(wù)的事務(wù)id。

有了這個(gè) ReadView,這樣在訪問(wèn)某條記錄時(shí),只需要按照下邊的步驟判斷記錄的某個(gè)版本是否可見(jiàn):

  • trx_id == creator_trx_id:可以訪問(wèn)這個(gè)版本。
  • trx_id < min_trx_id :可以訪問(wèn)這個(gè)版本。
  • trx_id > max_trx_id:不可以訪問(wèn)這個(gè)版本。
  • min_trx_id <= trx_id <= max_trx_id :如果trx_id是在m_ids中,不可以訪問(wèn)這個(gè)版本,反之可用。

在進(jìn)行判斷時(shí),首先會(huì)拿記錄的最新版本來(lái)比較,如果該版本無(wú)法被當(dāng)前事務(wù)看到,則通過(guò)記錄的 ROLL_PTR 找到上一個(gè)版本,重新進(jìn)行比較,直到找到一個(gè)能被當(dāng)前事務(wù)看到的版本。
而對(duì)于刪除,其實(shí)就是一種特殊的更新,InnoDB 用一個(gè)額外的標(biāo)記位 delete_bit 標(biāo)識(shí)是否刪除。當(dāng)我們?cè)谶M(jìn)行判斷時(shí),會(huì)檢查下 delete_bit 是否被標(biāo)記,如果是,則跳過(guò)該版本,通過(guò) ROLL_PTR 拿到下一個(gè)版本進(jìn)行判斷。

以上內(nèi)容是對(duì)于 RR 級(jí)別來(lái)說(shuō),而對(duì)于 RC 級(jí)別,其實(shí)整個(gè)過(guò)程幾乎一樣,唯一不同的是生成 ReadView 的時(shí)機(jī), RR 級(jí)別只在事務(wù)開(kāi)始時(shí)生成一次,之后一直使用該 ReadView。而 RC 級(jí)別則在每次 select 時(shí),都會(huì)生成一個(gè) ReadView。

MVCC 有沒(méi)有解決幻讀?

幻讀:在一個(gè)事務(wù)中使用相同的 SQL 進(jìn)行兩次讀取,第二次讀取到了其他事務(wù)新插入的行。
例如:

1)事務(wù) 1 第一次查詢(xún):select * from user where id < 10 時(shí)查到了 id = 1 的數(shù)據(jù)

2)事務(wù) 2 插入了 id = 2 的數(shù)據(jù)

3)事務(wù) 1 使用同樣的語(yǔ)句第二次查詢(xún)時(shí),查到了 id = 1、id = 2 的數(shù)據(jù),出現(xiàn)了幻讀。

談到幻讀,首先我們要引入“當(dāng)前讀”和“快照讀”的概念。

  • 快照讀:生成一個(gè)事務(wù)快照(ReadView),之后都從這個(gè)快照獲取數(shù)據(jù)。普通 select 語(yǔ)句就是快照讀。
  • 當(dāng)前讀:讀取數(shù)據(jù)的最新版本。常見(jiàn)的 update/insert/delete、還有 select ... for update、select ... lock in share mode 都是當(dāng)前讀。

對(duì)于快照讀,MVCC 因?yàn)閺?ReadView 讀取,所以必然不會(huì)看到新插入的行,所以天然就解決了幻讀的問(wèn)題。

而對(duì)于當(dāng)前讀的幻讀,MVCC 是無(wú)法解決的。需要使用 Gap Lock 或 Next-Key Lock(Gap Lock + Record Lock)來(lái)解決。

其實(shí)原理也很簡(jiǎn)單,用上面的例子稍微修改下以觸發(fā)當(dāng)前讀:

select * from user where id < 10 for update

當(dāng)使用了 Gap Lock 時(shí),Gap 鎖會(huì)鎖住 id < 10 的整個(gè)范圍,因此其他事務(wù)無(wú)法插入 id < 10 的數(shù)據(jù),從而防止了幻讀。

到此這篇關(guān)于MySQL的多版本并發(fā)控制MVCC的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL多版本并發(fā)控制MVCC內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL為JSON字段創(chuàng)建索引方式(Multi-Valued?Indexes?多值索引)

    MySQL為JSON字段創(chuàng)建索引方式(Multi-Valued?Indexes?多值索引)

    這篇文章主要介紹了MySQL為JSON字段創(chuàng)建索引方式(Multi-Valued?Indexes?多值索引),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Oracle 和 mysql的9點(diǎn)區(qū)別

    Oracle 和 mysql的9點(diǎn)區(qū)別

    這篇文章主要介紹了Oracle 和 mysql的9點(diǎn)區(qū)別,需要的朋友可以參考下
    2014-04-04
  • MySQL 關(guān)于表復(fù)制 insert into 語(yǔ)法的詳細(xì)介紹

    MySQL 關(guān)于表復(fù)制 insert into 語(yǔ)法的詳細(xì)介紹

    本篇文章是對(duì)MySQL中關(guān)于表復(fù)制insert into語(yǔ)法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • MySQL用戶(hù)權(quán)限設(shè)置保護(hù)數(shù)據(jù)庫(kù)安全

    MySQL用戶(hù)權(quán)限設(shè)置保護(hù)數(shù)據(jù)庫(kù)安全

    MySQL用戶(hù)權(quán)限設(shè)置是保護(hù)數(shù)據(jù)庫(kù)安全的重要措施之一。通過(guò)為用戶(hù)設(shè)置不同的權(quán)限,可以控制用戶(hù)對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)能力,包括讀取、修改、刪除、創(chuàng)建等操作。合理設(shè)置用戶(hù)權(quán)限可以避免誤操作、非法訪問(wèn)等安全問(wèn)題
    2023-05-05
  • 詳解GaussDB for MySQL性能優(yōu)化

    詳解GaussDB for MySQL性能優(yōu)化

    GaussDB(for MySQL)數(shù)據(jù)庫(kù)在寫(xiě)入性能上,在業(yè)界同類(lèi)產(chǎn)品中是最好的,這主要得益于GaussDB(for MySQL)在MySQL內(nèi)核方面的諸多優(yōu)化。其中有一項(xiàng)從“送快遞”得來(lái)靈感的優(yōu)化——事務(wù)異步提交,值得我們分析。
    2021-05-05
  • MySQL中由load data語(yǔ)句引起死鎖的解決案例

    MySQL中由load data語(yǔ)句引起死鎖的解決案例

    這篇文章主要介紹了MySQL中由load data語(yǔ)句引起死鎖的解決案例,文中講到了InnoDB引擎的數(shù)據(jù)表中一些鎖的機(jī)制,需要的朋友可以參考下
    2016-01-01
  • mysql 教程 存儲(chǔ)過(guò)程

    mysql 教程 存儲(chǔ)過(guò)程

    最近用mysql + asp.net來(lái)寫(xiě)網(wǎng)站,既然mysql已經(jīng)支持存儲(chǔ)過(guò)程了,那么像分頁(yè)這么常用的東西,當(dāng)然要用存儲(chǔ)過(guò)程啦
    2009-06-06
  • MySQL 5.6 如何更改安全的處理密碼探討

    MySQL 5.6 如何更改安全的處理密碼探討

    MySQL 5.6將會(huì)自動(dòng)的在日志中隱藏密碼信息,接下來(lái)為你詳細(xì)介紹下MySQL 5.6 如何更安全的處理密碼,感興趣的你可以參考下哈,希望可以幫助到你
    2013-03-03
  • Mysql ERROR 1577錯(cuò)誤解決方法

    Mysql ERROR 1577錯(cuò)誤解決方法

    這篇文章主要介紹了Mysql ERROR 1577錯(cuò)誤解決方法,一般是在升級(jí)mysql后會(huì)發(fā)生這個(gè)錯(cuò)誤,錯(cuò)誤原因是需要升級(jí)MySQL系統(tǒng)表,需要的朋友可以參考下
    2014-08-08
  • 全面解讀MySQL主從復(fù)制,從原理到安裝配置

    全面解讀MySQL主從復(fù)制,從原理到安裝配置

    這篇文章主要介紹了MySQL主從復(fù)制的相關(guān)資料,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2020-08-08

最新評(píng)論