#postgresql #concurrency #transactions #plpgsql
Вопрос:
Я пытался ВСТАВИТЬ В…. ( ВЫБРАТЬ… ) (вставка пакета строк из подзапроса ВЫБРАТЬ…) в ту же таблицу в моей базе данных. По большей части это работало, однако время от времени я видел, как регистрировалось исключение «Тупик». Имеет ли смысл это делать или есть способ избежать тупикового сценария? На высоком уровне мои запросы оба похожи на эту структуру:
CREATE OR REPLACE PROCEDURE myConcurrentProc() LANGUAGE plpgsql AS $procedure$ DECLARE BEGIN LOOP EXIT WHEN row_count = 0 WITH cte AS (SELECT * FROM TableA tbla WHERE EXISTS (SELECT 1 FROM TableB tblb WHERE tblb.id = tbla.id) INSERT INTO concurrent_table (SELECT id FROM cte); COMMIT; UPDATE log_tbl SET status = 'FINISHED', WHERE job_name = 'tblA_and_B_job'; END LOOP; END $procedure$;
И другой скрипт, который выполняется параллельно и ВСТАВЛЯЕТ… также в ту же таблицу, также в основном:
CREATE OR REPLACE PROCEDURE myConcurrentProc() LANGUAGE plpgsql AS $procedure$ DECLARE BEGIN LOOP EXIT WHEN row_count = 0 WITH cte AS (SELECT * FROM TableC c WHERE EXISTS (SELECT 1 FROM TableD d WHERE d.id = tblc.id) INSERT INTO concurrent_table (SELECT id FROM cte); COMMIT; UPDATE log_tbl SET status = 'FINISHED', WHERE job_name = 'tbl_C_and_D_job'; END LOOP; END $procedure$;
Таким образом, вы можете видеть, что я запрашиваю две разные таблицы в каждом сценарии, однако вставляю их в одну и ту же some_table
. У меня также есть инструкция UPDATE…, которая записывает данные в таблицу журнала, поэтому я полагаю, что это также может вызвать проблемы. Есть ли какой-нибудь способ использовать BEGIN… ЗАКОНЧИТЕ здесь и ЗАФИКСИРУЙТЕ, чтобы избежать каких-либо проблем с взаимоблокировкой/параллелизмом, или мне следует просто создать 2-ю таблицу для хранения данных «tbl_C_and_D_job»?
Комментарии:
1. В файле журнала должна быть подробная информация о том, что на самом деле вызвало тупик. Пожалуйста, опубликуйте это.
2. Ваш пример кода синтаксически некорректен по нескольким причинам. Это затрудняет понимание того, что делает ваш реальный код.