事務是一組邏輯上不可分割的操作單元:**要麼全成功,要麼全失敗**。滿足 ACID 四大特性:
表必須使用 InnoDB 引擎(MyISAM 不支援事務)。
CREATE TABLE bank (name VARCHAR(20), money DECIMAL(10,2)) ENGINE=InnoDB;
INSERT INTO bank VALUES ('Alice',1000), ('Bob',5000);
-- 1. 開啟事務
START TRANSACTION; -- 或 BEGIN;
-- 2. 執行業務 SQL
UPDATE bank SET money = money + 500 WHERE name = 'Alice';
UPDATE bank SET money = money - 500 WHERE name = 'Bob';
-- 3. 根據結果決定
-- 全成功
COMMIT;
-- 任一失敗
ROLLBACK;
-- 成功案例
START TRANSACTION;
UPDATE bank SET money = money + 500 WHERE name = 'Alice'; -- OK
UPDATE bank SET money = money - 500 WHERE name = 'Bob'; -- OK
COMMIT;
SELECT * FROM bank; -- Alice 1500, Bob 4500
-- 失敗回滾(第二條拼寫錯誤 moey)
START TRANSACTION;
UPDATE bank SET money = money + 500 WHERE name = 'Alice'; -- OK
UPDATE bank SET moey = money - 500 WHERE name = 'Bob'; -- ERROR 1054
ROLLBACK;
SELECT * FROM bank; -- Alice 1000, Bob 5000(回滾生效)
| 隔離級別 | 髒讀 | 不可重複讀 | 幻讀 | MySQL 預設 |
|---|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 | |
| READ COMMITTED | 不可能 | 可能 | 可能 | |
| REPEATABLE READ | 不可能 | 不可能 | 可能(InnoDB 用 Next-Key Lock 解決) | ✓ |
| SERIALIZABLE | 不可能 | 不可能 | 不可能 |
-- 查看/設定隔離級別
SELECT @@transaction_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
以下語句會隱式提交當前事務:
CREATE/ALTER/DROP TABLE、TRUNCATEGRANT/REVOKELOCK TABLESFLUSH TABLES WITH READ LOCK事務中避免混用上述語句。
START TRANSACTION;
UPDATE bank SET money = money - 100 WHERE name = 'Alice';
SAVEPOINT sp1;
UPDATE bank SET money = money - 200 WHERE name = 'Bob';
-- 發現 Bob 餘額不足
ROLLBACK TO SAVEPOINT sp1; -- 僅回滾到 sp1
COMMIT; -- 僅 Alice 扣款生效
ROLLBACK,否則連接池歸還時可能隱式提交。事務是關係型資料庫的核心價值之一,善用它守護資料正確性。