MySQL 事務處理是確保資料一致性的核心機制,配合行級鎖(InnoDB)可實現高並發下的資料完整性。本文系統整理事務控制語法、鎖類型特性、隔離等級與實務應用模式。
-- 開啟事務
START TRANSACTION; -- 或 BEGIN [WORK]
-- 提交事務
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE];
-- 回滾事務
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE];
-- 設定自動提交模式(連接層級)
SET AUTOCOMMIT = {0 | 1};
MySQL 預設 AUTOCOMMIT=1,每條更新語句立即持久化。對於事務型引擎(InnoDB、BDB、NDB Cluster),可透過 SET AUTOCOMMIT=0 關閉自動提交,需顯式 COMMIT 或 ROLLBACK。
-- 單一系列語句使用顯式事務(推薦)
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
使用 START TRANSACTION 期間自動提交暫時關閉,直到 COMMIT/ROLLBACK 結束後恢復原狀態。
START TRANSACTION WITH CONSISTENT SNAPSHOT;
僅適用於 InnoDB,效果等同於 START TRANSACTION 後緊接一個 SELECT,獲得事務開始時刻的一致性視圖。
| 鎖層級 | 代表引擎 | 特性 |
|---|---|---|
| 表級鎖 | MyISAM, MEMORY, ISAM | 開銷小、鎖定快、無死鎖、並發度低 |
| 頁級鎖 | BDB | 開銷與並發度介於表級與行級之間、可能死鎖 |
| 行級鎖 | InnoDB | 開銷大、並發度最高、可能死鎖、支援長時間單列鎖定 |
GROUP BY、全表掃描且無寫入操作SELECT ... FOR UPDATE 明確加鎖ER_LOCK_DEADLOCK 錯誤碼並重試// 表鎖(MyISAM 適用)
$sql = "LOCK TABLES stat_num WRITE";
$db->execute($sql);
$sql = "UPDATE stat_num SET correct_num=correct_num+1 WHERE stat_date='{$cur_date}'";
$db->execute($sql);
$sql = "UNLOCK TABLES";
$db->execute($sql);
// 行鎖(InnoDB 適用,配合事務)
$db->query("SET AUTOCOMMIT=0");
$row = $db->fetch_first("SELECT * FROM prizes WHERE id={$id} FOR UPDATE");
$db->query("DELETE FROM prizes WHERE id={$row['id']}");
$db->query("COMMIT");
單一事務中混用多種事務型引擎(如 InnoDB + BDB)且隔離等級非 SERIALIZABLE 時,無法保證原子性;混用非事務型表(MyISAM)時,該表變更即時生效,ROLLBACK 不會回滾,並產生警告 ER_WARNING_NOT_COMPLETE_ROLLBACK。