INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES ({expr | DEFAULT},...),(...),...
| SET col_name={expr | DEFAULT}, ...
}
[ON DUPLICATE KEY UPDATE col_name=expr, ...]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ON DUPLICATE KEY UPDATE col_name=expr, ...]
INSERT DELAYED,服務器將行放入隊列,**立即返回 OK**。SELECT 讀取時暫停寫入,讀完繼續。VALUES 列表,**不支援 SELECT、ON DUPLICATE KEY UPDATE** (會被忽略)。LAST_INSERT_ID() (自增值尚未生成)。INSERT + 應用層異步隊列 (Kafka/RabbitMQ/Redis Stream)。STRICT_TRANS_TABLES 模式下部分錯誤仍會報錯。INSERT IGNORE INTO users (id, email) VALUES (1, 'a@b.com'), (2, 'c@d.com');
-- id=1 已存在則跳過,id=2 不存在則插入
-- 無需先 SELECT 判斷,原子化「不存在則插入」
表有 PRIMARY KEY 或 UNIQUE 索引,插入行導致鍵值衝突。
-- 假設 a 為 UNIQUE,已有 a=1
INSERT INTO t (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
-- 等效
UPDATE t SET c=c+1 WHERE a=1;
1:新插入 1 行。2:更新 1 行 (刪 1 + 插 1 內部實現)。>2:多個唯一索引同時衝突,刪除多行再插 1 行。INSERT INTO t (a,b,c) VALUES (1,2,3), (4,5,6)
ON DUPLICATE KEY UPDATE c = VALUES(a) + VALUES(b);
-- 第一行衝突 → c=1+2=3
-- 第二行衝突 → c=4+5=9
-- 僅在 ON DUPLICATE KEY UPDATE 子句中有意義
-- 假設 a、b 均為 UNIQUE
INSERT INTO t (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
-- 衝突條件:a=1 OR b=2
-- 若同時匹配多行,僅更新第一行 (LIMIT 1 隱含)
-- 建議:避免在多唯一鍵表使用,或確保業務邏輯單一衝突
| 場景 | 推薦語法 | 理由 |
|---|---|---|
| 海量日誌寫入、允許極小概率丟失、追求極致吞吐 | 應用層異步隊列 + 批量 INSERT (勿用 DELAYED) | DELAYED 已棄用、無序、不可靠 |
| 業務主鍵天然唯一 (如用戶 ID)、重複請求頻繁、需「不存在則插入」 | INSERT IGNORE | 無衝突報錯、原子化、無額外更新開銷 |
| 需「存在則更新、不存在則插入」完整 UPSERT 語義 | INSERT ... ON DUPLICATE KEY UPDATE | 單語句完成、避免 SELECT+INSERT/UPDATE 競態 |
| 需更新特定欄位、保留其它欄位舊值 | ON DUPLICATE KEY UPDATE col=new_val | 精準控制更新範圍 |
VALUES (...),(...),(...) (500~5000 行/批) 遠優於循環單條 INSERT。ON DUPLICATE KEY UPDATE 會加排他鎖 (X-lock) 衝突行,高並發熱點鍵易死鎖/鎖等待;考慮應用層去重或分佈式鎖。IGNORE 仍會檢查唯一索引,大量衝突時 CPU 開銷大;預先去重更佳。