DuplicateKeyException: 主鍵沖突異常
catch (DuplicateKeyException e) { logger.info("重復請求。feeDetail={}", feeDetail.toString()); }
最近項目中遇到一個問題,我們提供的一個對外的服務接口在數據庫網絡層報錯DuplicateKeyException,是由於業務方重復調用而業務本不該重復調用,但是我們管不了業務方只能自己調整。
思路一:
去掉設置的數據庫層的唯一約束,報錯是解決了但是會引起后面一系列的問題,肯定是行不通的。
思路二:
插入數據之前先判斷數據存在否,不存在再插入。但是高並發的情況下還是會存在問題,除非給數據加鎖,但是這樣復雜度更高並沒有必要。
思路三:
數據庫層面的問題從數據庫解決,可以用 insert ignore來解決,insert ignore就表示存在則插入不存在則忽略。
思路三是很好的解決方法,但是遇到另一個問題,之前我插入之后都是把新生成的id返回回去,insert ignore則不管插入成功與否都會返回這個id,也就是業務邏輯那里並不能確定到底插入成功與否,插入的數據涉及到計算結果,為保證接口的冪等性,之前是在catch住DuplicateKeyException后又做了一些列的邏輯處理來保證接口冪等性。
現在的問題由數據庫報錯變成了如何知道數據庫是否真正插入數據,這時候想到了ROW_COUNT()來判斷數據庫的執行結果。
最后業務層根據返回的id是否是0就可以判斷數據是否真正插入,到這里問題也就解決了。