Mysql處理Duplicate entry ‘6‘ for key ‘PRIMARY‘問題及解決

Mysql處理Duplicate entry ‘6‘ for key ‘PRIMARY‘

在業務中app和設備都需要調用ip查詢對應城市的天氣接口,出現瞭ip這個唯一索引引起的插入沖突。

以前單系統處理這種主鍵沖突或唯一索引沖突,都是先查詢後插入。

使用 if-else語句,判斷dp_city是否存在,若存在則更新,不存在則插入。

if not exists (select ip from dp_city where ip = adress)
      insert into dp_city (ip ,name,...) values(adress,name,...)
else
      update dp_city set name= 'name',... where ip = adress

但這樣寫不僅效率太差,每次都需要執行兩條SQL語句,一條語句用來判斷dp_city是否在表中已經存在,另一條語句用來插入或更新表中數據。

而且在高並發的場景下,兩個請求同一時刻都查到數據不存在,一個請求先插入數據,另一個請求再插入數據時就會出現主鍵或索引沖突的異常,也不能保證原子性。

解決這個問題最常規的做法是:加鎖 

加數據庫悲觀鎖太影響性能;加數據庫樂觀鎖,基於版本號判斷,一般用於更新操作,像這種插入操作基本上不會用。

另一種辦法是使用redis加入基於redis的分佈式鎖,鎖定已存在的ip。但也如果過度依賴redis,若是出現網絡超時,服務就悲劇瞭。

那麼有沒有更優雅高效的方法呢,通過查閱資料,發現MySQL一條語句很好的解決瞭這個問題:ON DUPLICATE KEY UPDATE

該語句的語法如下:

INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ON DUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, ...; 

這個語法的目的是為瞭解決重復性,當數據庫中存在某個記錄時,執行這條語句會更新它,而不存在這條記錄時,會插入它。

該語句規則如下:

如果你插入的記錄導致一個UNIQUE索引或者primary key(主鍵)出現重復,那麼就會認為該條記錄存在,則執行update語句而不是insert語句,反之,則執行insert語句而不是更新語句。 

mysql1062錯誤:Duplicate entry ‘…‘ for key ‘PRIMARY

問題解釋

Duplicate entry ‘…’ for key ‘PRIMARY,即插入數據時,要插入數據的主鍵數據(…)已經存在,不能再重復添加瞭。

例:Duplicate entry ‘0’ for key ‘PRIMARY是指主鍵為0的數據已經存在,不能再插入主鍵值為0的數據瞭。

問題解決

在執行插入操作insert前,可以先執行一遍該主鍵值的查找操作select

【簡單的來說,就是這個語句已經執行過瞭,無需重復執行】

1062、1060報錯都是一樣的

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: