2011-07-20 56 views
1

我在做一個財務應用程序,我期待數據併發問題。如何處理這個數據併發問題?

假設有一個賬戶ABC,其中500美元。來自網絡的用戶可以將這些資金轉移到其他帳戶。這將涉及2個步驟,第一次檢查資金的可用性和第二次轉移。我正在進行一項交易,並在其中採取兩項行動。

問題是在某個時間(比如Time1)有2或3個分離請求進行傳輸(比如transaction1,transaction2,transaction3)的數量相同。現在承諾的可用金額是500美元。如果所有翻譯都是在同一時間開始的,所有的測試都是可用的金額($ 500)?這將真實和下一個聲明將資金轉移到其他帳戶。

我已閱讀關於事務隔離級別,但我無法確定我應該使用哪個隔離級別,實際上我很困惑它的理解。請幫幫我。

由於

回答

1

目的是防止其他進程讀取該平衡,但最小化阻擋其他用戶。所以使用「表作爲隊列」類型的鎖從而:

SET XACT_ABORT, NOCOUNT ON; 
BEGIN TRY 

    BEGIN TRANSACTION 

    SELECT @balance = Balance 
    FROM SomeTable WITH (ROWLOCK, HOLDLOCK, UPDLOCK) 
    WHERE Account = 'ABC' 

    --some checks 

    UPDATE ... 

    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    ... 
END CATCH 

另一種方法是做在一個,如果有涉及一個表格,它是更爲可行。 的CROSS JOIN是一個測試,

SET XACT_ABORT, NOCOUNT ON; 
BEGIN TRY 

    --BEGIN TRANSACTION 

    UPDATE SomeTable WITH (ROWLOCK, HOLDLOCK, UPDLOCK) 
    SET Balance = Balance - @request 
    WHERE 
     ST.Account = 'ABC' AND Balance > @request; 
    IF @@ROWCOUNT <> 1 
     RAISERROR ('Not enough in account', 16, 1); 

    --COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    ... 
END CATCH 
+0

感謝GBN,它看起來很好的解決方案。有兩個問題。 1.我是否也必須釋放鎖定,否則它會自動提交。 2.它在SQL Server 2005中支持共享主機嗎? 謝謝 – user576510

+1

1.自動提交(HOLDLOCK更改持續時間)。 2.是的:這是標準的SQL – gbn

+0

在回滾的情況下locak會自動釋放嗎? – user576510

0

爲了避免大量的價格比大的退出時,你可以這樣做:

update <table> 
set amount = amount - @price 
where amount >= @price 
and account = @account 

if @@rowcount = 1 print 'transaction went well' else print 'Insufficient funds' 
+0

在非常高的負載下 – gbn

+0

因爲行鎖? –

+0

第二個進程在實際更改之前可以讀取天平。獨佔鎖定用於更改,而不是WHERE位。所以這就是UPDLOCK。 ROWLOCK可以防止超過一行的併發鎖定。 – gbn