Я прочитал и протестировал блокировки на уровне строк в InnoDB MySQL, но мне все еще трудно сказать «Я знаю, как блокировки работают в MySQL»!Какие записи заблокированы с помощью MySQL «SELECT ... FOR UPDATE»
Вот мой тест данные:
mysql> select * from lockable;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
| 1 | A | A |
| 2 | A | B |
| 3 | A | C |
| 4 | B | A |
| 5 | B | B |
| 6 | B | C |
| 7 | C | A |
| 8 | C | B |
| 9 | C | C |
+----+----+----+
9 rows in set (0.00 sec)
Для того, чтобы проверить поведение MySQL в отношении блокировок на уровне строк, я открыл два терминала и подключен к MySQL. Я назову их mysql1>
и mysql2>
. Вот что я выполнил на первом терминале:
mysql1> ROLLBACK;
mysql1> BEGIN;
mysql1> SELECT id, c1, c2 FROM lockable WHERE c1 = "A" FOR UPDATE;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
| 1 | A | A |
| 2 | A | B |
| 3 | A | C |
+----+----+----+
3 rows in set (0.00 sec)
Затем на втором терминале:
mysql2> SELECT * FROM lockable WHERE c1 = "B" FOR UPDATE;
К моему удивлению, приведенный выше запрос будет заблокирован первым! Так что я отвалил первый терминал и начал снова:
mysql1> ROLLBACK;
mysql1> BEGIN;
mysql1> SELECT id, c1, c2 FROM lockable LIMIT 3 FOR UPDATE;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
| 1 | A | A |
| 2 | A | B |
| 3 | A | C |
+----+----+----+
3 rows in set (0.00 sec)
Затем на втором терминале:
mysql2> SELECT * FROM lockable WHERE LIMIT 6,1 FOR UPDATE;
Снова второй терминал блокируется первым! Есть ли сценарий, в котором заблокированы не все записи таблицы? Если нет, почему это называется «блокировка на уровне строк»?
Несвязанные, но: в стандартных двойных кавычках SQL * используются * только для идентификаторов. Чтобы указать строковый литерал, используйте одинарные кавычки. '' B "' является именем столбца, но '' B'' является строковым значением. MySQL принимает неправильное и правильное письмо, но вы должны придерживаться стандартного соответствия, если вы когда-либо захотите использовать другую СУБД. Что касается вашего вопроса: я * думаю * (не уверен), что вы попали в «блокировку блокировки» MySQL, где он блокирует другие строки, а не только тот, который вы запросили. Вы также можете попробовать вместо этого «обновление». Возможно, 'select .. for update' ведет себя по-другому. –
Спасибо за сообщение, я попытаюсь использовать '' 'вместо' '' с этого момента. – Mehran
Btw: ваш пример работает так, как ожидалось, в Postgres и Oracle. –