2011-07-20 3 views
1

Я делаю финансовое приложение, в котором я ожидаю проблему параллелизма данных.как справиться с этой проблемой параллелизма данных?

Предположим, что есть учетная запись ABC, в которой есть 500 долларов США. Пользователь из Интернета может перевести эти средства на другие счета. Это будет включать в себя 2 шага 1-й проверки наличия средств и 2-й передачи. Я делаю транзакцию и делаю в ней оба действия.

Проблема в том, что за какое-то время (скажем, Time1) есть 2 или 3 отдельных запроса на передачу (например, транзакция1, транзакция2, транзакция3) одинаковой суммы. Теперь выделенная сумма составляет 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 

Альтернативой сделать это в одном, что более целесообразно, если есть одна таблица. перекрестное соединение представляет собой тест для

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

Благодаря ГБН, это выглядит красиво решение. На это есть два вопроса. 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

2-й процесс может прочитать баланс до его фактического изменения. Исключительная блокировка - это изменение, а не бит WHERE. Таким образом, это делает UPDLOCK. ROWLOCK предотвращает блокировку более одной строки для параллелизма. – gbn

Смежные вопросы