MySQL 表鎖(LOCK TABLES)是處理高併發場景下數據一致性的重要手段。本文深入解析鎖模式、行為規則,並通過「庫存扣減」經典案例演示如何用表鎖解決併發超賣問題。
LOCK TABLES 創建一個「封閉空間」,鎖定的表進入該空間,直到 UNLOCK TABLES 或會話結束才釋放。空間內僅可訪問已鎖定的表,其他表不可用。
| 模式 | 當前會話 | 其他會話 | 適用場景 |
|---|---|---|---|
| READ | 可讀,不可寫(報錯) | 可讀,寫請求等待 | 只讀報表、備份 |
| WRITE | 可讀可寫 | 讀寫請求均等待 | 數據修改、關鍵業務 |
-- 鎖定多表,指定模式
LOCK TABLES `table1` READ, `table2` WRITE, `table3` READ;
-- 釋放所有鎖
UNLOCK TABLES;
商品庫存 1 件,用戶 A、B 幾乎同時下單。無鎖保護時:
<?php
// 1. 獲取寫鎖(排他鎖)
$db->lock('goods', 2); // 2 = WRITE
// 2. 安全檢查庫存並扣減
$sql = "SELECT number FROM goods WHERE id = 1";
$number = intval($db->result($db->query($sql), 0));
if ($number > 0) {
sleep(2); // 模擬業務處理延遲
$sql = "UPDATE goods SET number = number - 1 WHERE id = 1";
if ($db->query($sql)) {
echo '下單成功';
} else {
echo '系統錯誤,請重試';
}
} else {
echo '庫存不足';
}
// 3. 釋放鎖
$db->unlock();
?>
class MySQL_DB {
// ... 連接屬性 ...
public function lock($table, $type = 1) {
$mode = ($type == 1) ? 'READ' : 'WRITE';
$this->query("LOCK TABLE `$table` $mode");
}
public function unlock() {
$this->query("UNLOCK TABLES");
}
}
使用 JMeter 模擬 2 個併發線程:

LOCK TABLES 均會自動釋放舊鎖START TRANSACTION + 行鎖)是更現代的併發控制方案表鎖是 MyISAM 時代解決併發的利器,但在 InnoDB 為主的現代架構中,行級鎖 + 事務 才是首選。理解表鎖機制有助於維護舊系統、排查鎖衝突,也為學習事務隔離級別打下基礎。