2016-07-25 2 views
1

Я использую pg-prom для запуска моих SQL-запросов. Сами запросы хранятся во внешних файлах .sql.Postgresql Поймать транзакционную ошибку и откат

Когда я выполняю транзакцию, Postgres прервет транзакцию, если произошла ошибка (как и ожидалось). Проблема, с которой я сталкиваюсь, - это любые отдельные запросы, которые я пытаюсь запустить после прекращения транзакции, не запускаются, и я получаю это сообщение: «текущая транзакция прерывается, команды игнорируются до конца транзакционного блока». Если запросы выполнялись в консоли psql, я мог бы решить эту проблему, выпустив ROLLBACK после неудавшегося запроса. Я не думаю, что это вариант здесь, поскольку SQL, используемый моим приложением, находится во внешнем файле. Я также не думаю, что Savepoints являются опцией, потому что вся транзакция должна быть выброшена, если что-то не удастся.

Как я откатился бы в файле SQL, если эта ошибка возникла?

Вот SQL для справки:

BEGIN; 

DELETE 
FROM tournament_tossup_values 
WHERE tournament_id = $1 AND 
NOT EXISTS 
(
    SELECT id 
    FROM tournament_match 
    WHERE tournament_id = $1 
); 

UPDATE tournament 
SET bonus_point_value = $5, parts_per_bonus = $6 
WHERE id = $1 AND NOT EXISTS (
    SELECT id 
    FROM tournament_match 
    WHERE tournament_id = $1 
) 
RETURNING bonus_point_value, parts_per_bonus; <-- Any subsequent accesses to the database by the application fail if this transaction fails 

COMMIT; <-- I want to rollback everything if this fails 

Спасибо заранее!

+0

Вы ссылаетесь библиотеки [pg-prom] (https://github.com/vitaly-t/pg-promise), но вы не используете его поддержку для транзакций - метод 'tx'? В этом случае мы не можем быть уверены в том, что происходит, поскольку вы не показываете полный код того, что делаете. Возможно, лучше всего использовать метод 'tx' и выполнять запросы в нем, как показано во всех примерах. См. [Транзакции] (https://github.com/vitaly-t/pg-promise#transactions). Это сделает ваш код более предсказуемым, поскольку в любом случае вы не обеспечиваете правильную логику «ROLLBACK» в вашем SQL. –

ответ

1

При реализации транзакции во внешнем файле SQL вам необходимо предоставить всю необходимую обработку для COMMIT и ROLLBACK. Когда вы этого не сделаете, статус транзакции может стать непредсказуемым внутри вашего кода на стороне сервера и привести к типу ошибок, которые вы получаете.

Это может быть немного сложнее и проще сказать, чем сделать. Вот почему лучшим решением является вовсе не делать этого.

Модуль pg-promise, который вы уже используете, обеспечивает надежную обработку транзакций методом tx, что и должно использоваться вами.

С этой целью разделить файл SQL в два файла - один с DELETE операции и один с UPDATE операции, а затем выполнить их в виде двух запросов внутри транзакции:

db.tx(t => { 
    return t.batch([ 
     t.none('DELETE...'), 
     t.any('UPDATE...') 
    ]); 
}) 
    .then(data => { 
     // success; 
    }) 
    .catch(error => { 
     // error; 
    }); 
+0

А, это решение, к чему я приближался. Просто хотел убедиться, что не было решения, которое позволило бы мне хранить все в одном файле SQL. Я продолжу и реализую его так, как вы описали выше. Благодаря! :) – mbhuiyan

+0

@mbhuiyan может быть однофайльное решение, но было бы более неудобно реализовывать и использовать, а не стоит делать, когда транзакция 'pg-prom' намного проще в использовании. –

Смежные вопросы