資料庫併發插入避免重複資料的問題

2021-07-04 17:21:55 字數 1654 閱讀 1969

今天稍微研究了下這個問題從網上整理資料大致得到了如下方案,先粗略記錄下,下班回去再更詳細記錄下。

所有的方法都先不考慮效能問題,也不考慮業務,只看邏輯上能否達到去重,因為第一,如果唯一性是必須要保證的,那麼只能先實現了唯一,再去考慮優化;第二,如果能通過調整業務來規避,那我後面說的都是廢話了還有什麼看頭。

1.新增唯一索引。

但這種方法在表中有邏輯刪除時會有問題。   

後記:邏輯刪除如果用id來做刪除標識,應該也行。設刪除標識del_***,未刪除的用0做標記,刪除的用id做標記。設需要去重的字段為field_1,那麼用field_1和del_***組成聯合索引。邏輯刪除時將del_***設為與id相同,未刪除的del_***為0,

這樣聯合索引不會影響已刪除的,只會防止未刪除資料的重複。

2.加鎖。但是據查oracle中行鎖只能是寫時阻塞,且必須要該行資料存在,所以要確保你用來加鎖的字段在某個表已經存在(不存在的話也鎖不住),比如:如果你要在user_permission表中儲存user和permission的關係且user-permission的組合只能存在一條記錄。那麼此時如果兩個a,b程序同時都插入(user1,permission1)就會在表中產生重複資料。因為可以確定user1肯定已經在user表中存在,permission1肯定已經在permission表中存在,所以你可以考慮用這兩個表中的乙個來加鎖,具體插入步驟如下:

a、select * from user u where u.user = user1 for update

b、select count(*) from user_permission up where up.user = user1 and up.permission = permission1 然後判斷結果是否大於0

c、如果步驟b中結果等於0 則insert into from user_permission

按照以上的步驟,如果a程序先執行a步驟,則b程序會在a步驟阻塞,等a程序執行完後面兩步以後,b程序才會繼續執行b步驟,但此時a程序已經插入資料了,b程序查詢count等於1就不再插入。

但這種方法也有問題:假如此時正巧有人需要在user表中修改user1的基礎資料,就會被阻塞,等到別人執行完了才能執行;或者此時有個程序c想插入(user1,permisson2),雖然這條資料並沒有與a,b衝突,但是因為程序c在a步驟也發現user1加鎖了,所以也會阻塞,直到其他程序釋放。

3.多個連線需要插入的資料全插入後台的buff裡,然後在後台用乙個執行緒專門處理和資料庫的互動,從buff逐條讀取,再往資料庫插。因為最終插入資料庫只有乙個執行緒,所以只要在插入前檢測一下表中是否存在就可以了。

但是這種在分布式系統中這種方法肯定就跪了。

4.併發的資料都插入資料庫的中間表,然後做個後台儲存過程將中間表的資料往業務表插,這個過程中就可以保證相同資料只插入一條。

5.先插入重複資料,再用後台儲存過程刪除多餘的。

3,5 思想其實一樣,不過乙個是交給後台處理,乙個是交給資料庫處理。

其實還有一種方法,重複插入就重複插入唄。改,查的時候按最早插入時間來取第一條,刪除的時候全刪,統計的時候distinct ,當然在後台**中也要做是否有已存在記錄的檢驗,雖然不加鎖不能完全避免重複,但也要儘量減少不是。(此條權當玩笑吧 ->_->)。

大家都懂的,菜鳥寫部落格多多少少都會有問題,希望大家指正。只知道冷嘲熱諷的就不用來了,當然,諷完還能提建設性意見的我也可以接受 ->_->

mysql資料庫中避免重複資料插入

首先 資料庫中已經存在重複資料 並且資料量很大 之前並沒有設定重複欄位為唯一索引 需求 修改sql語句在插入時 避免重複插入 網上看了幾個部落格都是設定唯一索引 使用ignore或者replace into 或者on duplicate key update 如果資料存在會觸發更新操作 執行後面語句...

如何避免MySql資料庫的重複插入資料

通常我們需要避免資料庫重複插入操作的時候會給表設定主鍵或唯一索引,當插入重複資料的時候丟擲異常,程式終止,但是這樣也會存在一定的麻煩,所以就需要我們能盡量的避開或忽略異常。為了演示,我們新建乙個user測試表,包括欄位id username addr四個字段,其中主鍵為id 自增 同時對userna...

資料庫刪除重複資料

第一,資料庫中實體重複的解決方法。實體重複也就是完全重複 即表中兩行記錄完全一樣的情況。這類資料重複就需要刪除一條記錄,解決方法比較簡單,具體操作如下 使用select distinct from tablename就可以得到無重覆記錄的結果集。如果該錶需要刪除重複的記錄 重覆記錄保留1條 可以按以...