2014-01-25 2 views
0

Я прочитал и протестировал блокировки на уровне строк в 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; 

Снова второй терминал блокируется первым! Есть ли сценарий, в котором заблокированы не все записи таблицы? Если нет, почему это называется «блокировка на уровне строк»?

+0

Несвязанные, но: в стандартных двойных кавычках SQL * используются * только для идентификаторов. Чтобы указать строковый литерал, используйте одинарные кавычки. '' B "' является именем столбца, но '' B'' является строковым значением. MySQL принимает неправильное и правильное письмо, но вы должны придерживаться стандартного соответствия, если вы когда-либо захотите использовать другую СУБД. Что касается вашего вопроса: я * думаю * (не уверен), что вы попали в «блокировку блокировки» MySQL, где он блокирует другие строки, а не только тот, который вы запросили. Вы также можете попробовать вместо этого «обновление». Возможно, 'select .. for update' ведет себя по-другому. –

+0

Спасибо за сообщение, я попытаюсь использовать '' 'вместо' '' с этого момента. – Mehran

+0

Btw: ваш пример работает так, как ожидалось, в Postgres и Oracle. –

ответ

1

Ответ на мой вопрос, как говорят в MySQL's manual:

Блокирующий чтение, обновление или DELETE, как правило, установленные блокировки записи на каждый индексную запись, проверяемые в обработке оператора SQL ,

Таким образом, замки применяются к записям, которые прокатываются во время траверсы, а не во всех записях. Если индекс не найден, выполняется полная развертка, и все записи блокируются. Поэтому мне нужно было установить индекс в столбце. Даже тогда, если какая-либо запись будет прочитана, когда вы попадете к целевым записям, тогда они также заблокированы (хотя они, возможно, не будут окончательно выбраны).

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