為防止客戶端請求互相干擾、或服務與維護工具 (myisamchk/isamchk) 衝突,MySQL 提供表級鎖定機制。理解內部/外部鎖差異、檢查與修復的標準協議,能安全執行線上維護。
| 維度 | 內部鎖 (Internal Locking) | 外部鎖 (External Locking / File Lock) |
|---|---|---|
| 實現層級 | MySQL 伺服器內部 | 作業系統檔案系統 (fcntl/lockf) |
| 保護對象 | 客戶端請求間隔離、維護工具與伺服器隔離 | 防止其他進程修改檔案 |
| 啟用預設 | 永遠啟用 | 部分系統預設關閉 (如 Linux skip-locking) |
| 適用場景 | 所有存儲引擎 | 僅 MyISAM/ISAM,InnoDB 不支援 |
LOCK TABLES tbl_name {READ | WRITE} [, tbl_name {READ | WRITE}] ...
UNLOCK TABLES
READ:所有線程可讀,不可寫;申請 WRITE 的線程等待。WRITE:僅持鎖線程可讀寫,其他線程完全阻塞;優先級高於 READ。LOCK TABLES 或連線關閉自動 UNLOCK TABLES。mysql -u root -p db_name
LOCK TABLE tbl_name READ;
FLUSH TABLES; -- 關閉表檔案、刷新緩衝區
# 另一終端
myisamchk tbl_name
# 或 isamchk tbl_name
# 檢查完成回 mysql
UNLOCK TABLES;
mysql -u root -p db_name
LOCK TABLE tbl_name WRITE;
FLUSH TABLES;
# 1. 備份資料檔
cp tbl_name.* /backup/dir/
# 2. 執行修復
myisamchk --recover tbl_name
# 或 isamchk --recover tbl_name
# 3. 修復完成必須再次 FLUSH 使伺服器感知新索引
FLUSH TABLES;
UNLOCK TABLES;
關鍵差異: 修復後必須二次 FLUSH TABLES,否則伺服器仍使用舊索引快取,導致數據不一致。
mysqladmin variables | grep skip_locking
# skip_locking = OFF → 外部鎖啟用,可直接跑 myisamchk (需先 flush-tables)
# skip_locking = ON → 外部鎖禁用,必須用內部鎖協議或停庫
#!/bin/bash
DB=$1
TBL=$2
mysql -uroot -p"$3" -e "LOCK TABLE \`$DB\`.\`$TBL\` WRITE; FLUSH TABLES;"
myisamchk --recover /var/lib/mysql/$DB/$TBL
mysql -uroot -p"$3" -e "FLUSH TABLES; UNLOCK TABLES;"
掌握鎖協議,讓 myisamchk/OPTIMIZE TABLE/REPAIR TABLE 在線上安全執行,業務零感知。