MySQL 默認調度策略
- 寫優先於讀:寫請求到達時,阻塞後續讀請求,直到寫完成
- 寫串行:同一表同一時間只能一個寫入,按到達順序
- 讀並行:多個讀請求可同時進行
實現基礎:MyISAM/MEMORY 使用表級鎖;InnoDB 使用行級鎖(必要時)。
鎖類型與相容矩陣
| 鎖類型 | 別名 | 適用操作 | 相容性 |
| 共享鎖 | S 鎖、讀鎖 | SELECT ... LOCK IN SHARE MODE | S✓ S✓ X✗ |
| 排他鎖 | X 鎖、寫鎖 | INSERT/UPDATE/DELETE、SELECT ... FOR UPDATE | S✗ X✗ X✗ |
| 意向共享鎖 | IS 鎖 | 表級,表示意圖加行級 S 鎖 | 與表級 S/X 相容判斷 |
| 意向排他鎖 | IX 鎖 | 表級,表示意圖加行級 X 鎖 | 與表級 S/X 相容判斷 |
調度修飾符
| 修飾符 | 適用語句 | 效果 | 適用引擎 |
LOW_PRIORITY | INSERT/UPDATE/DELETE/REPLACE/LOAD DATA | 寫請求降級,等待所有讀完成才執行,可能餓死 | MyISAM/MEMORY |
HIGH_PRIORITY | SELECT/INSERT | 讀/寫請求插隊到普通寫請求前 | MyISAM/MEMORY |
DELAYED | INSERT/REPLACE | 客戶端立即返回,行入隊列,無讀時批量寫入 | MyISAM/MEMORY |
--low-priority-updates | 服務啟動參數 | 全局將所有寫操作降級 | MyISAM/MEMORY |
並發插入
- MyISAM:表中無「空洞」(無 DELETE/UPDATE 產生碎片)時,允許尾部插入與讀並行
- 條件:
concurrent_insert=1/2(預設 1),LOCK TABLE ... READ LOCAL 保留並發插入權
- InnoDB:行級鎖天然支援高併發插入,無空洞限制
鎖層級對併發的影響
| 引擎 | 鎖層級 | 併發特性 | 適用場景 |
| MyISAM | 表級 | 讀讀並行、讀寫互斥、寫寫串行;長查詢阻塞寫入 | 讀多寫少、全文搜索、只讀報表 |
| BDB | 頁級 | 不同頁可並行寫入,同頁串行 | 已棄用 |
| InnoDB | 行級 | 不同行可並行寫入,極高併發;支援 MVCC 非鎖定讀 | 核心業務、高併發寫入、事務 |
死鎖與預防
- 表級鎖:預先聲明
LOCK TABLES t1 WRITE, t2 READ,**無死鎖**
- 行級鎖:必發生死鎖(循環等待)。InnoDB 自動檢測並回滾代價最小事務
- 預防:固定表訪問順序、拆分大事務、合理索引減少掃描鎖、
innodb_lock_wait_timeout 設合理值(預設 50s)
顯式鎖表最佳實踐
-- 讀鎖(允許並發插入)
LOCK TABLES tbl READ LOCAL;
SELECT ...;
UNLOCK TABLES;
-- 寫鎖
LOCK TABLES tbl WRITE;
INSERT ...;
UNLOCK TABLES;
-- 多表按固定順序加鎖(避免死鎖)
LOCK TABLES t1 WRITE, t2 READ;
-- 業務邏輯
UNLOCK TABLES;
監控指標
SHOW STATUS LIKE 'Table_locks_%';
-- Table_locks_waited / Table_locks_immediate 比例過高 → 鎖爭用嚴重
SHOW ENGINE INNODB STATUS\G
-- TRANSACTIONS 區:LOCK WAIT、死鎖歷史
-- SEMAPHORES 區:信號量等待
總結
鎖是併發控制基石。**表級鎖簡單無死鎖但併發低;行級鎖併發高但需死鎖處理**。InnoDB MVCC 實現「讀不阻寫、寫不阻讀」是高併發核心。調度修飾符僅針對表級鎖引擎,InnoDB 靠隔離級別與鎖演算法控制。核心功課:**理解鎖相容、識別鎖爭用熱點、設計固定訪問順序、善用監控指標**。