什么是多版本控制
MySQL的多版本控制(簡稱MVCC)是一種并發控制機制,它允許在不鎖定資源的情況下進行數據的讀取和修改。MVCC通過在數據庫中保存數據的多個版本來實現這一點,使得不同的事務可以訪問他們的數據快照版本來保證數據訪問的安全性
基本概念
1、當前讀和快照讀
在MySQL中,特別是使用InnoDB存儲引擎時,“當前讀”(Current Read)是一種讀取操作,它不僅讀取數據,還會對數據加上適當的鎖,以保證數據的一致性和事務的隔離性。當前讀通常涉及到的是讀取到的最新數據,并且可能對數據加鎖以防止其他事務對數據進行修改。
具體來說,當前讀有以下幾個特點:
- 最新版本:當前讀獲取的是數據的最新版本,可以讀取到其他事務已經提交的更改。
- 加鎖機制:當前讀需要使用排他鎖(寫鎖)來保證數據的一致性,這會影響其他事務對相同數據的并發操作。
- 事務隔離性:不同的隔離級別(如READ COMMITTED、REPEATABLE READ、SERIALIZABLE)會對當前讀的行為有不同的影響。
- 常見操作:在MySQL中,使用以下SQL語句會觸發當前讀:
SELECT … FOR UPDATE、SELECT … LOCK IN SHARE MODE,以及UPDATE、INSERT、DELETE等操作。
在SERIALIZABLE隔離級別下,所有讀取操作都會變成當前讀,而不僅僅是那些顯式加上鎖的讀取操作。當前讀是一種帶有鎖機制的讀取操作,旨在確保讀取的數據一致性并防止其他事務對這些數據進行并發修改。
2、快照讀
在MySQL中,特別是在使用InnoDB存儲引擎時,“快照讀”(Snapshot Read)是一種讀取操作,它允許事務讀取到數據的一致性視圖,而不受其他并發事務的影響。這種讀取方式不涉及對數據行加鎖,因此不會阻塞其他事務對數據的修改,提高了數據庫的并發性能。
快照讀的主要特點包括:
- 一致性視圖:快照讀提供了一個數據的一致性快照,即事務在開始時“拍攝”的數據狀態。即使其他事務在該事務執行期間修改了數據,該事務也能讀取到它開始時的數據狀態。
- 非阻塞讀取:由于快照讀不涉及對數據行的加鎖,它不會阻塞其他事務對數據的修改。這減少了鎖爭用,提高了并發性能。
- 隔離級別依賴:快照讀的行為依賴于事務的隔離級別。在
READ COMMITTED隔離級別下,快照讀會讀取到最新提交的數據版本。而在REPEATABLE READ隔離級別下,快照讀會讀取到事務開始時的數據版本,即使其他事務在該事務執行期間提交了更改。 - 版本鏈:InnoDB通過維護數據的版本鏈來實現快照讀。每個數據行都保存了多個版本,事務可以根據自己的隔離級別和開始時間來選擇正確的版本。
- 垃圾回收:InnoDB的MVCC機制會負責清理不再需要的舊數據版本,以避免無限增長。
- 常見操作:在MySQL中,普通的
SELECT查詢默認就是快照讀,除非指定了FOR UPDATE或LOCK IN SHARE MODE。
什么是undolog
在數據庫系統中,undo log(撤銷日志)是一種重要的日志記錄機制,用于處理事務中的回滾操作和保持數據的一致性。它是事務日志(transaction log)的一部分,記錄了事務進行修改之前的數據狀態,以便在事務失敗或需要回滾時能夠恢復到原始狀態。
以下是undo log的一些關鍵特性:
- ?回滾操作?:當一個事務需要被回滾時,
undo log提供了必要的信息來撤銷事務中已經進行的修改,確保數據能夠恢復到事務開始前的狀態。 - ?一致性保證?:在事務執行過程中,如果系統發生故障(如宕機、斷電等),
undo log可以幫助數據庫恢復到一致的狀態,確保數據的完整性。 - ?**多版本并發控制(MVCC)**?:在支持MVCC的數據庫系統中,
undo log也用于維護數據的多個版本,使得不同的事務可以訪問到它們需要的數據版本,而不會相互干擾。 - ?非鎖定讀取?:在某些數據庫系統中,
undo log允許非鎖定讀取,即在不鎖定數據的情況下進行數據讀取,這有助于提高數據庫的并發性能。 - ?節省存儲空間?:
undo log通常只記錄必要的信息來恢復數據,而不是記錄完整的數據副本,這樣可以節省存儲空間。 - ?事務隔離?:在不同的事務隔離級別下,
undo log的使用方式可能不同,以確保事務的隔離性。 - ?垃圾回收?:在事務提交后,
undo log中不再需要的部分可以被垃圾回收機制清除,以釋放存儲空間。
在MySQL的InnoDB存儲引擎中,undo log是實現事務和MVCC的關鍵組件。InnoDB的undo log分為兩種類型:
-
?插入undo log?:記錄了插入操作的逆操作,用于處理插入操作的回滾。
Read View
實現mvcc的關鍵 事務讀取到對應版本的read view
在
REPEATABLE READ隔離級別下,Read View通常在以下幾種情況下被創建:
- ?事務開始時?:當事務開始時,如果沒有其他
Read View存在,InnoDB會創建一個新的Read View。 - ?第一次讀取操作時?:如果事務在執行過程中還沒有創建
Read View,那么在第一次執行讀取操作時會創建一個。 -
Read View的工作原理
Read View包含以下關鍵信息:
- ?事務ID列表?:記錄了在
Read View創建時所有已經啟動的事務的ID。 - ?低水位標記?:表示
Read View創建時的最小事務ID。 - ?高水位標記?:表示
Read View創建時的最大事務ID。
當事務嘗試訪問數據時,Read View會根據以下規則決定事務可以看到哪個版本的數據:
- ?如果數據的事務ID小于低水位標記?:表示該數據版本在
Read View創建之前就已經存在,事務可以看到這個版本。 - ?如果數據的事務ID大于高水位標記?:表示該數據版本是在
Read View創建之后由其他事務創建的,當前事務不可見。 - ?如果數據的事務ID在低水位和高水位之間?:需要檢查該事務是否在
Read View的事務ID列表中。如果在列表中,事務可以看到這個版本;如果不在,事務不可見。