Вопрос

Вызывает ли это состояние гонки с MySQL (InnoDB):

  1. Начать транзакцию.

  2. Попробуйте получить запись.

  3. Если запись не существует, вернитесь.

  4. Если запись существует, удалите ее и добавьте запись в журнал о том, что она была удалена.

  5. Завершить транзакцию (фиксация/откат).

Возможно ли, что другой процесс запустится непосредственно перед шагом удаления в шаге 2b, обнаружит наличие записи, а затем оба процесса введут записи об удалении элемента в журнал?

Есть ли какие-либо меры предосторожности, которые мне необходимо принять?

Спасибо.

Это было полезно?

Решение

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

Другие советы

Я считаю, что у подмастерья-программиста есть правильное решение.Поскольку вы указали, что используете неработающий инструмент ORM (который не позволит вам запрашивать обновления), я бы предложил вам переместить INSERT в таблицу журнала в триггер операции удаления, чтобы избежать дублирования. вход.

Начать транзакцию.

Удалить запись /* используя тот же критерий, который вы используете для «попытки получить запись» */

если ответ указывает на то, что запись действительно была удалена, добавьте запись в журнал.

Завершить транзакцию (фиксация/откат).

Нет больше состояния гонки.

Да, другая транзакция может проверить таблицу после того, как вы ее прочитали.

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

SELECT ... FOR UPDATE это один из способов предотвратить это.

LOCK TABLE tablename Другой.

К сожалению, поскольку вы используете ORM, я не могу сказать, способна ли она сделать что-либо из этого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top