目錄
什么是事務?
事務的四大特性
事務的隔離級別
事務的原理
redo log
undo log
MVCC實現原理
概念
隱藏字段
undo log版本鏈
readview
什么是事務?
? ? 事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要么同時成功,要不同時失敗。
? ??用一個形象的比喻:事務就像銀行轉賬操作,從A賬戶扣款和向B賬戶加款這兩個操作必須作為一個整體執行——要么都成功完成,要么都不執行。如果只執行了其中一個操作,就會導致數據不一致。
事務的四大特性
- 原子性:事務是不可分割的最小操作單元,要么同時成功,要么同時失敗。
- 一致性:事務完成時,必須使所有的數據保持一致狀態。
- 隔離性:數據庫系統提供的隔離機制,保證事務在不受外部并發操作影響的獨立環境下運行。
- 持久性:事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的。
事務的隔離級別
讀未提交(Read Uncommitted):事務可以讀取其他未提交事務的修改。會導致臟讀(Dirty Read)、不可重復讀和幻讀。
讀已提交(Read Committed):事務只能讀取其他已提交事務的修改。解決了臟讀,但仍可能存在不可重復讀(Non-repeatable Read)?和幻讀。這是Oracle等數據庫的默認級別。
可重復讀(Repeatable Read):確保在同一事務中多次讀取同一數據的結果是一致的。解決了臟讀和不可重復讀,但仍可能存在幻讀(Phantom Read)。這是MySQL InnoDB的默認級別。
串行化(Serializable):最高隔離級別,強制事務串行執行,完全避免臟讀、不可重復讀和幻讀,但性能開銷最大。
事務的原理
redo log
? ? 重做日志,記錄的是事務提交時數據頁的物理修改,是用來實現事務的持久性。
? ? 該日志文件由兩部分組成:重做日志緩沖(redo log buffer)以及重做日志文件(redo log file),前者是在內存中,后者在磁盤中,當事務提交之后會把所有的修改信息都存到該日志文件中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復使用。
? ? 當對緩沖區的數據進行增刪改之后,首先會把增刪改的數據記錄在redo log buffer中,redo log buffer就會去記錄數據頁的物理變化。當事務提交的時候就會把redo log buffer中數據頁變化刷新到磁盤中。當進行臟頁刷新時出錯了,就能通過redo log進行恢復。
undo log
? ? 回滾日志,用于記錄數據被修改前的信息,作用包含:提供回滾、MVCC(多版本并發控制)。
? ? redo log是記錄物理日志,而undo log是邏輯日志。當執行delete或update時,它都會記錄一條相反的記錄。當執行rollback時,就可以從undo log中的邏輯記錄讀取到相應的內容
? ? Undo log銷毀:undo log在事務執行時產生,事務提交時,并不會立刻刪除undo log,這些日志還可能用于MVCC。
? ? Undo log存儲:undo log采用段的方式進行管理和記錄,存放在rollback segment回滾段中。
MVCC實現原理
概念
- 當前讀:讀取的是記錄的最新版本,讀取時還要保證其他并發事務不能修改當前記錄,會對讀取的記錄進行加鎖。
- 快照讀:簡單的select(不加鎖)就是快照讀,讀取的是可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。RC:每次select都會生成一個快照讀;RR:開啟事務后的第一個select語句就是快照讀的地方;S:快照讀變成當前讀
- MVCC:Multi-Version Concurrency Control,多版本并發控制。指維護一個數據的多個版本,使得讀寫操作沒有沖突,快照讀為MySQL實現MVCC提供了一個非阻塞讀的功能。具體實現還依賴數據庫中的三個隱藏字段、undo log、readView。
隱藏字段
- DB_TRX_ID:最近修改事務id,記錄插入這條記錄或最后一次修改該記錄的事務id。
- DB_ROLL_PTR:回滾指針,指向這條記錄的上一個版本,用于配合undo log,指向上一個版本。
- DB_ROW_ID:隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏字段
undo log版本鏈
? ? 用 Undo Log 將一條記錄的多個歷史版本串聯起來,形成一個基于
ROLL_PTR
(回滾指針)的鏈表結構。? ? 這個鏈表使得數據庫能夠“回到過去”,找到記錄在某個特定時間點的狀態。
readview
? ? Readview是快照讀SQL執行時MVCC提取數據的依據,記錄并維護系統當前活躍(未提交)事務的id。包含四個核心字段:
- m_ids:當前活躍事務的id集合
- min_trx_id:最小活躍事務id
- max_trx_id:預分配事務id,當前最大事務id+1
- creator_trx_id:Readview創建者的事務id