Deadlock в insert запросе в postgres
Получаю время от времени ошибку
Message: SQLSTATE[40P01]: Deadlock detected: 7 ERROR: deadlock detected
Запрос вида (для примера сокращу, в запросе может быть до 250 строк и много контента):
INSERT INTO link (
parsed,
error,
error_message,
url,
title,
author_name,
date,
date_parsed,
updated_at,
rss_id,
content,
content_tsvector
) VALUES (true, false, '', 'https://medium.com/@scottishforsocial/a-leading-voice-from-india-transforming-indian-education-8655f91dd7b7', 'A leading voice from India-Transforming Indian Education', 'ScottishHigh', '2020-08-06 04:50:16', '2020-08-07 08:30:14', '2020-08-07 08:30:14',
221808, 'content', to_tsvector('content')) ON CONFLICT DO NOTHING
RETURNING id, rss_id
Так же есть ньюанс что подобные запросы выполняются на 40 серверах к одной базе данных
Как с таким бороться?
Ответы (1 шт):
Автор решения: Мелкий
→ Ссылка
в запросе может быть до 250 строк
Логично предположить, что конкурентно вставляете одни и те же данные в разном порядке.
Как же ON CONFLICT DO NOTHING? А что он может?
- t1: begin
- t2: begin
- t1: insert 1 on conflict - никто не мешает, записали
- t2: insert 2 on conflict - никто не мешает, записали
- t2: insert 1 on conflict - хм, это же значение пишет t1, но мы не знаем можем ли мы сделать do nothing, т.к. если t1 сделает rollback - мы сделаем неправильный выбор. Потому ждём окончание t1
- t1: insert 2 on conflict - а это значение хочет t2 писать, подождём её завершения.
- t1 или t2 спустя время deadlock_timeout - что-то я долго жду, проверю-ка граф ожиданий. Опа, действительно deadlock, отменяю свою транзакцию. Вторая транзакция соответственно разблокируется.
insert на много строк всё равно транзакция и потому может быть аналогично.
Отсортируйте записываемые множества по какому-либо признаку в идентичном порядке.