事務是數據庫區別於文件系統的核心特性,本文系統講解 MySQL 事務的原理、特性、隔離級別、程序化控制與生產環境注意事項。
事務:邏輯上的一組操作,組成單元要麼全成功,要麼全失敗。
autocommit=ON,每條語句隱式事務BEGIN / START TRANSACTION 開啟,COMMIT 提交,ROLLBACK 回滾| 特性 | 英文 | 核心含義 | MySQL 實現機制 |
|---|---|---|---|
| 原子性 | Atomicity | 事務為不可分割單元,全做或全不做 | Undo Log 記錄舊值,回滾時反向操作 |
| 一致性 | Consistency | 事務前後數據庫從一個一致性狀態變換到另一個 | 約束(PK/FK/UK/CHECK)+ 原子性/隔離性/持久性共同保證 |
| 隔離性 | Isolation | 並發事務互不干擾,多種隔離級別權衡性能與一致性 | MVCC(多版本並發控制)+ 鎖機制 |
| 持久性 | Durability | 提交後改變永久生效,故障也不丟失 | Redo Log(WAL機制)+ sync_binlog=1 + innodb_flush_log_at_trx_commit=1 |
| 隔離級別 | 髒讀 | 不可重複讀 | 幻讀 | 性能 | MySQL 默認 |
|---|---|---|---|---|---|
| READ UNCOMMITTED | ✅ 可能 | ✅ 可能 | ✅ 可能 | 最高 | 否 |
| READ COMMITTED | ❌ 避免 | ✅ 可能 | ✅ 可能 | 高 | Oracle 默認 |
| REPEATABLE READ | ❌ 避免 | ❌ 避免 | ⚠️ 可能(間隙鎖緩解) | 中 | 是 |
| SERIALIZABLE | ❌ 避免 | ❌ 避免 | ❌ 避免 | 最低 | 否 |
異常定義:
-- 查看當前會話隔離級別
SELECT @@TX_ISOLATION;
-- 或
SELECT @@TRANSACTION_ISOLATION;
-- 設置當前會話隔離級別(需在事務開啟前)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 設置全局默認(需重啟或新連接生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Connection conn = null;
PreparedStatement ps = null;
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false); // 關鍵:關閉自動提交,等同於 BEGIN
// 業務邏輯 1
ps = conn.prepareStatement("UPDATE account SET money = money - 100 WHERE id = 1");
ps.executeUpdate();
// 模擬業務異常
// int i = 1 / 0; // 取消註釋測試回滾
// 業務邏輯 2
ps = conn.prepareStatement("UPDATE account SET money = money + 100 WHERE id = 2");
ps.executeUpdate();
conn.commit(); // 顯式提交
} catch (Exception e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException ex) { log.error("Rollback failed", ex); }
}
throw new RuntimeException("Transaction failed", e);
} finally {
// 資源關閉建議使用 try-with-resources (JDK 7+)
if (ps != null) try { ps.close(); } catch (SQLException e) { /* ignore */ }
if (conn != null) try { conn.close(); } catch (SQLException e) { /* ignore */ }
}
| 屬性 | 說明 | 建議值 |
|---|---|---|
| propagation | 傳播行為 | REQUIRED(默認) |
| isolation | 隔離級別 | READ_COMMITTED(高併發) / REPEATABLE READ(默認) |
| timeout | 超時時間(秒) | 30-60,防止長事務阻塞 |
| readOnly | 只讀優化 | 查詢方法設 true |
| rollbackFor | 回滾異常類 | Exception.class(默認僅 RuntimeException) |
Lock wait timeout exceeded / Deadlock found,指數退避重試Innodb_row_lock_waits、Innodb_row_lock_time_avg、Trx_rseg_history_len(Undo 積壓)SELECT 不加鎖:RR 級別下普通 SELECT 是快照讀,但 SELECT ... LOCK IN SHARE MODE / FOR UPDATE 會加鎖autocommit 連接池默認值:Druid/HikariCP 默認 autoCommit=true,框架層接管深入理解事務機制,是編寫高可靠、高併發數據訪問層代碼的基石。