MySQL 表級鎖實戰:使用 LOCK TABLES 實現唯讀保護
在維護窗口、資料遷移、報表匯出等場景中,常需要暫時禁止表的寫入操作。MySQL 提供 `LOCK TABLES` 機制實現表級別的手動鎖控制。
基本語法
-- 加讀鎖(共享鎖):允許並發讀取,阻塞寫入
LOCK TABLES table_name READ [LOCAL];
-- 加寫鎖(排他鎖):阻塞所有其他讀寫
LOCK TABLES table_name WRITE;
-- 批次鎖定多張表
LOCK TABLES t1 READ, t2 WRITE, t3 READ;
-- 解鎖所有表
UNLOCK TABLES;
實戰範例:設定表為唯讀
mysql> USE test;
Database changed
mysql> LOCK TABLE t_depart_info READ;
Query OK, 0 rows affected (0.00 sec)
-- 嘗試插入資料(會被阻塞/報錯)
mysql> INSERT INTO t_depart_info VALUES (1, 'IT');
ERROR 1099 (HY000): Table 't_depart_info' was locked with a READ lock and can't be updated
-- 其他 Session 查詢正常
mysql> SELECT * FROM t_depart_info;
+----+----------+
| id | name |
+----+----------+
| 1 | HR |
+----+----------+
-- 解鎖恢復正常
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
關鍵特性與限制
| 特性 | READ 鎖 | WRITE 鎖 |
| 當前 Session 讀取 | ✅ 允許 | ✅ 允許 |
| 當前 Session 寫入 | ❌ 禁止 | ✅ 允許 |
| 其他 Session 讀取 | ✅ 允許 | ❌ 阻塞 |
| 其他 Session 寫入 | ❌ 阻塞 | ❌ 阻塞 |
| 支援 LOCAL 選項 | ✅ (允許並發插入) | ❌ |
重要注意事項
- 必須一次鎖定所有涉及表:`LOCK TABLES` 是原子操作,無法分步驟加鎖
- 不支援鎖升級:持有 READ 鎖無法執行 UPDATE/INSERT/DELETE
- 別名也需鎖定:`SELECT a.id FROM emp a` 需 `LOCK TABLES emp AS a READ`
- 事務會隱含提交:執行 `LOCK TABLES` 會隱含 `COMMIT` 當前事務
- 連線斷開自動釋放:Session 結束自動 `UNLOCK TABLES`
適用場景與替代方案
| 場景 | 建議方案 |
| 短時間維護/備份 | LOCK TABLES READ + mysqldump --single-transaction |
| 長時間唯讀(小時級) | REVOKE INSERT/UPDATE/DELETE ON table FROM user |
| 資料遷移同步 | 主庫 READ LOCK → 同步 → 從庫啟動 → UNLOCK |
| 應用層邏輯控制 | 軟刪除/狀態欄位 + 應用攔截器 |
監控鎖爭用
SHOW GLOBAL STATUS LIKE 'Table_locks%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Table_locks_immediate | 1258 | -- 立即獲取
| Table_locks_waited | 0 | -- 等待次數(>0 表示有爭用)
+-----------------------+-------+
Table_locks_waited 持續增長說明存在嚴重鎖爭用,需檢查長時間持鎖查詢或調整應用邏輯。
- 上一篇文章: MySQL 核心配置參數詳解:my.cnf 完整調優指南
- 下一篇文章: Ubuntu 14.04 安裝 MySQL 5.5 完整教學:從安裝到驗證與常用管理
Copyright ©
程式碼之家 All Rights Reserved