Mysql中的MVCC_第1頁
Mysql中的MVCC_第2頁
Mysql中的MVCC_第3頁
Mysql中的MVCC_第4頁
Mysql中的MVCC_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、mysql 中的 mvcc mysql 到底是怎么實(shí)現(xiàn)mvcc 的?這個(gè)問題無數(shù)人都在問,但google 中并無答案,本文嘗試從 mysql 源碼中尋找答案。在 mysql 中 mvcc 是在 innodb 存儲(chǔ)引擎中得到支持的,innodb 為每行記錄都實(shí)現(xiàn)了三個(gè)隱藏字段:6 字節(jié)的事務(wù)id(db_trx_id)7 字節(jié)的回滾指針(db_roll_ptr)隱藏的 id 6 字節(jié)的事物id 用來標(biāo)識(shí)該行所述的事務(wù),7 字節(jié)的回滾指針需要了解下innodb 的事務(wù)模型。1. innodb的事務(wù)相關(guān)概念為了支持事務(wù),innbodb 引入了下面幾個(gè)概念:redo log redo log 就是保存執(zhí)

2、行的sql 語句到一個(gè)指定的log 文件,當(dāng) mysql 執(zhí)行 recovery時(shí)重新執(zhí)行redo log 記錄的 sql 操作即可。當(dāng)客戶端執(zhí)行每條sql(更新語句)時(shí), redo log 會(huì)被首先寫入log buffer ;當(dāng)客戶端執(zhí)行commit命令時(shí), log buffer中的內(nèi)容會(huì)被視情況刷新到磁盤。redo log 在磁盤上作為一個(gè)獨(dú)立的文件存在,即innodb 的 log 文件。undo log 與 redo log 相反, undo log 是為回滾而用,具體內(nèi)容就是copy 事務(wù)前的數(shù)據(jù)庫內(nèi)容(行)到undo buffer ,在適合的時(shí)間把undo buffer中的內(nèi)容刷新到

3、磁盤。undo buffer 與 redo buffer一樣,也是環(huán)形緩沖,但當(dāng)緩沖滿的時(shí)候,undo buffer中的內(nèi)容會(huì)也會(huì)被刷新到磁盤;與 redo log 不同的是,磁盤上不存在單獨(dú)的undo log 文件,所有的 undo log 均存放在主ibd 數(shù)據(jù)文件中(表空間),即使客戶端設(shè)置了每表一個(gè)數(shù)據(jù)文件也是如此。rollback segment 回滾段這個(gè)概念來自oracle 的事物模型, 在 innodb 中, undo log 被劃分為多個(gè)段,具體某行的undo log就保存在某個(gè)段中,稱為回滾段??梢哉J(rèn)為undo log 和回滾段是同一意思。鎖innodb 提供了基于行的鎖,

4、如果行的數(shù)量非常大,則在高并發(fā)下鎖的數(shù)量也可能會(huì)比較大,據(jù)innodb 文檔說, innodb 對(duì)鎖進(jìn)行了空間有效優(yōu)化,即使并發(fā)量高也不會(huì)導(dǎo)致內(nèi)存耗盡。對(duì)行的鎖有分兩種:排他鎖、共享鎖。共享鎖針對(duì)讀,排他鎖針對(duì)寫,完全等同讀寫鎖的概念。如果某個(gè)事務(wù)在更新某行(排他鎖),則其他事物無論是讀還是寫本行都必須等待;如果某個(gè)事物讀某行(共享鎖),則其他讀的事物無需等待,而寫事物則需等待。通過共享鎖,保證了多讀之間的無等待性,但是鎖的應(yīng)用又依賴mysql 的事務(wù)隔離級(jí)別。隔離級(jí)別隔離級(jí)別用來限制事務(wù)直接的交互程度,目前有幾個(gè)工業(yè)標(biāo)準(zhǔn):- read_uncommitted:臟讀- read_committ

5、ed:讀提交- repeatable_read:重復(fù)讀- serializable:串行化innodb 對(duì)四種類型都支持,臟讀和串行化應(yīng)用場景不多,讀提交、重復(fù)讀用的比較廣泛,后面會(huì)介紹其實(shí)現(xiàn)方式。2. 行的更新過程下面演示下事務(wù)對(duì)某行記錄的更新過程:1. 初始數(shù)據(jù)行f1f6 是某行列的名字,16 是其對(duì)應(yīng)的數(shù)據(jù)。后面三個(gè)隱含字段分別對(duì)應(yīng)該行的事務(wù)號(hào)和回滾指針,假如這條數(shù)據(jù)是剛insert 的,可以認(rèn)為id 為 1,其他兩個(gè)字段為空。2.事務(wù) 1 更改該行的各字段的值當(dāng)事務(wù) 1 更改該行的值時(shí),會(huì)進(jìn)行如下操作:用排他鎖鎖定該行記錄 redo log 把該行修改前的值copy 到 undo lo

6、g ,即上圖中下面的行修改當(dāng)前行的值,填寫事務(wù)編號(hào),使回滾指針指向undo log 中的修改前的行3.事務(wù) 2 修改該行的值與事務(wù) 1 相同,此時(shí)undo log ,中有有兩行記錄,并且通過回滾指針連在一起。因此,如果undo log一直不刪除,則會(huì)通過當(dāng)前記錄的回滾指針回溯到該行創(chuàng)建時(shí)的初始內(nèi)容,所幸的時(shí)在innodb 中存在 purge 線程,它會(huì)查詢那些比現(xiàn)在最老的活動(dòng)事務(wù)還早的undo log ,并刪除它們,從而保證undo log 文件不至于無限增長。4. 事務(wù)提交當(dāng)事務(wù)正常提交時(shí)innbod 只需要更改事務(wù)狀態(tài)為commit 即可, 不需做其他額外的工作,而 rollback 則稍

7、微復(fù)雜點(diǎn),需要根據(jù)當(dāng)前回滾指針從undo log中找出事務(wù)修改前的版本,并恢復(fù)。 如果事務(wù)影響的行非常多,回滾則可能會(huì)變的效率不高,根據(jù)經(jīng)驗(yàn)值沒事務(wù)行數(shù)在1000 10000 之間, innodb 效率還是非常高的。很顯然,innodb 是一個(gè) commit 效率比rollback 高的存儲(chǔ)引擎。據(jù)說,postgress的實(shí)現(xiàn)恰好與此相反。5. insert undo log 上述過程確切地說是描述了update的事務(wù)過程,其實(shí)undo log 分 insert 和 update undo log, 因?yàn)?insert 時(shí), 原始的數(shù)據(jù)并不存在, 所以回滾時(shí)把insert undo log丟棄

8、即可,而 update undo log 則必須遵守上述過程。3. 事務(wù)級(jí)別眾所周知地是更新(update 、insert 、delete )是一個(gè)事務(wù)過程,在innodb 中,查詢也是一個(gè)事務(wù), 只讀事務(wù)。 當(dāng)讀寫事務(wù)并發(fā)訪問同一行數(shù)據(jù)時(shí),能讀到什么樣的內(nèi)容則依賴事務(wù)級(jí)別:read_uncommitted 讀未提交時(shí),讀事務(wù)直接讀取主記錄,無論更新事務(wù)是否完成read_committed 讀提交時(shí),讀事務(wù)每次都讀取undo log 中最近的版本,因此兩次對(duì)同一字段的讀可能讀到不同的數(shù)據(jù)(幻讀),但能保證每次都讀到最新的數(shù)據(jù)。repeatable_read 每次都讀取指定的版本,這樣保證不會(huì)產(chǎn)

9、生幻讀,但可能讀不到最新的數(shù)據(jù)serializable 鎖表,讀寫相互阻塞,使用較少讀事務(wù)一般有select 語句觸發(fā),在innodb 中保證其非阻塞,但帶for update的select 除外,帶for update的 select 會(huì)對(duì)行加排他鎖,等待更新事務(wù)完成后讀取其最新內(nèi)容。就整個(gè)innodb 的設(shè)計(jì)目標(biāo)來說,就是提供高效的、非阻塞的查詢操作。4. mvcc 上述更新前建立undo log ,根據(jù)各種策略讀取時(shí)非阻塞就是mvcc ,undo log 中的行就是mvcc 中的多版本, 這個(gè)可能與我們所理解的mvcc 有較大的出入, 一般我們認(rèn)為mvcc有下面幾個(gè)特點(diǎn):每行數(shù)據(jù)都存在一

10、個(gè)版本,每次數(shù)據(jù)更新時(shí)都更新該版本修改時(shí) copy 出當(dāng)前版本隨意修改,個(gè)事務(wù)之間無干擾保存時(shí)比較版本號(hào), 如果成功(commit ) , 則覆蓋原記錄; 失敗則放棄copy ( rollback )就是每行都有版本號(hào),保存時(shí)根據(jù)版本號(hào)決定是否成功,聽起來含有樂觀鎖的味道。,而 innodb 的實(shí)現(xiàn)方式是:事務(wù)以排他鎖的形式修改原始數(shù)據(jù)把修改前的數(shù)據(jù)存放于undo log ,通過回滾指針與主數(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)

11、真算不上mvcc ,因?yàn)椴]有實(shí)現(xiàn)核心的多版本共存,undo log 中的內(nèi)容只是串行化的結(jié)果,記錄了多個(gè)事務(wù)的過程,不屬于多版本共存。但理想的mvcc 是難以實(shí)現(xiàn)的,當(dāng)事務(wù)僅修改一行記錄使用理想的mvcc 模式是沒有問題的,可以通過比較版本號(hào)進(jìn)行回滾;但當(dāng)事務(wù)影響到多行數(shù)據(jù)時(shí),理想的mvcc 據(jù)無能為力了。比如,如果transaciton1執(zhí)行理想的mvcc ,修改 row1 成功,而修改row2 失敗,此時(shí)需要回滾 row1 ,但因?yàn)閞ow1 沒有被鎖定,其數(shù)據(jù)可能又被transaction2所修改,如果此時(shí)回滾 row1 的內(nèi)容,則會(huì)破壞 transaction2的修改結(jié)果,導(dǎo)致 transaction2違反 acid 。理想 mvcc 難以實(shí)現(xiàn)的根本原因在于企圖通過樂觀鎖代替二段提交。修改兩行數(shù)據(jù),但為了保證其一致性, 與修改兩個(gè)分布式系統(tǒng)中的數(shù)據(jù)并無區(qū)別,而二提交是目前這種場景保證一致性的唯一手段。二段提交的本質(zhì)是鎖定,樂觀鎖的本質(zhì)是消除鎖定

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論