Эксклюзивные замки для обновления, а затем вставка не работает - PullRequest
0 голосов
/ 27 марта 2020

У нас возникли проблемы с эксклюзивными замками. У нас есть таблицы ниже:

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 выше, я вижу, что второй терминал ждет, пока первый терминал совершит транзакцию.

Есть идеи о том, что нам не хватает?

...