Как обеспечить возможность одновременного вызова эндпойнта, пишущего в БД?
Доброго дня.
Есть простой сервер на Express, БД postgres через sequelize. Если я делаю простой запрос через постман, то все отлично работает, но при тестировании нагрузок с 10 потоками одновременно наступает дедлок. Я попробовал сделать через транзакцию (1 запрос - 1 транзакция), но это не работает, в консоли просто выводится, что транзакция стартанула 10 раз, и потом эксепшен по таймауту.
Я знаю только одно решение - поднять redis и через менеджер очередей добавлять туда задание на обновление БД. А клиента заставлять ждать, пока не выполнится задание в очереди.
Но может, есть вариант проще \ лучше? Например, на уровне Постгреса или Sequelize.
Решение нужно искать не в последовательном исполнении, а понять что вы делаете с БД что два идентичных обращения вызывают дедлок.
Например: если вы делаете апдейт одной и той же строки - то вопрос а может ли прийти 10 таких запросов на одну строку?
а понять что вы делаете с БД что два идентичных обращения вызывают дедлок.
Именно обновляю одно и то же поле одной и той же строки. Это скорее задача со звездочкой из курса по ноде. Цимес в том, что я, как мне кажется, заоверинжинирил решение - про редис и очереди только в следующих главах, и должен быть способ проще, которого не получается придумать. Как будто должен быть механизм, когда самая шустрая транзакция вызывает лок, а остальные ждут и выполняются последовательно, но почему-то это не хочет работать и падают все сразу.
Алексей Николаев, самое простое организовать "контроль блокировки" на стороне nodejs-app\redis\memcached.
Как пример, создаете "блок данных" в котором храните ID той записи по которой будет выполнятся апдейт. При поступлении запроса проверяете наличие ID:
если НЕТ - добавляете и начинаете выполнять запрос, а по его завершении удаляете ID
если ЕСТЬ - делаете отбивку тому кто прислал такой запрос - мол, уже обрабатываем
Попытаюсь ответить как-то комплексно.
Дедлоки в базе данных могут быть вызваны различными причинами, такими как конфликты параллельных транзакций, блокировки на ресурсы и другие. В вашем случае, если у вас возникают дедлоки при одновременных запросах, использование транзакций может помочь, но вам также необходимо управлять блокировками и избегать конфликтов. То есть воспользоваться блокировкой на уровне строки (Row Locking) и блокировкой на уровне транзакции (Transaction Locking) это всё механизмы Sequelize. Вполне возможно, что даже при использовании этих механизмов могут остаться дедлоки. И в таком случае использование Redis будет необходимо.
Спасибо, я и не думал, что в Sequelize можно так. Ожидалось почему-то, что он сам все сделает, автоматически, а по факту надо было передать `lock: true`, и `transaction` при работе с моделью, плюс убрать `pool` из опций инстанса. В итоге помогло, и нагрузочное тестирование прошло