今天收到一個國小弟的求助,資料庫插入偶爾重複,怎麼在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 創作不易,轉載或者部分轉載、摘錄,請在文章明顯位置注明作者和原文連結。 |