問題:
1.高併發時,數據庫插入操作拋出DuplicateKeyException異常;
2.批量插入數據的時,數據庫插入操作拋出DuplicateKeyException異常;
異常信息如下:
org.springframework.dao.DuplicateKeyException: ....(具體信息省略......)
解決方案:
方案一:捕獲異常,適用於需要對異常處理的程序,如交易訂單號重複,給客戶友好提示;
try{
// 入庫操作
inset into ...
}catch (DuplicateKeyException e){
// 返回響應信息或或略
}
方案二:數據庫層面上進行忽略,這樣遇到重複值就會跳過,後面的數據任然可以插入,適用於對單條數據的操作要求不嚴 格,如批量處理數據;
1.insert ignore into ...
當插入數據時,如出現錯誤時,如重複數據,將不返回錯誤,只以警告形式返回。
所以使用ignore請確保語句本身沒有問題,否則也會被忽略掉。
例如:
INSERT IGNORE INTO table (XXX) VALUES ('xxx')
這種方法很簡便,但是有一種可能,就是加入不是因爲重複數據報錯,而是因爲其他原因報錯的,也同樣被忽略了。
2.on duplicate key update
當primary或者unique重複時,則執行update語句,如update後爲無用語句,如id=id,則同1功能相同,但錯誤不會被忽略掉。
例如:
INSERT INTO table (XXX) VALUES ('xxx') ON duplicate KEY UPDATE id = id
這種方法的前提條件,就是,需要插入的約束,需要是主鍵(primary key)或者唯一約束(unique key)。
3.insert … select … where not exist
根據select的條件判斷是否插入,可以不光通過primary key 和unique來判斷,也可通過其它條件。
例如:
INSERT INTO table (XXX) SELECT 'xxx' FROM dual WHERE NOT EXISTS (SELECT id FROM table WHERE id = 1)
這種方法其實就是使用了mysql的一個臨時表的方式,但是裏面使用到了子查詢,效率也會有一點點影響,不是很推薦級。
4.replace into
如果存在primary key or unique相同的記錄,則先刪除掉。再插入新記錄。
例如:
REPLACE INTO table SELECT 1, 'xxx' FROM table
這種方法就是不管原來有沒有相同的記錄,都會先刪除掉然後再插入。
方案三:在對數據操作之前,先去數據庫查重,然後對數據操作加鎖或休眠線程等待,例如:redis 或線程sleep;不推薦, 浪費系統性能,降低了系統的效率;
原因:
mysql在批量插入數據的時候,如果有一個字段具有unique約束或是primary key ,而插入數據重複的話,就會拋出DuplicateKeyException,導致後續批量數據無法插入;
相關知識點:
1.異常處理;
2.數據庫操作語句;
3.鎖機制;
代碼示例:
如上。