Подтвердить что ты не робот

Поведение MySQL "выберите для обновления"

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

случай-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 не завершится.

случай-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 T2 ждет того же набора строк, что T1 заблокирован?

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

  • Можно ли каким-либо образом разрешить транзакции блокировать независимо, не указывая поле записи (т.е. без использования , где field = value)?
  • Обычно (или в соответствии с одновременной блокировкой Java) блокировка записи является эксклюзивной, а чтение - нет. В случае 2.1, хотя записи находятся в режиме блокировки записи, как T2 может читать одни и те же записи? Так как это разрешено, какова точка его блокировки?
  • Подразумевается случай 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.

  • Почему это поведение?
4b9b3361

Ответ 1

Позвольте мне разобраться в ваших делах и объяснить, как работают эти блокировки:

1 случай

T1 хочет обновить некоторые строки в тестовой таблице. Эта транзакция помещает фиксацию IX на всю таблицу и блокировку X в первых 5 строках.

T2 хочет обновить некоторые строки в тестовой таблице. Эта транзакция ставит IX (потому что IX совместим с IX) блокирует всю таблицу и пытается сначала 5 строк, но не может этого сделать, потому что X не совместим с X

Итак, мы в порядке.

2.1 case

T1 хочет обновить некоторые строки в тестовой таблице. Эта транзакция помещает блокировку IX на всю таблицу и блокировку X в первых 5 строках.

T2 хочет выбрать несколько строк из тестовой таблицы. И он не помещает никаких замков (поскольку InnoDB обеспечивает неблокирующие чтения)

2.1 case

T1 хочет обновить некоторые строки в тестовой таблице. Эта транзакция помещает блокировку IX на всю таблицу и блокировку X в первых 5 строках.

T2 хочет обновить (выбрать для обновления) несколько строк из тестовой таблицы. Поместите IS на всю таблицу и попытайтесь получить S-блокировку в строке и не получится, потому что X и S являются несовместимыми.


Также всегда следует знать уровень изоляции: разные уровни вызывают разный механизм освобождения/получения блокировок

Надеюсь, что это поможет