表鎖定是 MySQL 協調並發存取、配合維護工具(myisamchk/isamchk)的核心機制。本文深入解析內部鎖(LOCK TABLES)與外部鎖(檔案層級鎖)的運作差異、適用場景,並提供檢查表與修復表的標準鎖定協議流程,避免維護操作與線上業務衝突導致資料不一致。
為什麼需要表鎖定?
- 防止用戶查詢(SELECT)被其他用戶更新(UPDATE)干擾
- 防止
myisamchk/isamchk 檢查修復時,Server 同時修改表檔案
- 避免直接關閉資料庫服務(影響所有表可用性)
內部鎖定
語法
LOCK TABLES tbl_name {READ | WRITE} [, tbl_name {READ | WRITE} ...]
UNLOCK TABLES
鎖模式特性
| 鎖類型 | 持鎖線程 | 其他線程 | 優先級 |
| READ | 可讀、不可寫 | 可讀、不可寫 | 低 |
| WRITE | 可讀、可寫 | 阻塞(不可讀寫) | 高 |
關鍵行為
- 同一線程重複
LOCK TABLES 會隱含 UNLOCK TABLES
- 連線斷開自動釋放所有鎖
- WRITE 鎖優先級高於 READ:有 WRITE 等待時,新 READ 請求將排隊等待
- 檢查表只需 READ 鎖;修復表必須 WRITE 鎖
外部鎖定
檔案系統層級鎖(fcntl/lockf),協調 mysqld 與 myisamchk 等外部程式。
--skip-locking(或 --skip-external-locking)啟動參數可停用
- Linux 預設啟用
skip-locking(即外部鎖關閉)
- 驗證:
mysqladmin variables | grep skip_locking
外部鎖啟用時的協作流程
- 執行
mysqladmin flush-tables 刷新快取、關閉檔案
- 運行
myisamchk 檢查/修復
- Server 與工具透過檔案鎖自動協調
外部鎖停用時(預設)必須用內部鎖協議
檢查表鎖定協議(唯讀檢查)
# 1. 取得讀鎖並刷新
mysql -u root -p db_name
mysql> LOCK TABLE tbl_name READ;
mysql> FLUSH TABLES;
# 2. 執行檢查(Server 不持有檔案控制權)
myisamchk tbl_name
# 或
isamchk tbl_name
# 3. 釋放鎖
mysql> UNLOCK TABLES;
修復表鎖定協議(必須獨佔)
# 1. 取得寫鎖並刷新
mysql -u root -p db_name
mysql> LOCK TABLE tbl_name WRITE;
mysql> FLUSH TABLES;
# 2. 備份原始檔案再修復
cp tbl_name.* /backup/dir/
myisamchk --recover tbl_name
isamchk --recover tbl_name
# 3. 再次刷新(讓 Server 重新讀取新索引檔)並釋放
mysql> FLUSH TABLES;
mysql> UNLOCK TABLES;
關鍵差異:修復後必須二次 FLUSH TABLES,否則 Server 仍使用舊快取的索引資訊。
優化表同樣適用修復協議
OPTIMIZE TABLE 內部等同 myisamchk --recover + 索引重建,同樣需 WRITE 鎖與二次 FLUSH。
實戰建議
- 維護窗口操作:低峰期執行,減少業務影響
- 大表分區/分表:縮小鎖定範圍與修復時間
- InnoDB 表:不適用
myisamchk,使用 CHECK TABLE/REPAIR TABLE SQL 指令,行鎖機制無需手動 LOCK TABLES
- 監控鎖等待:
SHOW STATUS LIKE 'Table_locks_waited' 持續增長表示鎖爭用嚴重
掌握鎖定協議,能在不停機的前提下安全執行表檢查與修復,是 MyISAM 時代 DBA 的必備技能。雖然 InnoDB 已成主流,但理解表鎖原理對排查「Metadata Lock」阻塞、設計線上 Schema 變更策略仍具參考價值。
copyright ©
萬盛學電腦網 all rights reserved