Innodb 是如何實現事務的?
InnoDB 是 MySQL 中最常用的存儲引擎之一,它通過一系列複雜的機制和策略來實現事務的 ACID 特性(原子性、一致性、隔離性和持久性)。
以下是 InnoDB 實現事務的詳細過程和關鍵機制:
1. 事務的啓動和結束
-
啓動事務:通過
START TRANSACTION
或BEGIN
語句開始一個新事務。 -
提交事務:通過
COMMIT
語句提交事務,將事務中的所有操作永久保存到數據庫中。 -
回滾事務:通過
ROLLBACK
語句回滾事務,撤銷事務中的所有操作,使數據庫恢復到事務開始之前的狀態。
2. 日誌系統
Redo Log(重做日誌)
-
作用:確保事務的持久性。記錄數據頁的物理變化,以便在系統崩潰後進行數據恢復。
-
工作原理:遵循預寫日誌(Write-Ahead Logging, WAL)原則,即在事務提交之前先將修改操作記錄到日誌中。
-
過程:
-
當事務對數據庫進行修改時,先將修改記錄寫入重做日誌。
-
事務提交時,重做日誌會被持久化到磁盤。
-
如果系統崩潰,可以通過重做日誌恢復數據。
Undo Log(回滾日誌)
-
作用:確保事務的原子性和一致性。記錄數據修改前的舊值,以便在事務回滾時使用。
-
工作原理:在事務執行過程中,記錄每次數據修改前的舊值。如果事務需要回滾,可以使用回滾日誌將數據恢復到修改前的狀態。
3. 併發控制
MVCC(多版本併發控制)
-
基本概念:MVCC 是 InnoDB 中用於實現事務隔離性的機制,它通過爲每個事務創建一個獨立的數據庫視圖來避免讀寫衝突和髒讀等併發問題。
-
實現方式:使用版本號和回滾指針來實現對數據庫視圖的管理。每個事務在讀取數據時,會獲取一個事務開始時間戳(或事務 ID),並且只能讀取在該時間戳之前已提交的數據。而在寫入數據時,InnoDB 會爲每個修改操作創建一個新版本的數據,而原始數據版本會被保留在數據庫中。
####鎖機制
-
行級鎖:InnoDB 支持行級鎖定,這意味着在一個事務中,只有需要鎖定的行會被鎖定,而其他行可以被其他事務修改。這種鎖定方式可以大大提高併發性能。
-
表級鎖:InnoDB 也支持表級鎖,但通常只在特定情況下使用。
-
鎖的類型:包括共享鎖(S Lock)和排他鎖(X Lock)。共享鎖允許事務讀數據,排他鎖允許事務讀寫數據並阻止其他事務讀寫相同數據。
4. 事務的隔離級別
InnoDB 支持四種事務隔離級別,分別是:
-
讀未提交(READ UNCOMMITTED):允許讀取未提交事務的修改,可能導致髒讀和不可重複讀。
-
讀已提交(READ COMMITTED):只能讀取已提交事務的修改,避免了髒讀,但可能出現不可重複讀。
-
可重複讀(REPEATABLE READ)(默認級別):在同一事務中多次讀取同一數據時,結果是相同的。避免了髒讀和不可重複讀,但可能出現幻讀(通過多版本併發控制避免)。
-
串行化(SERIALIZABLE):最高隔離級別,通過鎖機制確保事務可以嚴格按順序執行,避免了髒讀、不可重複讀和幻讀,但可能導致性能下降。
5. 事務的原子性
通過 Redo Log 和 Undo Log 的協同工作,InnoDB 能夠保證事務的原子性。如果事務在執行過程中失敗,所有已經執行的操作都會被撤銷,確保事務中的所有操作要麼全部完成,要麼全部不完成。
6. 事務的持久性
通過 Redo Log 的持久化,即使系統崩潰,InnoDB 也能通過重做日誌恢復數據,保證事務的持久性。
簡單示例講解
舉例一個簡單的銀行轉賬場景。
假設我們有一個名爲accounts
的表,它存儲了客戶的賬戶信息,包括賬戶 ID、客戶姓名和賬戶餘額。
通過這個表來演示如何使用 InnoDB 的事務來保證轉賬操作的原子性和一致性。
accounts
表結構
-
account_id
(INT, 主鍵) -
customer_name
(VARCHAR, 客戶姓名) -
balance
(DECIMAL, 賬戶餘額)
SQL 事務操作
下面是一個簡單的 SQL 事務示例,用於從一個賬戶轉賬到另一個賬戶:
-- 開始事務
START TRANSACTION;
-- 1. 從賬戶1轉出100元
UPDATE accounts
SET balance = balance - 100
WHERE account_id = 1;
-- 2. 向賬戶2轉入100元
UPDATE accounts
SET balance = balance + 100
WHERE account_id = 2;
-- 檢查是否發生錯誤(在實際應用中,通常會有更復雜的錯誤處理邏輯)
-- 如果沒有錯誤,提交事務
COMMIT;
-- 如果發生錯誤,回滾事務
-- ROLLBACK; -- 這行代碼在正常情況下不會被執行,只有在發生錯誤時纔會用到
說明
-
開始事務:
-
START TRANSACTION;
:這條語句開始了一個新的事務。在 InnoDB 中,事務是一組要麼全部成功要麼全部失敗的操作。
-
-
執行操作:
-
第一個
UPDATE
語句從賬戶 1 中轉出 100 元。 -
第二個
UPDATE
語句向賬戶 2 中轉入 100 元。 -
這兩個操作是事務的一部分,它們要麼同時成功,要麼同時失敗。
-
-
提交事務:
-
COMMIT;
:如果所有操作都成功執行,沒有發生任何錯誤,那麼我們就提交事務。提交事務後,InnoDB 會將事務中的所有更改永久保存到數據庫中。
-
-
回滾事務(可選):
- 如果在執行過程中發生任何錯誤(例如,賬戶 1 的餘額不足或賬戶 2 不存在),我們可以使用
ROLLBACK;
語句來回滾事務。回滾事務會撤銷事務中的所有操作,使數據庫恢復到事務開始之前的狀態。
- 如果在執行過程中發生任何錯誤(例如,賬戶 1 的餘額不足或賬戶 2 不存在),我們可以使用
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qwFsNR_oS2TLLMcEoZ2dNw