MySQL 支援三種鎖粒度:表級鎖、頁級鎖、行級鎖,分別由不同儲存引擎實作。理解其特性差異、適用場景與死鎖處理,是構建高並發應用的關鍵。本文系統整理鎖機制原理、優缺點對比、實務操作範例與優化建議。
| 鎖層級 | 代表引擎 | 特性摘要 |
|---|---|---|
| 表級鎖 | MyISAM、MEMORY、ISAM | 開銷最小、加鎖最快、無死鎖、並發度最低 |
| 頁級鎖 | BDB | 開銷與並發度居中、可能死鎖 |
| 行級鎖 | InnoDB | 開銷最大、並發度最高、可能死鎖、支援長時間單列鎖定 |
可使用 LOW_PRIORITY(寫/讀)與 HIGH_PRIORITY(讀)調整隊列優先序。
當並行插入不可行時,可採用暫存表緩衝:
LOCK TABLES real_table WRITE, insert_table WRITE;
INSERT INTO real_table SELECT * FROM insert_table;
TRUNCATE TABLE insert_table;
UNLOCK TABLES;
UPDATE tbl SET col=val WHERE unique_key=key_val;DELETE FROM tbl WHERE unique_key=key_val;SELECT、INSERT 並發,極少 UPDATE/DELETEGROUP BY,無寫入操作InnoDB 透過多版本並發控制實現「讀不阻寫、寫不阻讀」,支援基於時間點的一致性視圖,又稱時間旅行、寫時複製或按需複製。
// 表鎖(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");
SELECT ... FOR UPDATE 明確加鎖ER_LOCK_DEADLOCK (1213) 錯誤碼並指數退避重試