0

我有一個Web應用程序,用戶通過單擊按鈕「加入」進行註冊。網站上可能有這麼多用戶,這就是爲什麼爲了快速保持我的數據庫查詢的原因;我選擇不在數據庫中添加foriegnkey約束(雖然它是關係數據庫)。如何防止Web應用程序中的競爭條件

現在會發生什麼情況是,當具有相同userId的用戶在兩個不同的瀏覽器中打開應用程序並同時完全打開「加入」按鈕時;兩行爲同一用戶添加到數據庫中是錯誤的。

我必須停止這樣做的想法是:

  1. 不要在存儲過程和使用SQL事務隔離級別爲Serializable事務中的支票/插入邏輯;但即使兩個不同的用戶同時點擊「加入」按鈕,該方法也會被鎖定。
  2. 在c#中使用lock關鍵字,並從裏面執行檢查/插入邏輯,但我相信如果來自兩個瀏覽器的同一個用戶他們將獲得自己的鎖,並且仍然能夠在數據庫中擁有兩個條目。對於不同的用戶,它可能會產生問題,因爲其他代碼將等待第一個用戶釋放資源。
  3. 使用由EntityFramework支持的開放式併發性,但我不確定它是否能解決我的問題。

你能幫我解決嗎?

+0

你可以創建一個插入觸發器,它首先檢查id。如果存在,則從SQL中拋出一個錯誤,該錯誤應該傳播到堆棧中供您在前端處理。 – bilpor

回答

1

您可以通過在用戶名中創建唯一索引來輕鬆解決您的問題。所以,只有第一個會被保存。下一個將被報告爲錯誤,因爲它會破壞唯一索引。

實際上,它應該是主鍵。

根據你的意見,你的桌子是巨大的。因此,在整個表中查找一行而不使用每個插入操作的索引,而不是更新每個插入/刪除/更新操作的索引。你會考慮這個。

無論如何,解決未插入值的問題(如果已經存在)的唯一方法是檢查它。

樂觀併發與此無關。樂觀併發與讀取數據,修改和保存更改有關,而不鎖定表。什麼樂觀併發確實可以在這個步驟來解釋:

  1. 讀取數據庫的原始行,沒有任何鎖或交易
  2. 應用修改原始行,當應用程序試圖挽救cahnges
  3. 它會檢查數據庫中的行是否與在步驟1中讀取時完全相同。如果是,則更改將被保存。如果它不是拋出併發異常。

所以優化併發性不會幫助你。

我堅持使用獨特的索引,這是最安全,最簡單,也許更高性能的解決方案。

+0

我不能將它作爲主鍵,因爲有一些其他列作爲主鍵。此外,它增加索引的一個非常大的表將降低更新和刪除性能,並且在該表上發生頻繁的DML操作。 – user1955255

+0

我已經更新了我的答案。 – JotaBe

+0

感謝JotaBe的解釋 – user1955255

0

我會使用實體及其樂觀併發。

它會將其包裝在一個事務中併爲您處理這些問題。請記住在桌面上放置標識和主鍵。如果用戶名必須是唯一的,那麼在表上添加唯一的註釋。

+0

Optmistic Concurrency如何幫助解決問題中的問題? – JotaBe