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