#sql #sql-server #jpa #locking #pessimistic-locking
#sql #sql-сервер #jpa #блокировка #пессимистическая блокировка
Вопрос:
Справочная информация: в моем веб-приложении пользователи могут приобретать выбранные ими товары. Недавно мы обнаружили, что с некоторых пользователей взималась плата несколько раз за один и тот же список элементов. Проблема воспроизводима при одновременной отправке двух запросов на оплату. Информация о пользователе хранится в User
таблице, и каждая попытка оплаты пользователя Payment
сохраняется в таблице в базе данных MS SQL. Связь между Payment
и User
есть Many To One
.
Исправление проблемы: чтобы устранить проблему, я добавил логику, которая проверяет, есть ли уже запись, которая идентифицирует текущую попытку оплаты пользователя. Но в случае параллельных транзакций запись может не быть вставлена первой транзакцией при выполнении второй транзакции SELECT
с Payment
таблицей, поэтому я должен приостановить вторую транзакцию до тех пор, пока первая транзакция не вставит новую запись. Для этого я использую пессимистическую блокировку записи JPA для общего ресурса между параллельными транзакциями, который представляет собой запись из User
таблицы. Таким образом, поток параллельных транзакций будет следующим:
- Транзакция 1 считывает данные из
User
таблицы и накладывает эксклюзивную блокировку на строку, которая предотвращает чтение, обновление или удаление записи пользователя другими транзакциями. Сгенерированный SQL выбирает userdmo0_ .Идентификатор как Id1_31_, … из dbo.Пользователь userdmo0_ с (updlock, holdlock, rowlock), где userdmo0_.Id =? - Транзакция 2 не сможет принять блокировку, поэтому она будет ждать, пока транзакция 1 не снимет свою собственную блокировку.
- Транзакция 1 выполняет ВСТАВКУ … в
Payment
таблицу, фиксирует изменения в БД и снимает блокировку. - Транзакция 2 блокирует запись
User
таблицы. - Транзакция 2 проверяет, идет ли текущий платеж. Поскольку да, новые записи не будут вставлены в
Payment
таблицу. - Транзакция 2 снимает блокировку.
Вопрос: Исправление работает нормально. Однако то, что я пытаюсь понять / предсказать, — это влияние на производительность приложения. Было бы здорово, если бы я мог получить отличное объяснение, поскольку я не смог найти много подробной информации, связанной с аспектом производительности.
Как я читал в документах, при использовании пессимистических блокировок вы можете столкнуться с замедлением работы приложения в случае высокого параллелизма, поскольку несколько транзакций одновременно пытаются получить доступ к одному и тому же фрагменту данных. Я не думаю, что это мой случай, о котором мне следует беспокоиться, так как в течение дня есть только дюжина пользователей, у которых есть одна повторяющаяся запись в Payment
таблице, следовательно, вообще нет высокого параллелизма.
Но приложение работает при высокой нагрузке, например: платежи совершают 100 пользователей в секунду. MS SQL должен иметь возможность тратить больше ресурсов на обработку созданных им 100 блокировок, я прав? Кроме того, будет ли он пытаться увеличить блокировки строк до блокировки страницы или блокировки таблиц?