LOCK TABLES 時用表鎖,**強烈建議別用**,依賴行鎖/頁鎖保證事務隔離-- 客戶端 A: 長時間報表查詢 (運行 30 分鐘)
SELECT * FROM huge_table WHERE ...;
-- 客戶端 B: 緊急更新 (被阻塞 30 分鐘)
UPDATE huge_table SET status=1 WHERE id=100;
-- 客戶端 C: 普通查詢 (也被阻塞,因 UPDATE 優先級高)
SELECT * FROM huge_table WHERE id=100;
**後果**:單個長讀導致所有寫入排隊,寫入又阻塞後續讀取,連鎖擁堵。
業務實際:讀查詢對用戶體感關鍵 (毫秒級響應),寫入可容忍秒級延遲 (異步隊列)。但表鎖**寫優先於讀**,導致關鍵讀被非關鍵寫阻塞。
表級鎖序列化所有寫操作,單表寫入 QPS 上限極低 (通常 < 100),完全無法滿足現代高並發場景。
EXPLAIN 驗證執行計畫,消除 type=ALL[mysqld]
low-priority-updates=1
# 或運行時
SET GLOBAL low_priority_updates=1;
SET LOW_PRIORITY_UPDATES=1; -- 會話級
效果:UPDATE/INSERT/DELETE 降級,SELECT 可優先執行。
INSERT LOW_PRIORITY INTO log_table ...;
UPDATE LOW_PRIORITY stats SET cnt=cnt+1 WHERE id=1;
DELETE LOW_PRIORITY FROM archive WHERE dt < '2023-01-01';
SELECT HIGH_PRIORITY * FROM users WHERE id=1;
[mysqld]
max_write_lock_count = 100 # 達到 100 個寫鎖後,暫時提升讀優先級
OPTIMIZE TABLE 清理空洞恢復特性INSERT DELAYED INTO stats (page, pv) VALUES ('home', 1);
-- 客戶端立即返回,服務器空閒時批量寫入
-- 適合:日志、統計、監控數據
DELETE FROM huge_table WHERE created < '2023-01-01' LIMIT 1000;
-- 分批刪除,每批持鎖時間短,減少阻塞窗口
-- 配合腳本循環執行至完成
SELECT SQL_BUFFER_RESULT * FROM huge_table WHERE ...;
-- 結果先存入臨時表,釋放表鎖,再傳給客戶端
-- 適合:網絡慢、結果集大、客戶端處理慢
修改 mysys/thr_lock.c 合併讀寫隊列,優先級平權。風險極高,升級維護困難,**生產環境禁用**。
| 場景 | 首選策略 | 備選策略 |
|---|---|---|
| 報表長查詢阻塞業務寫入 | 摘要表/物化視圖 (策略1) | LOW_PRIORITY_UPDATES (策略2) |
| 高頻統計寫入阻塞核心查詢 | INSERT DELAYED (策略6) | 低優先級更新 (策略2/3) |
| 海量歷史數據清理 | DELETE LIMIT 分批 (策略7) | 分區表 + DROP PARTITION |
| 大結果集慢客戶端 | SQL_BUFFER_RESULT (策略8) | 應用端流式處理 |
| 核心業務高並發讀寫 | 遷移 InnoDB (策略10) | — |