состояние гонки ОБНОВЛЕНИЕ модификация кредитной колонки - что происходит при откате? - PullRequest
0 голосов
/ 20 ноября 2010

хорошо, я попытался найти и не нашел ответа на этот вопрос - мне любопытно, как ROLLBACK справляется с условиями гонки.Например:

Если у меня есть таблица (CompanyAccount), которая отслеживает, сколько кредитов компания имеет для покупки (в таблице базы данных на одну компанию имеется только одна строка), и потенциально может быть несколько пользователей изта же компания, которая может уменьшить кредиты с одного корпоративного аккаунта, что произойдет в случае ошибки, когда произойдет ROLLBACK?

Пример:

Допущения: я правильно написал обновление для расчета«Кредитный» новый баланс вместо того, чтобы угадывать, что такое новый кредитный баланс (то есть мы не пытаемся сообщить оператору ОБНОВЛЕНИЯ, что такое новый Кредитный баланс / значение, мы говорим, взять все, что есть в столбце кредита, и вычесть значение моего уменьшенияв операторе UPDATE) ...

приведен пример написания инструкции обновления:

UPDATE dbo.CompanyAccount SET Credit = Credit - @DecrementAmount WHERE CompanyAccountId = @CompanyAccountId

Если в столбце «Кредит» указано 10 000 кредитов.Пользователь А вызывает уменьшение на 4000 кредитов, а Пользователь Б вызывает уменьшение на 1000 кредитов.По какой-то причине откат запускается во время декремента пользователя A (есть еще приблизительно полдюжины таблиц со строками, вставляемыми во время транзакции).Если пользователь A выигрывает условие гонки и новый баланс равен 6000 (но еще не зафиксирован COMMIT), что произойдет, если уменьшение пользователя B произойдет до применения отката?столбец баланса изменяется от 6000 до 5000, а затем получает откат до 10 000?

Мне не очень понятно, как ROLLBACK справится с этим.Возможно, я слишком упрощен.Может кто-нибудь, пожалуйста, скажите мне, если я неправильно понимаю, как будет работать ROLLBACK или есть другие риски, о которых мне нужно беспокоиться из-за этого стиля.

Спасибо за ваш вклад.

Ответы [ 2 ]

3 голосов
/ 20 ноября 2010

В приведенном вами примере проблем не будет.

Первая транзакция будет иметь эксклюзивную блокировку, что означает, что вторая не может изменять эту строку до тех пор, пока первая не будет зафиксирована или откатана.Ему просто придется ждать (заблокировано), пока не будет снята блокировка.

Это становится немного сложнее, если у вас есть несколько операторов.Вероятно, вам следует ознакомиться с различными уровнями изоляции и узнать, как они могут разрешать или предотвращать такие явления, как «потерянные обновления».

1 голос
/ 20 ноября 2010

Откат является частью транзакции, и блокировки будут сохраняться во время отката.* A * томический в кислоте.Пользователь B не запустится, пока не будут сняты все блокировки.

Что происходит:

  • Пользователь A блокирует строки
  • Пользователь B не увидит строки, пока блокировки не будутОсвобожден
  • Пользователь А откатывается назад, снимает блокировки, изменений не было.
  • Пользователь Б видит строки.-1000 приведет к 9000

Однако, если пользователь B уже прочитал баланс, он может быть непоследовательным, когда дело доходит до UPDATE.Это зависит от того, что вы на самом деле делаете и в каком порядке, следовательно, необходимо понимать уровни изоляции (и проблемы с фантомным и неповторяющимся чтением)

Альтернатива SERIALIZABLE илиREPEATABLE READ может использовать sp_getapplock в режиме транзакции для семафорных частей транзакции.

...