今天收到一個小學弟的求助,數據庫插入偶爾重復,怎么在sql語句上進行解決。
Q:學長,我導入excel數據的操作,平時使用好好的,怎么突然發生插入重復的問題?
A:你是使用哪個ORM框架進行操作的?
Q:什么是ORM框架?
A:額……,你數據庫怎么鏈接操作的?
Q:我使用Connection對象進行鏈接操作的。
A:哦,ADO.NET呀,你把導入數據的插入sql語句的截圖發出來看看。
Q:sql截圖(這里就不展示了,就是一個簡單的insert into,如:INSERT INTO aTable(id) VALUES("1"))
A:哦哦,你語句沒有並發情況下沒問題,但是多人同時導入數據就存在並發,數據重復意料之中。
Q:啊,這還涉及到並發?那我怎么修改呀
A:簡單,不改變其他操作的情況下,你把插入語句加事務加鎖機制既可以了。
Q:額……不怎么懂,有demo嗎?
A:沒事,我就在你的sql語句上優化下,你直接粘貼就可以了。
我們來解刨一下這個問題,現在很多人依賴ORM,都沒怎么寫sql了,我們就從sql的角度解析一下這個問題。
這里不好提供代碼展示,我們這里就簡單進行一個模擬還原使用場景。
創建一個表,命名為aTable,里面就一個字段id,int類型,然后插入一個數據為1;
操作一:重現問題出現原因
然后同時(有點間隔也沒關系,但隔時間要小)在查詢分析器的兩個窗口中執行下如下語句:
declare @id int set @id = ( select max(id) from aTable ) while @id < 40000 begin set @id = @id + 1 insert into aTable ( id ) select @id set @id = ( select max(id) from aTable ) end
這樣的目的在於測試當兩個用戶同時操作同一個表時的重復性操作,模擬多用戶同時導入相同的excel數據,
結果:共得到42953條數據,其中2953條重復,當然,這個重復數據跟執行間隔時間有關。
操作二:進行第一步優化,添加事務
sql語句加上事務處理,
然后同時(有點間隔也沒關系,但間隔時間要小)在查詢分析器的兩個窗口中執行下如下語句:
begin tran --開啟事務 declare @id int set @id = ( select max(id) from aTable ) while @id < 40000 begin set @id = @id + 1 insert into aTable ( id ) select @id set @id = ( select max(id) from aTable ) end commit tran --提交事務
結果:共得到40000條數據,無重復,但是執行時間是沒加事務處理時的6倍,時間太久。
操作三:進行第二步優化,添加鎖
sql語句加上事務處理和鎖機制,
然后同時(有點間隔也沒關系,但間隔時間要小)在查詢分析器的兩個窗口中執行下如下語句:
begin tran --開始事務
declare @id INT
set @id = ( select max(id) from aTable )
while @id < 40000
begin
set @id = @id + 1
--添加鎖 with(tablock)
insert into aTable with (tablock) ( id ) select @id
set @id = ( select max(id) from aTable )
end
commit tran --提交事務
結果:共得到40000條數據,無重復,執行時間快。
這樣就從sql上簡單解決並發問題啦,當然,還有其他問題和解決方法,
這里就不做敘說了,具體情況遇到再分析,拜拜。
![]()
歡迎關注訂閱我的微信公眾平台【熊澤有話說】,更多好玩易學知識等你來取
作者:熊澤-學習中的苦與樂 公眾號:熊澤有話說 出處: https://www.cnblogs.com/xiongze520/p/14524707.html 創作不易,轉載或者部分轉載、摘錄,請在文章明顯位置注明作者和原文鏈接。
|