首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 防止重複插入實戰:從應用層解決「同一記錄雙主鍵」問題

     編輯:MySQL 資料庫相關知識

開發反饋:同一業務邏輯在網頁端因卡頓導致用戶連點提交按鈕,造成資料庫插入兩條內容完全相同、但自增主鍵 ID 不同的記錄。本文記錄問題分析、解決方案探討與最終落地過程。

一、問題現場與表結構

SHOW CREATE TABLE HudsonResult;
# 關鍵結構
PRIMARY KEY (`ID`)  -- 單一自增主鍵
# 無唯一索引約束業務字段

插入語句:

INSERT INTO HudsonResult (JobID, EnvironmentID, FirstSessionID, RerunSessionID, State, Desp, OtherInfo)
VALUES ((SELECT ID FROM Hudson WHERE ...), 0, 'N', 'N', 'N', 'smoke_test', '');

二、資料庫層面方案探討

方案 A:增加業務唯一索引 + INSERT IGNORE / ON DUPLICATE KEY UPDATE

若在 (JobID, EnvironmentID, FirstSessionID, RerunSessionID, State, Desp, OtherInfo) 上建立唯一索引,可直接阻擋重複寫入。但開發表示業務邏輯複雜,難以確定唯一鍵組合,且 DDL 變更需審批流程較長。

方案 B:應用層 SELECT 先查後插 + 事務控制

START TRANSACTION;
SELECT 1 FROM HudsonResult WHERE ... FOR UPDATE;
-- 若不存在則 INSERT
COMMIT;

缺點:高併發下仍存在競態條件,需序列化鎖,效能損耗大。

方案 C:REPLACE INTO / INSERT ... ON DUPLICATE KEY UPDATE

依賴主鍵或唯一鍵判斷,因表無業務唯一鍵,無法直接應用。

三、最終解決方案:前端按鈕防重複提交

經溝通,開發採用最簡單有效的方案:

  1. 用戶點擊提交按鈕後,立即將按鈕設為 disabled / 灰色狀態。
  2. 前端阻止後續點擊事件。
  3. 等待後端響應(成功/失敗)後,根據結果恢復按鈕或引導下一步操作。

優勢:零資料庫變更、零效能損耗、徹底解決「手抖連點」導致的重複提交,兼容所有業務場景。

四、總結與延伸思考

  • 數據質量問題多源於應用層:資料庫約束是最後防線,應用層驗證才是根本治理。
  • 冪等性設計:所有寫入介面應具備冪等特性,配合唯一業務標識(如訂單號、請求 ID)實現安全重試。
  • 前後端協同:前端攔截誤操作、後端兜底校驗,雙重保障資料準確性。

本案例再次驗證:能在應用層解決的問題,絕不拖到資料庫層面硬扛。

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