萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 表鎖定機制詳解:內部鎖 vs 外部鎖、檢查與修復協議實戰

表鎖定是 MySQL 協調並發存取、配合維護工具(myisamchk/isamchk)的核心機制。本文深入解析內部鎖(LOCK TABLES)與外部鎖(檔案層級鎖)的運作差異、適用場景,並提供檢查表與修復表的標準鎖定協議流程,避免維護操作與線上業務衝突導致資料不一致。

為什麼需要表鎖定?

  • 防止用戶查詢(SELECT)被其他用戶更新(UPDATE)干擾
  • 防止 myisamchk/isamchk 檢查修復時,Server 同時修改表檔案
  • 避免直接關閉資料庫服務(影響所有表可用性)

內部鎖定

語法

LOCK TABLES tbl_name {READ | WRITE} [, tbl_name {READ | WRITE} ...]
UNLOCK TABLES

鎖模式特性

關鍵行為

  • 同一線程重複 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

外部鎖啟用時的協作流程

  1. 執行 mysqladmin flush-tables 刷新快取、關閉檔案
  2. 運行 myisamchk 檢查/修復
  3. 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。

實戰建議

  1. 維護窗口操作:低峰期執行,減少業務影響
  2. 大表分區/分表:縮小鎖定範圍與修復時間
  3. InnoDB 表:不適用 myisamchk,使用 CHECK TABLE/REPAIR TABLE SQL 指令,行鎖機制無需手動 LOCK TABLES
  4. 監控鎖等待:SHOW STATUS LIKE 'Table_locks_waited' 持續增長表示鎖爭用嚴重

掌握鎖定協議,能在不停機的前提下安全執行表檢查與修復,是 MyISAM 時代 DBA 的必備技能。雖然 InnoDB 已成主流,但理解表鎖原理對排查「Metadata Lock」阻塞、設計線上 Schema 變更策略仍具參考價值。

copyright © 萬盛學電腦網 all rights reserved
鎖類型持鎖線程其他線程優先級
READ可讀、不可寫可讀、不可寫低
WRITE可讀、可寫阻塞(不可讀寫)高