面试官:请说一下Mysql事务实现原理
在日常工作中,數據庫是我們必須使用的,其中使用最多的也是大部分中小公司的選擇是Mysql,跳槽面試中也是必問的,今天我們就說一下Mysql事務
MySQL中的事務實現原理主要涉及以下幾個方面:
- ACID特性:MySQL支持事務的原因之一是它遵循ACID(原子性、一致性、隔離性和持久性)特性。這意味著在一個事務中的所有操作要么全部成功地提交,要么全部失敗回滾。這確保了數據的一致性和可靠性。
- 日志:MySQL使用日志來記錄事務的操作和變化。MySQL有兩種主要的日志類型:重做日志(Redo Log)和回滾日志(Undo Log)。
- 鎖機制:MySQL使用鎖機制來實現事務的隔離性,保證并發事務的正確執行。MySQL支持多種類型的鎖,如共享鎖(Shared Lock)和排他鎖(Exclusive Lock),以及行級鎖和表級鎖等。鎖機制可以防止多個事務同時修改同一個數據,保證數據的一致性。
- MVCC(多版本并發控制):MVCC是MySQL中的一種并發控制機制,用于在并發事務執行時保證數據的隔離性。MVCC通過在每個數據行上維護多個版本來實現。每個事務在讀取數據時,會根據自己的事務ID和數據行的版本信息來確定可見的數據版本,從而實現不同事務之間的隔離性。
- 事務管理器:MySQL有一個事務管理器來協調和管理事務的執行。事務管理器負責事務的開始、提交、回滾和并發控制等。它還負責處理并發事務之間的沖突和死鎖等問題。
綜上所述,MySQL通過使用日志、鎖機制、MVCC和事務管理器等技術來實現事務的原子性、一致性、隔離性和持久性。這些機制保證了數據的完整性和一致性,并提供了高并發的支持。
其中ACID四大特性,實際上分為兩個部分,其中的原子性、一致性、持久性,實際上是由InnoDB中的兩份日志來保證的,一份是redo log日志,一份是undo log日志。而隔離性是通過數據庫的鎖,加上MVCC來保證的。
我們在講解事務原理的時候,主要就是來研究一下redolog,undolog以及MVCC
事務基礎ACID
事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要么同時成功,要么同時失敗。
特性
? 原子性(Atomicity):事務是不可分割的最小操作單元,要么全部成功,要么全部失敗。
? 一致性(Consistency):事務完成時,必須使所有的數據都保持一致狀態。
? 隔離性(Isolation):數據庫系統提供的隔離機制,保證事務在不受外部并發操作影響的獨立環境下運行。
? 持久性(Durability):事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的。
那實際上,我們研究事務的原理,就是研究MySQL的InnoDB引擎是如何保證事務的這四大特性的。
redo log重做日志
記錄的是事務提交時數據頁的物理修改,是用來實現事務的持久性。
該日志文件由兩部分組成:重做日志緩沖(redo log buffer)以及重做日志文件(redo log file),前者是在內存中,后者在磁盤中。當事務提交之后會把所有修改信息都存到該日志文件中, 用于在刷新臟頁到磁盤,發生錯誤時, 進行數據恢復使用。
如果沒有redolog,可能會存在什么問題的?我們一起來分析一下。我們知道,在InnoDB引擎中的內存結構中,主要的內存區域就是緩沖池,在緩沖池中緩存了很多的數據頁。當我們在一個事務中,執行多個增刪改的操作時,InnoDB引擎會先操作緩沖池中的數據,如果緩沖區沒有對應的數據,會通過后臺線程將磁盤中的數據加載出來,存放在緩沖區中,然后將緩沖池中的數據修改,修改后的數據頁我們稱為臟頁。而臟頁則會在一定的時機,通過后臺線程刷新到磁盤中,從而保證緩沖區與磁盤的數據一致。而緩沖區的臟頁數據并不是實時刷新的,而是一段時間之后將緩沖區的數據刷新到磁盤中,假如刷新到磁盤的過程出錯了,而提示給用戶事務提交成功,而數據卻沒有持久化下來,這就出現問題了,沒有保證事務的持久性。
那么,如何解決上述的問題呢?在InnoDB中提供了一份日志 redo log,接下來我們再來分析一下,通過redolog如何解決這個問題。
有了redolog之后,當對緩沖區的數據進行增刪改之后,會首先將操作的數據頁的變化,記錄在redo log buffer中。在事務提交時,會將redo log buffer中的數據刷新到redo log磁盤文件中。過一段時間之后,如果刷新緩沖區的臟頁到磁盤時,發生錯誤,此時就可以借助于redo log進行數據恢復,這樣就保證了事務的持久性。而如果臟頁成功刷新到磁盤或或者涉及到的數據已經落盤,此時redolog就沒有作用了,就可以刪除了,所以存在的兩個redolog文件是循環寫的。那為什么每一次提交事務,要刷新redo log 到磁盤中呢,而不是直接將buffer pool中的臟頁刷新到磁盤呢 ?
因為在業務操作中,我們操作數據一般都是隨機讀寫磁盤的,而不是順序讀寫磁盤。而redo log在往磁盤文件中寫入數據,由于是日志文件,所以都是順序寫的。順序寫的效率,要遠大于隨機寫。這種先寫日志的方式,稱之為 WAL(Write-Ahead Logging 預寫日志)。
undo log回滾日志
用于記錄數據被修改前的信息 , 作用包含兩個 : 提供回滾(保證事務的原子性) 和MVCC(多版本并發控制
undo log和redo log記錄物理日志不一樣,它是邏輯日志。可以認為當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。當執行rollback時,就可以從undo log中的邏輯記錄讀取到相應的內容并進行回滾。
Undo log銷毀:undo log在事務執行時產生,事務提交時,并不會立即刪除undo log,因為這些日志可能還用于MVCC。
Undo log存儲:undo log采用段的方式進行管理和記錄,存放在前面介紹的 rollback segment 回滾段中,內部包含1024個undo log segment。
MVCC
全稱 Multi-Version Concurrency Control,多版本并發控制。指維護一個數據的多個版本,使得讀寫操作沒有沖突,快照讀為MySQL實現MVCC提供了一個非阻塞讀功能。MVCC的具體實現,還需要依賴于數據庫記錄中的三個隱式字段、undo log日志、readView。
接下來介紹一下InnoDB引擎的表中涉及到的隱藏字段、undolog 以及 readview。
隱藏字段
當我們創建了上面的這張表,我們在查看表結構的時候,就可以顯式的看到這三個字段。實際上除了這三個字段以外,InnoDB還會自動的給我們添加三個隱藏字段及其含義分別是:
| 隱藏字段 | 含義 |
|---|---|
| DB_TRX_ID | 最近修改事務ID,記錄插入這條記錄或最后一次修改該記錄的事務ID。 |
| DB_ROLL_PTR | 回滾指針,指向這條記錄的上一個版本,用于配合undo log,指向上一個版本。 |
| DB_ROW_ID | 隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏字段。 |
而上述的前兩個字段是肯定會添加的,是否添加最后一個字段DB_ROW_ID,得看當前表有沒有主鍵,如果有主鍵,則不會添加該隱藏字段。
undolog
介紹
回滾日志,在insert、update、delete的時候產生的便于數據回滾的日志。
當insert的時候,產生的undo log日志只在回滾時需要,在事務提交后,可被立即刪除。
而update、delete的時候,產生的undo log日志不僅在回滾時需要,在快照讀時也需要,不會立即被刪除。
版本鏈
有一張表原始數據為:
DB_TRX_ID : 代表最近修改事務ID,記錄插入這條記錄或最后一次修改該記錄的事務ID,是自增的。
DB_ROLL_PTR :由于這條數據是才插入的,沒有被更新過,所以該字段值為null。然后,有四個并發事務同時在訪問這張表。
最終生成記錄數據:
最終我們發現,不同事務或相同事務對同一條記錄進行修改,會導致該記錄的undolog生成一條記錄版本鏈表,鏈表的頭部是最新的舊記錄,鏈表尾部是最早的舊記錄。
readview
ReadView(讀視圖)是快照讀 SQL執行時MVCC提取數據的依據,記錄并維護系統當前活躍的事務(未提交的)id。
ReadView中包含了四個核心字段:
| 字段 | 含義 |
|---|---|
| m_ids | 當前活躍的事務ID集合 |
| min_trx_id | 最小活躍事務ID |
| max_trx_id | 預分配事務ID,當前最大事務ID+1(因為事務ID是自增的) |
| creator_trx_id | ReadView創建者的事務ID |
而在readview中就規定了版本鏈數據的訪問規則:trx_id 代表當前undolog版本鏈對應事務ID。
| 條件 | 是否可以訪問 | 說明 |
|---|---|---|
| trx_id == creator_trx_id | 可以訪問該版本 | 成立,說明數據是當前這個事務更改的。 |
| trx_id < min_trx_id | 可以訪問該版本 | 成立,說明數據已經提交了。 |
| trx_id > max_trx_id | 不可以訪問該版本 | 成立,說明該事務是在 |
ReadView生成后才開啟。 |
| min_trx_id <= trx_id <= max_trx_id | 如果trx_id不在m_ids中,是可以訪問該版本的 | 成立,說明數據已經提交。 |
不同的隔離級別,生成ReadView的時機不同:
- READ COMMITTED :在事務中每一次執行快照讀時生成ReadView。
- REPEATABLE READ:僅在事務中第一次執行快照讀時生成ReadView,后續復用該ReadView。
MVCC的實現原理就是通過 InnoDB表的隱藏字段、UndoLog 版本鏈、ReadView來實現的。而MVCC + 鎖,則實現了事務的隔離性。而一致性則是由redolog 與 undolog保證。
總結
以上是生活随笔為你收集整理的面试官:请说一下Mysql事务实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过腾讯网页快捷登录协议截取 QQ邮箱
- 下一篇: java信息管理系统总结_java实现科