У нас возникли проблемы с эксклюзивными замками. У нас есть таблицы ниже:
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 | |
+---------------+------------+------+-----+---------+-------+
У нас также есть эти индексы:
+----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| journeys | 0 | PRIMARY | 1 | journey_id | A | 35 | NULL | NULL | | BTREE | | |
| journeys | 1 | pack_id | 1 | pack_id | A | 17 | NULL | NULL | YES | BTREE | | |
| journeys | 1 | family_id | 1 | family_id | A | 2 | NULL | NULL | YES | BTREE | | |
| journeys | 1 | user_id | 1 | user_id | A | 4 | NULL | NULL | | BTREE | | |
+----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
У нас есть AWS лямбда-функция (в node.js) и логика c выглядит так:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
(SELECT QUERY 1) SELECT `pack_id`, `is_published`, `order`, `family_id`, `created_at`, `updated_at` FROM `packs` AS `packs` WHERE `packs`.`family_id` = '6e9bdac8-1380-4e65-babc-be7858150bec' AND `packs`.`is_published` = true;
(SELECT QUERY 2) SELECT `journey_id`, `is_completed`, `user_id`, `created_at`, `updated_at`, `pack_id`, `family_id` FROM `journeys` AS `journey` WHERE `journey`.`user_id` = '58411ec6-493b-4173-8649-569eb624d46c' FOR UPDATE;
// There is a bit of logic in node.js here to find the difference between the packs and the journeys depending on the pack_id
// For example, if we find 8 results in the first query and 0 results in the second query, we are finding the difference and we
// insert it in the journeys table in the query below. So we expect 8 entries into the journeys table after the insert.
INSERT INTO `journeys` (`journey_id`,`is_completed`,`user_id`,`created_at`,`updated_at`,`pack_id`,`family_id`) VALUES
('032708d2-00e5-4933-b0d8-c53499b78a7c',false,'58411ec6-493b-4173-8649-569eb624d46c','2020-03-26 18:38:21','2020-03-26 18:38:21','004
7ebd6-129d-45e1-a347-41eda0ad1195','6e9bdac8-1380-4e65-babc-be7858150bec'),('75a11afd-1adf-4e5f-b44e-85e54421812b',false,'58411ec6-49
3b-4173-8649-569eb624d46c','2020-03-26 18:38:21','2020-03-26 18:38:21','1b42fa56-827b-442b-bc07-0be54843b8e6','6e9bdac8-1380-4e65-bab
c-be7858150bec'),('c12ab6ac-f5ec-423a-bffc-004292ca2f39',false,'58411ec6-493b-4173-8649-569eb624d46c','2020-03-26
18:38:21','2020-03-26 18:38:21','80707835-6d7f-47a9-9da8-294ab6d14f92','6e9bdac8-1380-4e65-babc-be7858150bec'),('f4bdf022-2756-4ceb-a
8d0-065abcecc071',false,'58411ec6-493b-4173-8649-569eb624d46c','2020-03-26 18:38:21','2020-03-26 18:38:21','82061215-d24d-4012-b95c-a
e9ded725fa9','6e9bdac8-1380-4e65-babc-be7858150bec'),('d86f30e5-4e03-4638-b415-0a4340ab23b2',false,'58411ec6-493b-4173-8649-569eb624d
46c','2020-03-26 18:38:21','2020-03-26 18:38:21','ad1623cf-a357-47fa-8745-3c2ac7c40af6','6e9bdac8-1380-4e65-babc-be7858150bec'),('cfa
0e974-9ee5-424c-9ccc-c0a2c068309a',false,'58411ec6-493b-4173-8649-569eb624d46c','2020-03-26 18:38:21','2020-03-26 18:38:21','d6d61531
-88b2-4d44-8357-19e95c4ca379','6e9bdac8-1380-4e65-babc-be7858150bec'),('0faced86-29aa-429d-a763-c9d79898cebf',false,'58411ec6-493b-41
73-8649-569eb624d46c','2020-03-26 18:38:21','2020-03-26
18:38:21','e6e737f8-d051-4b6f-b93a-765b6e39038b','6e9bdac8-1380-4e65-babc-be7858150bec');
COMMIT;
Сценарий таков:
Мы запускаем два запроса API POST параллельно
Две лямбды работают одновременно и выполняют точно такую же логику c выше
Кажется, что блокировка в SELECT QUERY 2 не работает. Довольно часто мы получаем 16 записей в таблице поездок.
Мы ожидаем, что в таблице поездок должно быть только 8 записей, потому что первый запрос заблокирует строки, поэтому второй запрос должен подождите, пока будет снята первая блокировка. Первый запрос вставки в таблицу фиксирует и снимает блокировку. Затем второй запрос должен получить доступ к данным о поездках, но он получит самые последние результаты.
Странно то, что когда я открываю два терминала, я подключаюсь к базе данных и выполняю Логика c выше, я вижу, что второй терминал ждет, пока первый терминал совершит транзакцию.
Есть идеи о том, что нам не хватает?