Пессимистическая блокировка JPA возможные проблемы с производительностью

#sql #sql-server #jpa #locking #pessimistic-locking

#sql #sql-сервер #jpa #блокировка #пессимистическая блокировка

Вопрос:

Справочная информация: в моем веб-приложении пользователи могут приобретать выбранные ими товары. Недавно мы обнаружили, что с некоторых пользователей взималась плата несколько раз за один и тот же список элементов. Проблема воспроизводима при одновременной отправке двух запросов на оплату. Информация о пользователе хранится в User таблице, и каждая попытка оплаты пользователя Payment сохраняется в таблице в базе данных MS SQL. Связь между Payment и User есть Many To One .

Исправление проблемы: чтобы устранить проблему, я добавил логику, которая проверяет, есть ли уже запись, которая идентифицирует текущую попытку оплаты пользователя. Но в случае параллельных транзакций запись может не быть вставлена первой транзакцией при выполнении второй транзакции SELECT с Payment таблицей, поэтому я должен приостановить вторую транзакцию до тех пор, пока первая транзакция не вставит новую запись. Для этого я использую пессимистическую блокировку записи JPA для общего ресурса между параллельными транзакциями, который представляет собой запись из User таблицы. Таким образом, поток параллельных транзакций будет следующим:

  1. Транзакция 1 считывает данные из User таблицы и накладывает эксклюзивную блокировку на строку, которая предотвращает чтение, обновление или удаление записи пользователя другими транзакциями. Сгенерированный SQL выбирает userdmo0_ .Идентификатор как Id1_31_, … из dbo.Пользователь userdmo0_ с (updlock, holdlock, rowlock), где userdmo0_.Id =?
  2. Транзакция 2 не сможет принять блокировку, поэтому она будет ждать, пока транзакция 1 не снимет свою собственную блокировку.
  3. Транзакция 1 выполняет ВСТАВКУ … в Payment таблицу, фиксирует изменения в БД и снимает блокировку.
  4. Транзакция 2 блокирует запись User таблицы.
  5. Транзакция 2 проверяет, идет ли текущий платеж. Поскольку да, новые записи не будут вставлены в Payment таблицу.
  6. Транзакция 2 снимает блокировку.

Вопрос: Исправление работает нормально. Однако то, что я пытаюсь понять / предсказать, — это влияние на производительность приложения. Было бы здорово, если бы я мог получить отличное объяснение, поскольку я не смог найти много подробной информации, связанной с аспектом производительности.

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

Но приложение работает при высокой нагрузке, например: платежи совершают 100 пользователей в секунду. MS SQL должен иметь возможность тратить больше ресурсов на обработку созданных им 100 блокировок, я прав? Кроме того, будет ли он пытаться увеличить блокировки строк до блокировки страницы или блокировки таблиц?