接續上篇,本文探討利用臨時表隔離讀寫衝突、MyISAM 延遲鍵寫入特性、服務器級延遲索引刷新配置等進階優化手段,解決高併發寫入與大量數據導入的實戰難題。
場景: 頻繁 UPDATE/INSERT 的主表上運行長時間 SELECT,產生嚴重鎖爭用,寫入性能急劇下降。
方案: 寫入操作改為寫入臨時表,定期批量合併到主表。
-- 應用層邏輯
INSERT INTO temp_table ...; -- 極快,無鎖衝突
-- 定時任務
INSERT INTO main_table SELECT * FROM temp_table;
TRUNCATE temp_table;
優勢:
適用性: 允許數據「最終一致性」的場景(如 Web 訪問日誌、非實時統計)。需立即可見的數據不適用。
原理: 創建表時指定 DELAY_KEY_WRITE=1,索引塊不在每次插入後立即刷盤,而是:
FLUSH TABLES 時大幅減少隨機 I/O,適合大量插入、少量讀取、可容忍崩潰後需修復索引的場景(如數據錄入系統)。
CREATE TABLE log_table (...) ENGINE=MYISAM DELAY_KEY_WRITE=1;
啟動 mysqld 時添加 --delayed-key-write,使所有 MyISAM 表自動啟用延遲鍵寫入。行為同表級選項,但範圍擴大到實例級。注意:崩潰恢復時間會增加,需權衡。
使用 myisamchk/isamchk 禁用啟用索引時,必須遵循表修復鎖定協議:
LOCK TABLES tbl WRITE;FLUSH TABLES tbl;UNLOCK TABLES;防止服務器進程同時修改表文件導致損壞。
| 策略 | 適用場景 | 風險/代價 |
|---|---|---|
| LOAD DATA + 多行 INSERT | 所有批量導入 | 需文件權限、SQL 解析限制 |
| 新表先數據後索引 | 全量構建新表 | 導入期間無索引查詢極慢 |
| 臨時表緩衝合併 | 高併發寫入+長查詢共存 | 數據延遲可見、雙表維護 |
| DELAY_KEY_WRITE | 海量插入、少讀、可修復 | 崩潰後需 REPAIR TABLE |
| 服務器級延遲寫入 | 整庫屬寫入密集型應用 | 所有 MyISAM 表受影響 |
實際架構中,常組合使用:如日誌系統採用「臨時表緩衝 + DELAY_KEY_WRITE + 定時合併」,數據倉庫採用「LOAD DATA + 先數據後索引 + 分區表」。核心原則始終是:批量化、延遲索引維護、隔離讀寫衝突。