2010-05-11 5 views
5

Рассмотрим такую ​​ситуацию:Выполняет ли транзакция все проблемы с условиями гонки в MySQL?

  1. Begin сделка
  2. Вставка 20 записей в таблицу с auto_increment ключом
  3. Получить первую вставку идентификатора (скажем, это 153)
  4. Обновление всех записей в этой таблице где id >= 153
  5. Commit

Безопасен ли шаг 4?

То есть, если другой запрос поступает почти точно в одно и то же время и вставляет еще 20 записей после шага 2 выше, но до шага 4 будет состояние гонки?

+0

Почему у вас есть отдельный шаг обновления, а не просто вставка правильных данных в первую очередь? Это довольно странно. Вам не нужно будет беспокоиться о «состоянии гонки», если вы ввели правильные данные в первую очередь. Обновление 'WHERE id> 153' также очень странный запрос. Идентификаторы автоматического увеличения не имеют для них никакой логики, и поэтому вы никогда не должны (насколько мне известно) обновляться исключительно на основе id. И, наконец, я не знаю никакой функции «first insert id». –

+0

@ButtleButkus http://dev.mysql.com/doc/refman/5.0/information-functions.html#function_last-insert-id "Если вы вставляете несколько строк, используя один оператор INSERT, LAST_INSERT_ID() возвращает значение сгенерированный для первой вставленной строки " – nickf

+0

Вы правы относительно LAST_INSERT_ID(), но это не меняет того факта, что вопрос, похоже, связан с гипотетической ситуацией, которая никогда не будет существовать, если следовать основной структуре базы данных и процедуре. Почему ваш критерий обновления когда-либо был бы значением бессмысленного идентификатора? Я не могу думать ни о какой причине. Я бы не назвал это «расовым состоянием», потому что это бессмысленно. Зачем вам сразу обновляться после вставки, когда вы можете просто вставить правильные значения для начала?Это реальные причины, по которым этот вопрос не имеет смысла. –

ответ

5

То есть, если другой запрос поступает почти точно в одно и то же время и вставляет еще 20 записей после шага 2 выше, но до шага 4 будет состояние гонки?

Да, это будет.

Записи 21 по 40 будут заблокированы по сделке 2.

Сделка 1 будет заблокирована и дождитесь завершения транзакции 2.

Если транзакция 2 совершает, то транзакция 1 обновит 40 записи (включая вставленные транзакцией 2)

+1

Можете ли вы уточнить? Вы говорите, что есть проблема или нет? – nickf

+0

@nickf: см. Обновление сообщения. – Quassnoi

0

Я не думаю, что это может быть каталогизированы как условие гонки, а как специфическое поведение СУБД. В основном, если СУБД блокирует недавно вставленные записи, тогда первая транзакция не увидит записи со второго, пока не будет совершена вторая транзакция.

И, конечно, дело в блокировке таблицы, если первая транзакция записывает блокировку таблицы, а вторая блокируется при записи до тех пор, пока первая не завершится. Не уверен, хотя, если стандартный mysql предлагает такую ​​функцию. Я знаю сервер MSSQL.

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