MySQL是怎麼保證資料一致性的
在《寫資料庫同時發mq訊息事務一致性的一種解決方案》一文的方案中把分散式事務巧妙轉成了資料庫事務。我們都知道關係型資料庫事務能保證資料一致性,那資料庫到底是怎麼設計事務這一特性的呢?
一、MySQL事務模型ACID
MySQL是一個多引擎資料庫,其中InnoDB支援資料庫事務,也是最常用的引擎。下邊就介紹InnoDB的事務模型
MySQL官方文件對事務是這麼描述的“事務是可以提交或回滾的原子工作單元。當事務對資料庫進行多個更改時,要麼提交事務時所有更改都成功,要麼回滾事務時撤消所有更改。”
“ACID模型是一組資料庫設計原則,強調業務資料和關鍵應用程式的可靠性很重要。MySQL包含與ACID模型緊密結合的innodb儲存引擎元件,確保資料不會被破壞,結果不會被軟體崩潰和硬體故障等異常情況所篡改。當您依賴ACID的特性,就不再需要重新發明一致性檢查和崩潰恢復機制。”
ACID模型按照字母拆解分為四大特性
A : atomicity 原子性。原子性是我們對事務最直觀的理解:事務就是一系列的操作,要麼全部都執行,要麼全部都不執行。
C : consistency 一致性。資料庫事務不能破壞關係資料的完整性以及業務邏輯上的一致性。例如對銀行轉帳事務,不管事務成功還是失敗,應該保證事務結束後ACCOUNTS表中Tom和Jack的存款和不變。
I : isolation 隔離性。在併發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。
D : durability 永續性。只要事務成功結束,它對資料庫所做的更新就必須永久儲存下來。即使發生系統崩潰,重新啟動資料庫系統後,資料庫還能恢復到事務成功結束時的狀態。
二、InnoDB儲存引擎架構
下邊這張圖是InnoDB的架構,包括兩大部分,記憶體結構(In-Memory Structures)和磁碟上的結構(On-Disk Structures)。
在這張圖中,尤其要關注“Redo Log”和“Undo Tablespaces”這兩個區域,它們跟事務息息相關。
記憶體結構(In-Memory Structures)更多的目的是在提高效能,因此本文不會過多關注。如果感興趣,可以訪問MySQL的官方網站
“Undo Tablespaces”包含Undo Log(撤消日誌),Undo Log是撤消日誌記錄的集合,其中包含如何撤消事務對聚集索引記錄的最新更改的資訊。Undo Log存在於撤消日誌段中,這些日誌段包含在回滾段中。
MySQL事務的四個特性中ACD三個特性是透過Redo Log(重做日誌)和Undo Log 實現的,而 I(隔離性)是透過Lock(鎖)來實現。
三、普及個概念MVCC
MVCC,Multi-Version Concurrency Control,多版本併發控制。這項技術使得InnoDB的事務隔離級別下執行一致性讀操作有了保證,換言之,就是為了查詢一些正在被另一個事務更新的行,並且可以看到它們被更新之前的值。這是一個可以用來增強併發性的強大技術,查詢不用等待另一個事務釋放鎖。這項技術廣泛應用於資料庫,例如Oracle,PostgreSQL。當然也有一些資料庫產品以及mysql的其它儲存引擎不支援它。
看一看MVCC機制的示意圖,圖下邊會給出文字解釋
圖中底部橫軸是時間,縱向的箭頭用來標記增、刪、改、查發生的時刻。尤其注意時間軸上方兩條色塊,代表資料的兩個版本V1、V2。為了醒目,我把V1、V2用紅色方框圈了起來(多版本的體現)。從左向右解讀這張圖
1、T1事務插入資料a=3,然後提交,生成了資料對應的V1版本
2、T2事務開始讀取a資料,讀取會持續一段時間,由於開始讀取的時刻,只有V1版本,所以最終T2讀到a=3
3、T2讀取過程中,T3對資料a進行修改,a=4,生成a資料的V2版本,但此時並未提交,因此生效的是V1版本資料。
4、T3修改提交之前,T4讀取a資料,由於此時V1版本資料生效,因此,T4讀到a=3
5、T3提交a=4的修改,V1版本資料失效,V2生效。a的值變為4
6、T5讀取a的值,讀到V2版本,a=4
至此,MVCC的概念就搞明白了,那麼MySQL是怎麼實現的呢?
四、InnoDB多版本的實現
1、三個隱藏欄位
在內部,InnoDB向資料庫中儲存的每一行資料新增三個欄位。
(1)DB_TRX_ID欄位,6位元組。表示插入或更新行的最後一個事務的事務識別符號。此外,刪除在內部被視為更新,其中行中的特殊位被設定為將其標記為已刪除。
(2)DB_ROLL_PTR欄位,7位元組,叫做回滾指標(roll pointer)。回滾指標指向寫入回滾段的撤消日誌(Undo Log)。如果行已更新,則撤消日誌包含重建更新前該行內容所需的資訊。
(3)DB_ROW_ID欄位,6位元組。包含一個隨著新行插入而單調增加的行ID,如果innodb自動生成聚集索引,則該索引包含行ID值。否則,DB_ROW_ID列不會出現在任何索引中。
2、多版本產生過程
以新增一條記錄並對該記錄進行2次修改來說明具體實現
這條記錄有3個隱含欄位(前面已經介紹),分別應對行的ID、事務號和回滾指標。
當插入的是一條新資料時,記錄上對應的回滾段指標為NULL
這個過程做了以下幾件事
用排他鎖鎖定該行
把該行修改前的值複製到Undo Log中
修改當前行的值,填寫事務編號,使回滾指標指向Undo Log中的修改前的行
記錄Redo Log,包括Undo Log中的變化
多次更新後,回滾指標會把不同版本的記錄串在一起。在InnoDB中存在purge執行緒,它會查詢那些比現在最老的活動事務還早的Undo Log,並刪除它們,從而保證Undo Log檔案不至於無限增長。
3、提交與回滾
當事務正常提交時,InnoDB只需要更改事務狀態為commit即可,不需要做其他額外的工作
回滾(rollback)需要根據當前回滾指標從Undo Log中找出事務修改前的版本,並恢復。如果事務影響的行非常多,回滾則可能會很慢,根據經驗值沒提交的事務行數在1000~10000之間,InnoDB效率還是非常高的(唐成-資料庫多版本實現內幕)。
commit效率高,rollback代價大
4、可見性
事務隔離是資料庫處理的基礎之一,隔離是縮寫ACID中的I。隔離級別是當多個事務同時進行更改和執行查詢時,微調效能、可靠性、一致性和結果再現性之間的平衡的設定。
InnoDB提供SQL1992標準定義的四個隔離級別,READ UNCOMMITTED(未提交讀), READ COMMITTED(已提交讀), REPEATABLE READ(可重複讀), and SERIALIZABLE(可序列化)。預設的是REPEATABLE READ
每種隔離級別具體的意義可以百度查到,實現原理深入進去比較複雜。注意到每條資料隱藏的事務ID欄位DB_TRX_ID有時序性,理論上可以根據一些策略,藉助這個欄位來實現與隔離級別相關的功能。事實上InnoDB也是這麼做的。當然這個功能還涉及很多鎖的問題,這裡不再展開。
MySQL官方文件在“鎖和事務模型”這一章節開始就介紹了InnoDB的鎖,截個目錄,感興趣可以去讀一下。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556438/viewspace-2662580/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- HTTPS是怎麼保證資料安全傳輸的?HTTP
- 如何保證MySQL和Redis資料一致性?MySqlRedis
- MySQL怎麼保證高可用MySql
- 面試重災區:怎麼保證快取與資料庫的雙寫一致性?面試快取資料庫
- exp能在什麼級別保證備份資料的一致性呢?
- Spark CommitCoordinator 保證資料一致性SparkMIT
- 冗餘資料一致性,到底如何保證?
- 資料庫和快取的一致性如何保證資料庫快取
- 如何保證快取和資料庫的一致性?快取資料庫
- 如何保證mongodb和資料庫雙寫資料一致性?MongoDB資料庫
- 【面試普通人VS高手系列】Redis和Mysql如何保證資料一致性面試RedisMySql
- 為什麼延遲刪除可以保證MYSQL 與redis的一致性?MySqlRedis
- WEBAPI怎麼保證安全WebAPI
- Zookeeper 如何保證分散式系統資料一致性分散式
- 使用雙非同步後,如何保證資料一致性?非同步
- 瞅瞅Facebook是怎麼保證CSS程式碼質量的CSS
- 如何保證快取與資料庫的雙寫一致性?快取資料庫
- 保證分散式系統資料一致性的6種方案分散式
- Oracle Goldengate是如何保證資料有序和確保資料不丟失的?OracleGo
- PHP 併發扣款,保證資料一致性(悲觀鎖)PHP
- 趣說 | 資料庫和快取如何保證一致性?資料庫快取
- FAQ系列|如何保證主從複製資料一致性
- 如何保證快取(redis)與資料庫的雙寫一致性快取Redis資料庫
- 如何保證資料新增或修改成功失敗的一致性?
- 面試常問:如何保證Redis快取和資料庫的資料一致性NRXW面試Redis快取資料庫
- APISIX 是怎麼保護使用者的敏感資料不被洩露的?API
- 美團二面:Redis與MySQL雙寫一致性如何保證?RedisMySql
- MySQL 在高併發下的 訂單撮合 系統使用 共享鎖 與 排他鎖 保證資料一致性MySql
- 什麼是備份資料庫?什麼是資料庫一致性備份和非一致性備份?資料庫
- 針對靜默資料錯誤,如何採用DIX和DIF保證資料一致性?
- MySQL資料一致性MySql
- 阿里面試題:如何保證快取與資料庫的雙寫一致性?阿里面試題快取資料庫
- 首個徹底保證快取與資料庫一致性的開源方案快取資料庫
- mysql怎麼清空表中的資料MySql
- mysql 的資料庫同步怎麼配置?MySql資料庫
- MySQL半同步複製資料最終一致性驗證MySql
- mysql order by是怎麼工作的?MySql
- mysql:使用樂觀鎖保護資料一致性和完整性MySql