如何处理这个数据并发问题?

时间:2011-07-20 06:22:11

标签: sql-server sql-server-2005 tsql

我正在做一个财务应用程序,我期待数据并发问题。

假设有一个账户ABC,其中有500美元。来自网络的用户可以将这些资金转移到其他帐户。这将涉及两个步骤,首先检查资金的可用性和第二次转移。我正在做一笔交易并在其中做两件事。

问题是在某个时间(比如Time1)有2或3个seprate转移请求(比如transaction1,transaction2,transaction3)相同的数量。现在承诺的可用金额是500美元。如果所有翻译都在同一时间开始,所有测试的金额(500美元)都可用吗?这将是真实的和下一个声明将资金转移到其他帐户。

我已经阅读了有关事务隔离级别但我无法确定应该使用哪个隔离级别,实际上我对它的理解感到困惑。请帮帮我。

由于

2 个答案:

答案 0 :(得分:1)

目的是防止另一个进程读取余额,但最大限度地减少对其他用户的阻止。因此,使用“table as a queue”类型锁定:

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

答案 1 :(得分:0)

为了避免提取超过价格的金额,您可以这样做:

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

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