2009-04-27 5 views
2

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

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

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

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

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

  5. Конец операции (фиксация/откат).

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

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

Спасибо.

+0

Вы видите это поведение? Или это чисто теоретический вопрос? – Joe

+0

Если у вас есть уникальный индекс в таблице журналов, то второй поток не сможет добавить туда дублируемую запись, а второй поток будет откат. Индексы на помощь еще раз. –

ответ

4

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

+0

Да, это бросает некоторых людей, но * технически * удаление - это своего рода обновление. – Powerlord

+0

Я использую ORM, который предотвращает это. Итак, вы можете подтвердить, что это состояние гонки? – user96747

+0

Я бы сказал, что да, это состояние гонки. – Powerlord

0

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

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

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

LOCK TABLE tablename - другой.

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

1

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

1

Start Transaction.

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

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

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

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

Смежные вопросы