2010-06-24 70 views
0

我理解編輯行如何導致併發問題,但選擇行導致的併發問題是我不明白的。線程安全「選擇」Linq查詢?

如果查詢從數據庫選擇數據,併發問題如何產生?是否如果對我選擇的數據進行了更改,事情會爆炸?

在任何情況下,如果由選擇查詢引起的併發問題,處理它的最佳方法是什麼?這是我的想法,但如果它錯了,我一點也不會感到驚訝。

try 
{ 
    var SelectQuery = 
    from a DB.Table 
    where a.Value == 1 
    select new {Result = a}; 
} 
catch 
{ 
    //retry query?? 
} 

回答

0

在這種情況下,您的選擇操作本質上等於讀取/查詢。即使只讀操作也會導致應用程序出現併發問題。

最簡單的例子是當讀取的對象具有線程相關性並且讀取發生在不同的線程中時。由於數據以不正確的方式訪問,這可能導致競爭。

處理併發問題的最好方法是簡單地避免它。如果你有2個線程玩同一個數據使用一個鎖來串行訪問數據是可能是最好的辦法。雖然一個明確的解決方案需要更多的細節。

你能解釋一下這裏發生了什麼,爲什麼這場比賽正在發生?其他線程在閱讀時是否修改此對象?

0

當您的查詢運行時,將生成一個SQL查詢以對應您的查詢。如果其他線程(或其他線程)試圖修改查詢中涉及的表,那麼數據庫服務器通常會檢測到這一點並處理必要的邏輯以避免造成任何實際問題。如果查詢執行更新語句時可能會花費較長的時間執行查詢,但唯一真正的問題是如果系統檢測到正在運行的事務的某個組合實際上導致了死鎖。在這種情況下,它會殺死其中一個連接。我相信只有當你的語句試圖更新數據庫值時纔會發生這種情況 - 而不是來自選擇。

查看您的示例,更重要的一點是您放入try/catch塊的代碼實際上並沒有執行任何查詢。它只是建立一個表達式樹。在你做一些事情導致表達式樹被評估之前,SQL查詢將不會被運行,就像調用SelectQuery.ToList()一樣。

請記住,當您嘗試查詢數據庫時,有很多事情可能「出錯」。也許有人正在對您嘗試選擇的數據進行大量更新,並且在完成查詢之前連接超時。也許電纜被碰撞,或者隨機的一點宇宙輻射導致某處丟失。然後再次,也許你的查詢有問題,或者你正在使用的數據庫上下文沒有同步到數據庫模式。一些可能出錯的事情只是間歇性的,你可以像你的問題一樣再試一次。其他事情可能會更持久,並會不斷重複。對於後面的情況,如果你試圖重複你的行動直到你不再犯錯,你的線程可能會在那裏停留很長時間。

因此,當您決定如何處理數據庫連接問題時,請注意您希望發生各種問題的頻率。我看到了在放棄之前嘗試執行三次交易的代碼,like this。但是當涉及到日常查詢時,這種情況很少發生,我個人只會允許異常涓涓細流到用戶界面可以說「出現意外錯誤,請再試一次,如果問題仍然存在,請聯繫你的管理員。「或類似的東西。