У нас есть таблицы ниже:
mysql> desc journeys ;
+---------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| journey_id | char(36) | NO | PRI | NULL | |
| is_completed | tinyint(1) | NO | | 0 | |
| user_id | char(36) | NO | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| pack_id | char(36) | YES | MUL | NULL | |
| family_id | char(36) | YES | MUL | NULL | |
+---------------+------------+------+-----+---------+-------+
mysql> desc packs ;
+---------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| pack_id | char(36) | NO | PRI | NULL | |
| is_published | tinyint(1) | NO | | 0 | |
| order | int(11) | NO | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| family_id | char(36) | NO | MUL | NULL | |
+---------------+------------+------+-----+---------+-------+
Уровень изоляции - REPEATABLE_READ.
Согласно глоссарию здесь: https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_exclusive_lock
Эксклюзивная блокировка - это своего рода блокировка, которая предотвращает любую другую транзакцию от блокировки той же строки . В зависимости от уровня изоляции транзакции этот тип блокировки может блокировать запись других транзакций в одну и ту же строку или блокировать чтение других транзакций в той же строке.
Логика c, которая у нас есть, выглядит так, как показано ниже (user_id
принимает различные значения):
START TRANSACTION;
SELECT * FROM journeys WHERE user_id = <user_id> FOR UPDATE ;
# COMMIT;
Ниже приведено небольшое тестирование. Я открываю одно окно терминала (терминал # 1) и выполняю следующие инструкции:
START TRANSACTION;
SELECT * FROM journeys WHERE user_id = user_id_1 FOR UPDATE ;
Затем я открываю второе окно терминала (терминал # 2) и выполняю следующие инструкции:
START TRANSACTION;
SELECT * FROM journeys WHERE user_id = user_id_2 FOR UPDATE ;
Терминал № 2 теперь останавливается, потому что мы никогда не совершали транзакцию на терминале № 1.
Я предполагал, что, поскольку условие на первом терминале № 1 отличается от утверждения в терминале № 2 о том, что второй терминал не будет ждать первого принятия. Я основываю свое предположение на определении исключительной блокировки, которая говорит, что исключительная блокировка предотвращает любую другую транзакцию от блокировки той же строки. Это неправильное предположение? Если да, как можно заблокировать строки, которые у нас есть в первом условии?
Кажется, что все по-другому, когда я использую первичный ключ в условии. В приведенном ниже случае терминал # 2 не ожидает фиксации терминала # 1.
terminal #1
START TRANSACTION;
SELECT * FROM journeys WHERE journey_id = journey_id_1 FOR UPDATE ;
Операции в терминале # 2
terminal #2
START TRANSACTION;
SELECT * FROM journeys WHERE journey_id = journey_id_2 FOR UPDATE ;
Что именно происходит с эксклюзивными блокировками, когда у нас есть условия, которые не включают первичные ключи? Мы закрываем весь стол?