@JimmyTheWorm

Deadlock, что за зверь, с чем едят?

Здравствуйте. Имею небольшой сервер на node.js+mysql. использую движок mysqljs. Сам сервер парсит данные раз в минуту с некоторых сайтов и складывает их в таблицу бд(таблица получается относительно небольшой, 8к строк и около 15 столбцов). А также делает выборку из бд в таблицу html. С некоторого времени стали появляться ошибки "Error: ER_LOCK_DEADLOCK: Deadlock found when trying to get lock; try restarting transaction". Погуглив, я понял, что необходимо повторить запрос и ошибка уйдёт. С конкретным запросом то оно вроде пропадает, но тут же появляется новая ошибка лока, уже с другим запросом.
Также гугл подсказал делать commit'ы. Но возникает вопрос. На движке mysqljs вроде как нет возможности отправлять сразу несколько запросов вида
BEGIN;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

И приходится открывать pool, и делать много connection.query() запросов один за одним. Всё это ужасно не удобно.

Есть ли какой-то деликатный способ обхода ER_LOCK_DEADLOCK на nodejs?
Есть ли способ сбросить непроведённые транзакции?
Почему возникают дедлоки? Из-за того что sql не успевает обрабатывать данные? Если да, то поможет ли, если я создам новую таблицу и часть данных перенесу туда?

p.s. забыл написать, проверяю статус через "SHOW ENGINE INNODB STATUS", там выдаёт 3.5к строк текста, в которых написано что 140 локов висит
  • Вопрос задан
  • 1181 просмотр
Решения вопроса 1
bubandos
@bubandos
bash'у, javascript'ую, php'лю, css'аю, html'каю
Судя по исходным данным, тут не коммиты с транзакциями писать надо, а просто почитать про составление sql-запросов.
Запрос типа
INSERT INTO `table2`
SELECT `type` , SUM(`salary` ) 
FROM `table1`
GROUP BY `type`


UPDATE table2 AS t2 JOIN (
SELECT SUM( salary ) AS summary, 
TYPE FROM table1
GROUP BY TYPE
) AS t1 ON t1.type = t2.type
SET t2.summary = t1.summary WHERE t2.type = t1.type

решит вашу проблему.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
megafax
@megafax
web-программист
Вам как раз правильно гугл подсказал. Сама идея заключается в том, чтобы брать один коннект из пула и в рамках него уже делать всю транзакцию. Дедлок Вам говорит о том, что несколько запросов пытаются обратиться/изменить к одним и тем же данным. Можете решить этот вопрос при помощи транзакций, только нужно подобрать правильный уровень изоляции. Например, при самом строгом SERIALIZABLE Вам придется повторять транзакцию как раз при получении ошибки синхронизации.
https://dev.mysql.com/doc/refman/5.6/en/innodb-dea...
https://stackoverflow.com/questions/43625542/er-lo...
Ответ написан
@402d
начинал с бейсика на УКНЦ в 1988
https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D...

поправьте код так, чтобы ресурсы захватывались всегда в порядке а,б
или "Бери ложку и вилку сразу (WaitForMultipleObjects)"
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы