2015-07-16 1 views
0

Рассмотрим следующий рабочий процесс, работающий в MySQL с движком InnoDB.Каковы возможные режимы отказа чтения-фильтрации-записи внутри транзакции без блокировки?

  1. Начните сделку.
  2. Выберите несколько строк, используя SELECT FROM tablename WHERE ..., а не SELECT ... FOR UPDATE.
  3. Отфильтруйте эти строки, используя код, который не выполняется в базе данных (скажем, Python).
  4. Выполните команду DELETE в некоторых подмножествах строк.
  5. Завершить сделку.

На основании this question, кажется, что этот рабочий процесс небезопасен из-за шага 2, но ответы не дали подробностей о режимах отказа.

Является ли это просто неопределенным поведением или существует определенный, четко определенный набор режимов отказа?

Кроме того, почему здесь не существует характера ACID для защиты от небезопасного поведения?

ответ

0

DELETEs всегда будет в безопасности. Например, рассмотрите очередь, в которой SELECT извлекает некоторую «работу», и DELETE сигнализирует, что работа выполнена. Кроме того, предположим, что неприятные вещи произойдут, если работа будет выполнена дважды. (Возможно, что-то такое же простое, как приращение счетчика, - это какая-то другая таблица.) Без FOR UPDATE два потока могли бы захватить один и тот же элемент из очереди; один DELETE удалит строку; другой удалит нулевые строки (и вы не заметите этого).

Если вместо этого на этапе 3 участвуют UPDATEing некоторые из строк; есть довольно хороший шанс, что вы можете бросать конфликтующие обновления в строке (-ах).

Это два режима отказа. Обратите внимание, что они действительно являются сбоями приложений или данных, а не «неудачами» MySQL. Без FOR UPDATE MySQL рад «поступать не так».

Подумайте о FOR UPDATE: «Это минута, держите руки подальше!»

0

В итоге я обнаружил более серьезную проблему с этим сценарием, когда он чередуется с двумя другими транзакциями, что приводит к удалению непреднамеренных данных. Этот сценарий описан ниже, где name является первичным ключом, а gender - это еще один столбец.

Сделка 1

  1. DELETE FROM people WHERE name="foo";

Сделка 2

  1. SELECT name, gender FROM people WHERE name="foo";
  2. (логика приложения) If gender == female, then return.
  3. DELETE FROM people WHERE name="foo" // Обратите внимание, что целью является удаление foo только в том случае, если foo является мужчиной, основанным на логике приложения.

Сделка 3

  1. INSERT INTO people (name, gender) VALUES("foo", "female")

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

2.1, 2.2, 1, 3, 2.3 

С SELECT...FOR UPDATE, это не будет происходить, потому что SELECT предотвращает как 1.1 и 3.1 от происходящего.

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