事務四大特性(ACID)
| 特性 | 英文 | 銀行轉帳例子 |
| 原子性 | Atomicity | 扣款+入帳要麼全成功,要麼全失敗,不可只做一半 |
| 一致性 | Consistency | 轉帳前後總金額不變,無憑空增減 |
| 隔離性 | Isolation | 同時多筆轉帳互不干擾,看不到中間狀態 |
| 持久性 | Durability | 提交後掉電也能恢復,Redo Log 保證 |
引擎支援
- InnoDB:完整支援 ACID、行鎖、MVCC、外鍵
- MyISAM:不支援事務,表鎖、無崩潰恢復
- 建表指定:
CREATE TABLE t (...) ENGINE=InnoDB;
事務控制語句
import pymysql
conn = pymysql.connect(host='localhost', user='root', password='pwd', db='mydb', autocommit=False)
try:
with conn.cursor() as cur:
# 可選:顯式關閉自動提交(連線參數已設)
# cur.execute('SET autocommit=0')
cur.execute('UPDATE account SET balance = balance - 100 WHERE id = 1')
cur.execute('UPDATE account SET balance = balance + 100 WHERE id = 2')
conn.commit()
except pymysql.Error as e:
conn.rollback()
print(f'MySQL Error {e.args[0]}: {e.args[1]}')
finally:
conn.close()
並發與鎖機制
| 引擎 | 鎖粒度 | 並發特性 |
| MyISAM | 表鎖 | 同一時間只能一寫或多讀,寫阻塞所有 |
| InnoDB | 行鎖(索引上) | 不同行可並發寫,同一行隊列;MVCC 讀不阻寫 |
InnoDB 隔離級別與現象
| 級別 | 髒讀 | 不可重複讀 | 幻讀 | 預設 |
| READ UNCOMMITTED | ✅ | ✅ | ✅ | |
| READ COMMITTED | ❌ | ✅ | ✅ | |
| REPEATABLE READ | ❌ | ❌ | ✅ (Gap Lock 防幻) | ✅ MySQL 預設 |
| SERIALIZABLE | ❌ | ❌ | ❌ | |
-- 錯誤:先 SELECT 再 UPDATE(中間可能被改)
-- 正確:單條 SQL 相對更新
UPDATE account SET balance = balance - 100 WHERE id = 1;
方案 2:顯式鎖表(MyISAM/特殊場景)
START TRANSACTION;
SELECT balance FROM account WHERE id = 1 FOR UPDATE; -- 加排他鎖
UPDATE account SET balance = balance - 100 WHERE id = 1;
COMMIT;
小結
MySQL 事務核心:InnoDB + autocommit=0 + START TRANSACTION + 業務 SQL + COMMIT/ROLLBACK。隔離級別預設 RR(防幻讀),高並發可降 RC。Python 用 autocommit=False + try/except/commit/rollback 範本。記住:DDL 隱式提交、相對更新優於鎖、FOR UPDATE 解決讀寫競態。