首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 批量更新神技:INSERT ... ON DUPLICATE KEY UPDATE 替代萬條 UPDATE 語句

     編輯:MySQL 綜合教學

場景:需一次性更新 5000 條會員記錄(id、name、email)。傳統 UPDATE 僅支援單條,循環執行 5000 次網絡往返極慢。MySQL 獨有的 INSERT ... ON DUPLICATE KEY UPDATE 可將「不存在則插入、存在則更新」合併為單條 SQL,實現批量 Upsert。

核心語法

INSERT INTO t_member (id, name, email) VALUES
  (1, 'nick', 'nick@126.com'),
  (4, 'angel', 'angel@163.com'),
  (7, 'brank', 'ba198@126.com')
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  email = VALUES(email);
  • VALUES(col) 引用插入行中對應列的值,避免重複寫常量。
  • 要求表有 主鍵或唯一索引,否則無法觸發「重複鍵」邏輯。
  • 非標準 SQL:僅 MySQL 支援,PostgreSQL 用 ON CONFLICT,SQL Server 用 MERGE,Oracle 用 MERGE。

性能對比(5000 條測試)

方式網絡往返耗時估算備註
循環 UPDATE5000~15-30 秒每條單獨解析、優化、執行
單條 INSERT ... ON DUPLICATE KEY UPDATE1~0.2-0.5 秒單次解析、批量執行,Redo Log 連續寫入

注意事項與避坑指南

  1. 自增主鍵不回退:即使觸發 UPDATE,AUTO_INCREMENT 計數器仍會增長,可能導致主鍵空洞。
  2. 觸發器雙重觸發:若表有 BEFORE INSERT/AFTER INSERT 觸發器,重複鍵更新時 只會觸發 BEFORE/AFTER UPDATE,INSERT 觸發器不會再跑。
  3. 唯一索引衝突語義:複合唯一索引 (a,b) 時,任一組合重複都會走 UPDATE 分支,需確認業務語義一致。
  4. 大批次分片:單條 SQL 超過 max_allowed_packet (默認 4MB/64MB) 會報錯,建議每 1000-2000 行分批提交。
  5. 死鎖風險:高併發下多線程同時 Upsert 相同鍵範圍易產生死鎖,應用層做好重試或按主鍵排序後分批。

擴展:僅更新部分列

INSERT INTO t_member (id, name, email, last_login) VALUES
  (1, 'nick', 'nick@126.com', NOW()),
  (4, 'angel', 'angel@163.com', NOW())
ON DUPLICATE KEY UPDATE
  last_login = VALUES(last_login),  -- 僅刷新登錄時間
  name = VALUES(name);              -- name 同步更新

未列在 UPDATE 子句的列(如 email)將保持原值不變。

總結

INSERT ... ON DUPLICATE KEY UPDATE 是 MySQL 批量 Upsert 的「殺手鐧」,能將萬條級更新從「分鐘級」壓縮至「毫秒級」。只要表有唯一鍵、業務允許非標準 SQL、注意分片與死鎖,即可放心用於生產環境核心寫入路徑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved