在 MySQL 備份、主從搭建、DDL 變更等場景中,正確使用全局鎖與表鎖是保證數據一致性的關鍵。本文深度解析 FLUSH TABLES WITH READ LOCK(FTWRL)與 LOCK TABLES 的工作原理、阻塞行為、隱式提交陷阱及生產級最佳實踐。
FLUSH TABLES WITH READ LOCK; -- 獲取全局讀鎖 UNLOCK TABLES; -- 釋放所有鎖
許多 DBA 困惑:SELECT 是讀操作,為什麼 FTWRL 要等它結束?
-- 會話 A:長時間掃描大表 SELECT COUNT(*) FROM huge_table; -- 耗時 30 分鐘 -- 會話 B:執行 FTWRL FLUSH TABLES WITH READ LOCK; -- 狀態顯示 "Waiting for table flush"
根因:
對策:備份窗口選在業務低峰;使用 pt-online-schema-change 類工具避免長鎖;或改用 Percona XtraBackup 物理熱備(無需 FTWRL)。
-- 會話 A FLUSH TABLES WITH READ LOCK; -- 此時保持會話開啟(建議 screen/tmux/nohup) -- 若 Ctrl+C 斷開、網絡中斷、kill 會話 -- MySQL 會隱式執行 UNLOCK TABLES,鎖瞬間失效!
鐵律:執行 FTWRL 的會話必須全程保持存活,直到備份/快照完成並手動 UNLOCK TABLES。
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE};
UNLOCK TABLES;
READ [LOCAL]:允許並發讀,LOCAL 允許非衝突 INSERT(MyISAM 尾部插入)[LOW_PRIORITY] WRITE:獨佔寫鎖,阻塞所有其他讀寫LOCK TABLES t READ; mysqldump ...; UNLOCK TABLES; 邏輯備份ANALYZE TABLE / OPTIMIZE TABLE 前鎖定防寫入會話斷開、執行 START TRANSACTION、執行 DDL 等均會隱式 UNLOCK TABLES。
| 場景 | 推薦方案 | 避坑提示 |
|---|---|---|
| 全庫邏輯備份 | mysqldump --single-transaction (InnoDB) / --lock-all-tables (MyISAM) | 避免手動 FTWRL,工具內部自動處理一致性與鎖釋放 |
| 物理熱備/快照 | Percona XtraBackup / 文件系統快照 + FTWRL(極短時間) | FTWRL 持有時間 < 1 秒,配合 FLUSH TABLES WITH READ LOCK 瞬間完成 |
| 搭建從庫 | XtraBackup + 記錄 binlog position / GTID | 不再建議 FTWRL + mysqldump,耗時長、影響業務 |
| 跨表一致性讀 | InnoDB REPEATABLE READ + 一致性非鎖定讀 / READ ONLY 事務 | 優先用事務隔離級別解決,避免 LOCK TABLES 串行化 |
| DDL 變更前鎖定 | pt-online-schema-change / gh-ost(無鎖變更) | 絕不在高峰期手動 LOCK TABLES WRITE 做 DDL |
FLUSH TABLES WITH READ LOCK = 全局 Flush 髒頁 + 全局讀鎖,阻塞寫、等待長查詢、會話斷開即失效。LOCK TABLES = 顯式表級鎖,粒度細、不影響無關表、同樣怕隱式提交。