Поведение MySQL 'select for update'

Согласно документации MySql, MySql поддерживает блокировку с множественной гранулярностью (MGL).

case-1

Открыли терминал-1:

// подключились к mysql

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id, status from tracking_number limit 5 for update;
+----+--------+
| id | status |
+----+--------+
|  1 |      0 |
|  2 |      0 |
|  3 |      0 |
|  4 |      0 |
|  5 |      0 |
+----+--------+
5 rows in set (0.00 sec)
mysql> 

оставили его открытым и открыли терминал-2:

// подключились к mysql

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id, status from tracking_number limit 5 for update;

<!-- Hangs here. and after some time it says-->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

Хотя есть много строк для извлечения, T2 ждет, пока t1 не завершит работу.

case-2

Оставил терминал-1 как есть. Теперь в терминале-2:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

<!-- case 2.1 -->
mysql> select id, status from tracking_number where id=1;
+----+--------+
| id | status |
+----+--------+
|  1 |      0 |
+----+--------+
1 row in set (0.00 sec)

mysql> select id, status from tracking_number where id=2;
+----+--------+
| id | status |
+----+--------+
|  2 |      0 |
+----+--------+
1 row in set (0.00 sec)

<!-- case 2.2 -->
mysql> select * from tracking_number where id=2 for update;
<!-- Hangs here. and after some time -->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
  1. Но почему в случае 1, T2 ждет тот же набор строк, который T1 заблокировал?

  2. Значит ли это, что запрос select без ограничений (даже с параметром limint. Я пробовал и с другим диапазоном) блокирует всю таблицу?

  3. Есть ли способ позволить транзакциям блокировать независимо, не указывая поле записи (т.е., без использования where field=value)?
  4. Обычно (или согласно Java concurrent locking), блокировка на запись является эксклюзивной, а на чтение - нет. В случае 2.1, хотя записи находятся в режиме блокировки записи, как T2 может читать те же записи? Поскольку это разрешено, какой смысл в блокировке?
  5. Пример 2.2 понятен.

Открыл терминал и транзакцию:

mysql> update tracking_number set status=4 where status=0 limit 5;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5  Changed: 5  Warnings: 0

Оставил ее там и открыл другой терминал и транзакцию:

mysql> update tracking_number set status=5 where status=0 limit 5; 

T2 не удалась, пока я не зафиксировал (или откатил) T1.

  1. Почему такое поведение?
27
задан Pragalathan M 13 January 2012 в 11:14
поделиться