MySQL Race Условия - PullRequest
       15

MySQL Race Условия

2 голосов
/ 28 апреля 2009

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

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

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

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

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

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

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

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

Спасибо.

Ответы [ 4 ]

4 голосов
/ 28 апреля 2009

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

1 голос
/ 19 августа 2010

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

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

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

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

Больше нет условий гонки.

1 голос
/ 28 апреля 2009

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

0 голосов
/ 28 апреля 2009

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

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

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

LOCK TABLE tablename - это другое.

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

...