MySQL 事務詳解
- 一、事務是什么?
- 為什么需要事務?
- 二、事務的四大特性(ACID)
- 舉例說明:轉賬操作
- 三、MySQL 中事務的支持
- 四、事務分類:隱式 vs 顯式
- 1. 隱式事務(自動提交)
- 2. 顯式事務(手動控制)
- 五、事務的操作語句
- 使用保存點(SAVEPOINT)
- 六、并發事務帶來的問題
- 七、事務隔離級別
- 八、InnoDB 如何實現事務
- 1. 重做日志(Redo Log)
- 2. 撤銷日志(Undo Log)
- 3. MVCC(多版本并發控制)
- 九、最佳實踐與注意事項
- 十、總結
一、事務是什么?
在數據庫系統中,事務(Transaction)
是指一組操作序列,這些操作要么全部執行成功,要么全部不執行,是數據庫操作的基本單位,主要用于保證數據的一致性和完整性。
為什么需要事務?
在多個 SQL 操作依賴于彼此時,若某條操作失敗,必須撤銷之前的操作以防止數據不一致。例如:
UPDATE account SET balance = balance - 100 WHERE user = 'A';
UPDATE account SET balance = balance + 100 WHERE user = 'B';
如果第二條語句失敗,而第一條已經生效,就會導致數據不一致。事務機制可以確保這種情況不會發生。
二、事務的四大特性(ACID)
特性 | 含義 |
---|---|
原子性(Atomicity) | 事務中的所有操作要么全部成功,要么全部失敗,不會停留在中間狀態。 |
一致性(Consistency) | 事務前后數據庫保持一致狀態,不會因事務失敗造成數據損壞。 |
隔離性(Isolation) | 并發事務之間互不干擾,每個事務的執行不會被其他事務看到。 |
持久性(Durability) | 一旦事務提交成功,結果將永久保存到數據庫,即使系統崩潰也不丟失。 |
舉例說明:轉賬操作
步驟 | 操作 | 說明 |
---|---|---|
1 | A賬戶減100元 | 原子性的一部分 |
2 | B賬戶加100元 | 必須與上一步一同成功 |
3 | 事務提交 | 所有變更永久保存 |
? | 若第2步失敗,事務回滾 | 保證一致性、原子性 |
三、MySQL 中事務的支持
不是所有存儲引擎都支持事務,常見如下:
存儲引擎 | 是否支持事務 | 是否支持外鍵 |
---|---|---|
InnoDB | ? | ? |
MyISAM | ? | ? |
MEMORY | ? | ? |
TokuDB | ? | ? |
查看支持情況:
SHOW ENGINES;
四、事務分類:隱式 vs 顯式
1. 隱式事務(自動提交)
MySQL 默認自動提交每一條 DML 語句:
UPDATE users SET age = 30 WHERE id = 1; -- 自動提交
2. 顯式事務(手動控制)
當需要將多條語句當作一個整體執行時,使用顯式事務:
SET autocommit = 0; -- 禁用自動提交
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE name = 'A';
UPDATE users SET balance = balance + 100 WHERE name = 'B';
COMMIT; -- 提交事務
-- ROLLBACK; -- 取消事務
推薦使用
BEGIN
作為START TRANSACTION
的簡潔寫法。
五、事務的操作語句
語句 | 含義 |
---|---|
START TRANSACTION / BEGIN | 顯式開啟事務 |
COMMIT | 提交事務,持久保存變更 |
ROLLBACK | 回滾事務,撤銷變更 |
SAVEPOINT | 設置事務保存點(用于局部回滾) |
ROLLBACK TO SAVEPOINT | 回滾到某個保存點 |
使用保存點(SAVEPOINT)
START TRANSACTION;
UPDATE t SET score = 90 WHERE id = 1;
SAVEPOINT sp1;
UPDATE t SET score = 100 WHERE id = 1;
ROLLBACK TO sp1; -- 回滾到sp1,score回到90
COMMIT;
六、并發事務帶來的問題
在并發執行多個事務時,若沒有合理控制,會產生以下問題:
并發問題 | 描述 |
---|---|
臟讀 | 讀到未提交事務修改的數據 |
不可重復讀 | 同一事務兩次讀到不同數據 |
幻讀 | 同一查詢兩次返回行數不同(新增/刪除行) |
七、事務隔離級別
事務的隔離級別定義了事務間可見的數據范圍,MySQL 支持如下四種:
隔離級別 | 描述 | 能否避免并發問題 |
---|---|---|
READ UNCOMMITTED | 允許讀未提交的數據(最低) | ?臟讀、不可重復讀、幻讀 |
READ COMMITTED | 只能讀已提交的數據 | ?臟讀 ?不可重復讀、幻讀 |
REPEATABLE READ | 可重復讀(MySQL 默認) | ?臟讀 ?不可重復讀 ?幻讀 |
SERIALIZABLE | 串行執行(最高隔離) | ?全部避免,但性能最低 |
設置隔離級別:
-- 查詢當前隔離級別
SELECT @@transaction_isolation;-- 修改隔離級別(會話級)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
八、InnoDB 如何實現事務
InnoDB 使用以下機制來支持事務:
1. 重做日志(Redo Log)
用于保證持久性,即使崩潰后也能恢復事務提交的結果。
2. 撤銷日志(Undo Log)
用于支持原子性和一致性。當事務回滾時,Undo Log 可以撤銷操作。
3. MVCC(多版本并發控制)
實現事務的隔離性(特別是可重復讀),通過版本控制每一行數據,允許事務讀到歷史版本數據。
九、最佳實踐與注意事項
- 顯式開啟事務時,要顯式
COMMIT
或ROLLBACK
,否則鎖會長期占用。 - 控制事務作用域,不要將事務保持過長時間。
- 多個事務同時操作數據時要注意鎖競爭與死鎖問題。
- 盡量使用合適的隔離級別以提升性能。
- 結合業務需求設置合適的回滾點
SAVEPOINT
。
十、總結
MySQL 事務機制是保證數據一致性、完整性的重要基礎。掌握事務的使用方法、隔離級別、InnoDB 實現原理,以及并發控制策略,是每位開發者和 DBA 的必備技能。