MySQL - 多版本控制 MVCC 机制初探
文章目錄
- 生猛干貨
- MVCC (Multi-Version Concurrency Control)原理
- 快照讀與當(dāng)前讀
- MVCC 多版本實(shí)現(xiàn)
- 總結(jié)
- 搞定MySQL
生猛干貨
帶你搞定MySQL實(shí)戰(zhàn),輕松對應(yīng)海量業(yè)務(wù)處理及高并發(fā)需求,從容應(yīng)對大場面試
MVCC (Multi-Version Concurrency Control)原理
MySQL InnoDB 存儲引擎,實(shí)現(xiàn)的是基于多版本的并發(fā)控制協(xié)議——MVCC,而不是基于鎖的并發(fā)控制。
MVCC 最大的好處是讀不加鎖,讀寫不沖突。在讀多寫少的 OLTP(On-Line Transaction Processing)應(yīng)用中,讀寫不沖突是非常重要的,極大的提高了系統(tǒng)的并發(fā)性能。
快照讀與當(dāng)前讀
在 MVCC 并發(fā)控制中,讀操作可以分為兩類: 快照讀(Snapshot Read)與當(dāng)前讀 (Current Read)。
-
快照讀:讀取的是記錄的可見版本(有可能是歷史版本),不用加鎖。
-
當(dāng)前讀:讀取的是記錄的最新版本,并且當(dāng)前讀返回的記錄,都會加鎖,保證其他事務(wù)不會再并發(fā)修改這條記錄。
MVCC 只在 Read Commited 和 Repeatable Read 兩種隔離級別下工作
如何區(qū)分快照讀和當(dāng)前讀呢? 可以簡單的理解為:
-
快照讀:簡單的 select 操作,屬于快照讀,不需要加鎖。
-
當(dāng)前讀:特殊的讀操作,插入/更新/刪除操作,屬于當(dāng)前讀,需要加鎖。
MVCC 多版本實(shí)現(xiàn)
為了更直觀地理解 MVCC 的實(shí)現(xiàn)原理,這里舉一個“事務(wù)對某行記錄更新的過程”的案例來講解 MVCC 中多版本的實(shí)現(xiàn)。
假設(shè) F1~F6 是表中字段的名字,1~6 是其對應(yīng)的數(shù)據(jù)。后面三個隱含字段分別對應(yīng)該行的隱含ID、事務(wù)號和回滾指針,如下圖所示
-
隱含 ID(DB_ROW_ID),6 個字節(jié),當(dāng)由 InnoDB 自動產(chǎn)生聚集索引時(shí),聚集索引包括這個 DB_ROW_ID 的值
-
事務(wù)號(DB_TRX_ID),6 個字節(jié),標(biāo)記了最新更新這條行記錄的 Transaction ID,每處理一個事務(wù),其值自動 +1
-
回滾指針(DB_ROLL_PT),7 個字節(jié),指向當(dāng)前記錄項(xiàng)的 Rollback Segment 的 Undo log記錄,通過這個指針才能查找之前版本的數(shù)據(jù)
【更新過程】
首先,假如這條數(shù)據(jù)是剛 INSERT 的,可以認(rèn)為 ID 為 1,其他兩個字段為空。
然后,當(dāng)事務(wù) 1 更改該行的數(shù)據(jù)值時(shí),會進(jìn)行如下操作,如下圖所示
-
用排他鎖鎖定該行;記錄 Redo log;
-
把該行修改前的值復(fù)制到 Undo log,即圖中下面的行;
-
修改當(dāng)前行的值,填寫事務(wù)編號,使回滾指針指向 Undo log 中修改前的行
接下來,與事務(wù) 1 相同,此時(shí) Undo log 中有兩行記錄,并且通過回滾指針連在一起。因此,如果 Undo log 一直不刪除,則會通過當(dāng)前記錄的回滾指針回溯到該行創(chuàng)建時(shí)的初始內(nèi)容,所幸的是在 InnoDB 中存在 purge 線程,它會查詢那些比現(xiàn)在最老的活動事務(wù)還早的 Undo log,并刪除它們,從而保證 Undo log 文件不會無限增長,如下圖所示
總結(jié)
MVCC機(jī)制的實(shí)現(xiàn)就是通過read-view機(jī)制與undo版本鏈比對機(jī)制,使得不同的事務(wù)會根據(jù)數(shù)據(jù)版本鏈對比規(guī)則讀取同一條數(shù)據(jù)在版本鏈上的不同版本數(shù)據(jù)。
搞定MySQL
總結(jié)
以上是生活随笔為你收集整理的MySQL - 多版本控制 MVCC 机制初探的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL - 存储引擎初探
- 下一篇: MySQL - 并发事务问题及解决方案