MVCC简介
一、MVCC簡(jiǎn)介
MVCC (Multiversion Concurrency Control),即多版本并發(fā)控制技術(shù),它使得大部分支持行鎖的事務(wù)引擎,不再單純的使用行鎖來(lái)進(jìn)行數(shù)據(jù)庫(kù)的并發(fā)控制,取而代之的是把數(shù)據(jù)庫(kù)的行鎖與行的多個(gè)版本結(jié)合起來(lái),只需要很小的開(kāi)銷(xiāo),就可以實(shí)現(xiàn)非鎖定讀,從而大大提高數(shù)據(jù)庫(kù)系統(tǒng)的并發(fā)性能
讀鎖:也叫共享鎖、S鎖,若事務(wù)T對(duì)數(shù)據(jù)對(duì)象A加上S鎖,則事務(wù)T可以讀A但不能修改A,其他事務(wù)只能再對(duì)A加S鎖,而不能加X(jué)鎖,直到T釋放A上的S 鎖。這保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對(duì)A做任何修改。
寫(xiě)鎖:又稱(chēng)排他鎖、X鎖。若事務(wù)T對(duì)數(shù)據(jù)對(duì)象A加上X鎖,事務(wù)T可以讀A也可以修改A,其他事務(wù)不能再對(duì)A加任何鎖,直到T釋放A上的鎖。這保證了其他事務(wù)在T釋放A上的鎖之前不能再讀取和修改A。
表鎖:操作對(duì)象是數(shù)據(jù)表。Mysql大多數(shù)鎖策略都支持(常見(jiàn)mysql innodb),是系統(tǒng)開(kāi)銷(xiāo)最低但并發(fā)性最低的一個(gè)鎖策略。事務(wù)t對(duì)整個(gè)表加讀鎖,則其他事務(wù)可讀不可寫(xiě),若加寫(xiě)鎖,則其他事務(wù)增刪改都不行。
行級(jí)鎖:操作對(duì)象是數(shù)據(jù)表中的一行。是MVCC技術(shù)用的比較多的,但在MYISAM用不了,行級(jí)鎖用mysql的儲(chǔ)存引擎實(shí)現(xiàn)而不是mysql服務(wù)器。但行級(jí)鎖對(duì)系統(tǒng)開(kāi)銷(xiāo)較大,處理高并發(fā)較好。
|
一句話(huà)講,MVCC就是用 這里留意到 MVCC 關(guān)鍵的兩個(gè)點(diǎn): 在讀寫(xiě)并發(fā)的過(guò)程中如何實(shí)現(xiàn)多版本; |
二、MVCC實(shí)現(xiàn)原理
innodb MVCC主要是為Repeatable-Read事務(wù)隔離級(jí)別做的。在此隔離級(jí)別下,A、B客戶(hù)端所示的數(shù)據(jù)相互隔離,互相更新不可見(jiàn)
了解innodb的行結(jié)構(gòu)、Read-View的結(jié)構(gòu)對(duì)于理解innodb mvcc的實(shí)現(xiàn)由重要意義
innodb存儲(chǔ)的最基本row中包含一些額外的存儲(chǔ)信息 DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT
6字節(jié)的DATA_TRX_ID 標(biāo)記了最新更新這條行記錄的transaction id,每處理一個(gè)事務(wù),其值自動(dòng)+1
7字節(jié)的DATA_ROLL_PTR 指向當(dāng)前記錄項(xiàng)的rollback segment的undo log記錄,找之前版本的數(shù)據(jù)就是通過(guò)這個(gè)指針
6字節(jié)的DB_ROW_ID,當(dāng)由innodb自動(dòng)產(chǎn)生聚集索引時(shí),聚集索引包括這個(gè)DB_ROW_ID的值,否則聚集索引中不包括這個(gè)值.,這個(gè)用于索引當(dāng)中
DELETE BIT位用于標(biāo)識(shí)該記錄是否被刪除,這里的不是真正的刪除數(shù)據(jù),而是標(biāo)志出來(lái)的刪除。真正意義的刪除是在commit的時(shí)候
具體的執(zhí)行過(guò)程
begin->用排他鎖鎖定該行->記錄redo log->記錄undo log->修改當(dāng)前行的值,寫(xiě)事務(wù)編號(hào),回滾指針指向undo log中的修改前的行
上述過(guò)程確切地說(shuō)是描述了UPDATE的事務(wù)過(guò)程,其實(shí)undo log分insert和update undo log,因?yàn)閕nsert時(shí),原始的數(shù)據(jù)并不存在,所以回滾時(shí)把insert undo log丟棄即可,而update undo log則必須遵守上述過(guò)程
下面分別以select、delete、 insert、 update語(yǔ)句來(lái)說(shuō)明
SELECT
Innodb檢查每行數(shù)據(jù),確保他們符合兩個(gè)標(biāo)準(zhǔn):
1、InnoDB只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行(也就是數(shù)據(jù)行的版本必須小于等于事務(wù)的版本),這確保當(dāng)前事務(wù)讀取的行都是事務(wù)之前已經(jīng)存在的,或者是由當(dāng)前事務(wù)創(chuàng)建或修改的行
2、行的刪除操作的版本一定是未定義的或者大于當(dāng)前事務(wù)的版本號(hào),確定了當(dāng)前事務(wù)開(kāi)始之前,行沒(méi)有被刪除
符合了以上兩點(diǎn)則返回查詢(xún)結(jié)果。
INSERT
InnoDB為每個(gè)新增行記錄當(dāng)前系統(tǒng)版本號(hào)作為創(chuàng)建ID。
DELETE
InnoDB為每個(gè)刪除行的記錄當(dāng)前系統(tǒng)版本號(hào)作為行的刪除ID。
UPDATE
InnoDB復(fù)制了一行。這個(gè)新行的版本號(hào)使用了系統(tǒng)版本號(hào)。它也把系統(tǒng)版本號(hào)作為了刪除行的版本。
說(shuō)明
insert操作時(shí) “創(chuàng)建時(shí)間”=DB_ROW_ID,這時(shí),“刪除時(shí)間 ”是未定義的;
update時(shí),復(fù)制新增行的“創(chuàng)建時(shí)間”=DB_ROW_ID,刪除時(shí)間未定義,舊數(shù)據(jù)行“創(chuàng)建時(shí)間”不變,刪除時(shí)間=該事務(wù)的DB_ROW_ID;
delete操作,相應(yīng)數(shù)據(jù)行的“創(chuàng)建時(shí)間”不變,刪除時(shí)間=該事務(wù)的DB_ROW_ID;
select操作對(duì)兩者都不修改,只讀相應(yīng)的數(shù)據(jù)
三、對(duì)于MVCC的總結(jié)
上述更新前建立undo log,根據(jù)各種策略讀取時(shí)非阻塞就是MVCC,undo log中的行就是MVCC中的多版本,這個(gè)可能與我們所理解的MVCC有較大的出入,一般我們認(rèn)為MVCC有下面幾個(gè)特點(diǎn):
每行數(shù)據(jù)都存在一個(gè)版本,每次數(shù)據(jù)更新時(shí)都更新該版本
修改時(shí)Copy出當(dāng)前版本隨意修改,各個(gè)事務(wù)之間無(wú)干擾
保存時(shí)比較版本號(hào),如果成功(commit),則覆蓋原記錄;失敗則放棄copy(rollback)
就是每行都有版本號(hào),保存時(shí)根據(jù)版本號(hào)決定是否成功,聽(tīng)起來(lái)含有樂(lè)觀鎖的味道,而Innodb的實(shí)現(xiàn)方式是:
事務(wù)以排他鎖的形式修改原始數(shù)據(jù)
把修改前的數(shù)據(jù)存放于undo log,通過(guò)回滾指針與主數(shù)據(jù)關(guān)聯(lián)
修改成功(commit)啥都不做,失敗則恢復(fù)undo log中的數(shù)據(jù)(rollback)
二者最本質(zhì)的區(qū)別是,當(dāng)修改數(shù)據(jù)時(shí)是否要排他鎖定,如果鎖定了還算不算是MVCC?
Innodb的實(shí)現(xiàn)真算不上MVCC,因?yàn)椴](méi)有實(shí)現(xiàn)核心的多版本共存,undo log中的內(nèi)容只是串行化的結(jié)果,記錄了多個(gè)事務(wù)的過(guò)程,不屬于多版本共存。但理想的MVCC是難以實(shí)現(xiàn)的,當(dāng)事務(wù)僅修改一行記錄使用理想的MVCC模式是沒(méi)有問(wèn)題的,可以通過(guò)比較版本號(hào)進(jìn)行回滾;但當(dāng)事務(wù)影響到多行數(shù)據(jù)時(shí),理想的MVCC據(jù)無(wú)能為力了。
比如,如果Transaciton1執(zhí)行理想的MVCC,修改Row1成功,而修改Row2失敗,此時(shí)需要回滾Row1,但因?yàn)镽ow1沒(méi)有被鎖定,其數(shù)據(jù)可能又被Transaction2所修改,如果此時(shí)回滾Row1的內(nèi)容,則會(huì)破壞Transaction2的修改結(jié)果,導(dǎo)致Transaction2違反ACID。
理想MVCC難以實(shí)現(xiàn)的根本原因在于企圖通過(guò)樂(lè)觀鎖代替二段提交。修改兩行數(shù)據(jù),但為了保證其一致性,與修改兩個(gè)分布式系統(tǒng)中的數(shù)據(jù)并無(wú)區(qū)別,而二提交是目前這種場(chǎng)景保證一致性的唯一手段。二段提交的本質(zhì)是鎖定,樂(lè)觀鎖的本質(zhì)是消除鎖定,二者矛盾,故理想的MVCC難以真正在實(shí)際中被應(yīng)用,Innodb只是借了MVCC這個(gè)名字,提供了讀的非阻塞而已。
參考鏈接:https://www.cnblogs.com/huacheng/p/11830901.html
聯(lián)系方式
總結(jié)
- 上一篇: 煤气灶什么牌子好 选购煤气灶的实用指南?
- 下一篇: 数据库迁移神器——Flyway