溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法

發(fā)布時間:2021-06-25 10:33:10 來源:億速云 閱讀:203 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要介紹“傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法”,在日常操作中,相信很多人在傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

        根據(jù)《高性能mysql》一書的描述,mvcc實現(xiàn)應該大致如下:

        1、每行數(shù)據(jù)后面有兩個隱藏的字段,一個字段為更新標識,一個字段為刪除標識,記錄內(nèi)容為更新/刪除時候的系統(tǒng)版本號。

        2、select過程中,會根據(jù)當前事務版本號去過濾小于等于的數(shù)據(jù)。

        3、update操作實際會新增一行記錄,而并非在原數(shù)據(jù)上修改。

        4、delete也并非物理刪除,而是在刪除標識字段上加上版本號。

        然而innodb的mvcc并不盡相同??!

        在innodb中,兩個隱藏字段分別為DATA_TRX_ID、DATA_ROLL_PTR(如果沒有主鍵,則還會多一個隱藏的主鍵列,在一些文章中有看到del_flag字段,但是具體它是一個單獨字段還是DATA_TRX_ID中的一位,目前還沒有搞清楚)。

        DATA_TRX_ID

記錄最近更新這條行記錄的事務 ID,大小為 6 個字節(jié)

        DATA_ROLL_PTR

表示指向該行回滾段(rollback segment)的指針,大小為 7 個字節(jié),InnoDB 便是通過這個指針找到之前版本的數(shù)據(jù)。該行記錄上所有舊版本,在 undo 中都通過鏈表的形式組織,在網(wǎng)上搜了一下,大概格式如下,它記錄的是每個版本被修改的數(shù)據(jù),并非是一條操作的反操作。

傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法

所以,實際上每次進行update操作時,并非是會創(chuàng)建一個新的副本。而是會先將就的數(shù)據(jù)行copy進undo log中去,隨后修改該數(shù)據(jù)行,并且修改其DATA_TRX_ID 和 DATA_ROLL_ID。

        上面說了支撐mvcc功能的列結構,那么下來看一下mysql的四種事務隔離級別和mvcc的關系。

        1.臟讀

        和mvcc沒有關系,每次select最新的數(shù)據(jù),別的事務的數(shù)據(jù)只要已經(jīng)物理寫入或者修改,那么它便會去讀,直接忽略掉后面的DATA_TRX_ID。

        2.提交讀

        在mvcc的使用上,innodb引入了ReadView 這一方式。在生成一個ReadView的時候,會收集所有目前所有活躍事務(既還未提交的事務)的版本號到一個隊列中m_ids,并且把當前系統(tǒng)版本號+1,也加入隊列中。那么就可以找到版本號的最小值up_limit_id和最大值low_limit_id。在select的過程中,對于一條數(shù)據(jù),與m_ids對比,會有如下結果。

        a.小于up_limit_id,說明該事務在ReadView開啟之前已經(jīng)提交,所以為有效數(shù)據(jù)。

        b.大于low_limit_id,說明該事物是在ReadView開啟之后才提交的,為無效數(shù)據(jù),這時候就要順著undo log鏈表向上查找了,直到找到有效的

        c.如果 up_limit_id<id<=low_limit_id,這個時候就要拿到id在m_ids中做比較,如果找到了相同的,則說明ReadView建立時,該事務還未提交,所以為無效數(shù)據(jù),如果找不到,則為有效數(shù)據(jù)。數(shù)據(jù)無效處理方法同b。

        ps.在undo log上查找時,并不是只有data_trx_id小于up_limit_id才為有效,滿足條件c也是可以的。

        那么解釋了innodb如何使用mvcc,那么提交讀就好理解了,它在每次select都會新建一個ReadView,所以兩次select會擁有不同的ReadView,那么兩次對于同一個數(shù)據(jù)的結果是可能不同的。

        3.可重復讀

       同樣用mvcc的可重復讀就更好解釋了,可重復讀只在第一次select的時候建立一次ReadView,在整個事務的周期內(nèi)都使用這個ReadView。所以它就能保證對于同一數(shù)據(jù)查詢總是相同版本號的數(shù)據(jù)。

        4.序列化

        實際上幻讀并非是傳統(tǒng)意義的上的兩次讀取結果不一致,因為從可重復讀的場景上來看。即使是有新的數(shù)據(jù)插入,因為mvcc的原因?qū)嶋H上并不會對兩次的結果產(chǎn)生影響?;米x多發(fā)于 讀-寫 操作,既select * from t1 where id = 1 然后插入id = 1 的數(shù)據(jù),此時有別的事務插入了id = 1,結果報錯,這是mvcc無法解決的問題,所以采取的方案便是序列化執(zhí)行。

        最后說一下兩種數(shù)據(jù)丟失

第一類丟失更新(回滾丟失,Lostupdate) (通過設置隔離級別可以防止 Repeatable Read)

    這類問題產(chǎn)生原因在于由于回滾使得別的事務提交的數(shù)據(jù)被一并拋棄掉了。

第二類丟失更新(覆蓋丟失/兩次更新問題,Second lost update) A事務覆蓋B事務已經(jīng)提交的數(shù)據(jù),造成B事務所做操作丟失:   

    這類問題實際上是由于讀取、更新并非原子操作,在執(zhí)行過程中,可能已經(jīng)別別的事務修改掉了,所以這個時候你用的是一個舊的數(shù)據(jù)進行更新,最終導致數(shù)據(jù)出現(xiàn)錯亂。比如說另外一個已經(jīng)修改為1100,你再來進行修改為1000的基礎上加100,那么這樣就丟失了部分數(shù)據(jù)。

    第一類問題可以通過數(shù)據(jù)庫的隔離級別來解決掉,對于第二類就需要在業(yè)務代碼中進行了,比如采用select for update這樣的操作,或者加上時間版本號來防止問題的發(fā)生。

到此,關于“傳統(tǒng)mvcc和innodb mvcc的實現(xiàn)方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

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

AI