FOR UPDATE ВЫБОРА Mysql - странная проблема

У меня есть странная проблема (по крайней мере, для меня :)) со средством блокировки MySQL.

У меня есть таблица:

create table `test` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  PRIMARY KEY (`id`)  
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1

С этими данными:

+----+
| идентификатор |
+----+
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 10 |
| 11 |
| 12 |
+----+

Теперь у меня есть 2 клиента с этими командами, выполняемыми вначале:

набор autocommit=0;
сериализуемый уровень изоляции транзакции сессии набора;
начните;

Теперь самая интересная часть. Первый клиент выполняет этот запрос: (делает намерение вставить строку с идентификатором, равным 9),

ВЫБЕРИТЕ * из теста где идентификатор = 9 FOR UPDATE;
Пустое множество (0,00 секунды)

Затем второй клиент делает то же:

ВЫБЕРИТЕ * из теста где идентификатор = 9 FOR UPDATE;
Пустое множество (0,00 секунды)

Мой вопрос: Почему второй клиент не блокируется? Эксклюзивная блокировка разрыва должна была быть установлена первым запросом, потому что FOR UPDATE использовался, и второй клиент должен заблокироваться.

Если я неправ, кто-то мог бы сказать мне, как сделать это правильно?

Версия MySql, которую я использую: 5.1.37-1ubuntu5.1

7
задан Mohsen Nosratinia 8 May 2015 в 14:19
поделиться

2 ответа

Потому что в это время безопасно возвращать (пустой) результат - re не устанавливает блокировку для записи с id = 9, поскольку она не существует и, следовательно, не может быть обновлена ​​- я не думаю, что вы можете полагаться на innodb, устанавливающий блокировки чтения в таком случае. Однако он должен установить блокировку записи на id = 9.

Если позже одна из транзакций действительно обновит таблицу и коснется тех же данных, что и другая транзакция, обновление, скорее всего, заблокирует одну из транзакций, а затем потерпит неудачу, если другая транзакция зафиксирует эти данные. Совершенно нормально, что транзакции терпят неудачу в подобных сценариях - оставляя вас заниматься этим - обычно это вопрос повторной попытки транзакции.

Если бы существовала запись с id = 9, вы, вероятно, увидели бы блок 2. select до завершения первой транзакции, так как теперь есть запись, которую необходимо заблокировать для чтения в случае, если первая транзакция решает обновить эту строку.

3
ответ дан 7 December 2019 в 18:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: