MySQL 在標準 SQL 基礎上擴展了三大 INSERT 修飾符,解決高併發寫入、冪等導入、業務 upsert 等典型場景。本文深度解析語法、行為差異、適用邊界與組合陷阱,給出選型決策表。
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_list)]
VALUES (val_list), ...
[ON DUPLICATE KEY UPDATE col=expr, ...]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
SET col=val, ...
[ON DUPLICATE KEY UPDATE ...]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_list)]
SELECT ...
[ON DUPLICATE KEY UPDATE ...]
kill -9 / 崩潰 / 重啟 → 隊列數據全丟。日誌寫入、埋點上報、非核心業務、極高寫入峰值、可容忍少量丟失。
affected_rows = 實際插入行數 (忽略的不計)。-- 大文件冪等導入,主鍵衝突自動跳過
INSERT IGNORE INTO facts (id, metric, val) VALUES ...;
-- 批量建立關聯,避免重複報錯
INSERT IGNORE INTO user_role (user_id, role_id) SELECT ...;
插入行導致 主鍵 或 任一唯一索引 衝突 → 執行 UPDATE 子句。
INSERT INTO stats (date, type, cnt) VALUES ('2024-01-15', 'pv', 1)
ON DUPLICATE KEY UPDATE cnt = cnt + VALUES(cnt);
多行批量 upsert 時,VALUES(col) 取對應行的插入值。
-- 表有 UK(a) 和 UK(b)
INSERT ... ON DUPLICATE KEY UPDATE ...
-- 若 a 衝突更新,b 也衝突但不同行 → 僅更新第一個匹配行 (非確定性)
-- 建議:單表最多一個唯一鍵參與 ODKU,或業務保證不同時衝突。
| 組合 | 行為 | 建議 |
|---|---|---|
| DELAYED + IGNORE | IGNORE 生效,DELAYED 入隊 | 可用,但 InnoDB 無效 |
| DELAYED + ODKU | DELAYED 被忽略,退為同步 INSERT + ODKU | 避免組合 |
| IGNORE + ODKU | 衝突時優先 ODKU (更新),不觸發 IGNORE | 語義明確,可組合 |
| LOW_PRIORITY + HIGH_PRIORITY | 互斥,後者生效 | 二選一 |
| 場景 | 推薦寫法 | 理由 |
|---|---|---|
| 日誌/埋點/監控數據,極高寫入,可丟 | INSERT DELAYED (MyISAM) | 異步入隊,客戶端零等待 |
| InnoDB 高併發寫入,需持久化 | 普通 INSERT + 批量多值 | DELAYED 無效,批量減少往返 |
| 定時同步/ETL 導入,主鍵衝突跳過 | INSERT IGNORE | 冪等、無報錯、簡單 |
| 業務 Upsert (有則改、無則增) | INSERT ... ON DUPLICATE KEY UPDATE | 原子化、避免 SELECT+INSERT 競態 |
| 計數器增量 (PV/UV/庫存) | ODKU + VALUES(col) | 單語句完成讀改寫 |
INSERT INTO t (a,b) VALUES (1,2),(3,4),...; 單條 500-1000 行,配合 max_allowed_packet 調大。DELAYED = 異步火力掩護 (MyISAM 專屬);IGNORE = 靜默冪等盾;ODKU = 原子 Upsert 劍。 InnoDB 時代 DELAYED 已邊緣化,核心武器是 批量多值 INSERT + ODKU。理解三者互斥規則與返回值語義,能在高併發寫入、數據同步、計數器業務中寫出正確、高效、可觀測的 SQL。