Я написал следующий триггер, чтобы гарантировать, что поле «fileequence» на вставке всегда имеет максимальное значение + 1 для одной заинтересованной стороны.Проблема параллелизма Postgres
CREATE OR REPLACE FUNCTION update_filesequence()
RETURNS TRIGGER AS '
DECLARE
lastSequence file.filesequence%TYPE;
BEGIN
IF (NEW.filesequence IS NULL) THEN
PERFORM ''SELECT id FROM stakeholder WHERE id = NEW.stakeholder FOR UPDATE'';
SELECT max(filesequence) INTO lastSequence FROM file WHERE stakeholder = NEW.stakeholder;
IF (lastSequence IS NULL) THEN
lastSequence = 0;
END IF;
lastSequence = lastSequence + 1;
NEW.filesequence = lastSequence;
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';
CREATE TRIGGER file_update_filesequence BEFORE INSERT
ON file FOR EACH ROW EXECUTE PROCEDURE
update_filesequence();
Но я повторил «filesequence» в базе данных:
select id, filesequence, stakeholder from file where stakeholder=5273;
id filesequence stakeholder
6773 5 5273
6774 5 5273
По моему undertanding, в SELECT ... FOR UPDATE запирали две сделки на той же заинтересованной стороной, а затем второй один будет читать новое «fileequence». Но это не работает.
Я сделал несколько тестов на PgAdmin, выполнив следующие действия:
BEGIN;
select id from stakeholder where id = 5273 FOR UPDATE;
И действительно LOCKED других записей вставляются в ту же заинтересованную сторону. Тогда кажется, что LOCK работает.
Но когда я запускаю приложение с одновременными загрузками, я вижу, что повторяю.
Кто-то может помочь мне найти, что является проблемой с моим триггером?
Thanks, Douglas.
В plpgsql, не первый BEGIN отмечает начало блока, а не начало транзакции? –
Личный вопрос: где вы научились использовать 'PERFORM', как это? Я видел много людей, которые это делали, и я не знаю, почему. (это неправильно, см. мой ответ) ... – MatheusOl
@ MikeSherrill'Catcall ', что 'BEGIN' не запускает транзакцию, но на PostgreSQL функция ** всегда ** называется ** внутри транзакции **. – MatheusOl