Я заметил, что одновременное выполнение простых и идентичных запросов, подобных
BEGIN;
SELECT files.data FROM files WHERE files.file_id = 123 LIMIT 1 FOR UPDATE;
UPDATE files SET ... WHERE files.file_id = 123;
COMMIT;
, приводит к тупику, что меня удивляет, так как похоже, что такие запросы не должны создавать тупик.Кроме того: для выполнения такого запроса обычно требуется всего несколько миллисекунд.Во время такой ситуации тупика, если я запускаю:
SELECT blockeda.pid AS blocked_pid, blockeda.query as blocked_query,
blockinga.pid AS blocking_pid, blockinga.query as blocking_query FROM pg_catalog.pg_locks blockedl
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid
JOIN pg_catalog.pg_locks blockingl ON(blockingl.transactionid=blockedl.transactionid
AND blockedl.pid != blockingl.pid)
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid
WHERE NOT blockedl.granted;
, я вижу оба моих идентичных оператора выбора, перечисленных для blocked_pid
и blockin_pid
для всей продолжительности тупика.
Итак, мой вопрос: нормально ли это для запросов, которые пытаются выбрать одну и ту же строку FOR UPDATE
, чтобы вызвать взаимоблокировку?И если да, то какова лучшая стратегия, чтобы избежать взаимоблокировок в этом сценарии?