Является ли BEGIN-END блок атомарной транзакцией?
Ответ может быть легко найти, но не нашёл.
Когда есть блок BEGIN-END в PL/SQL, ведет ли он себя как атомарная транзакция, которая пытается зафиксировать изменения по достижении END блока, а если что-то пойдет не так, то откатит изменения?
Если нет, то как убедиться, что код внутри блока BEGIN-END ведет себя как атомарная транзакция? И как блок ведет себя "по умолчанию"?
Свободный перевод вопроса BEGIN - END block atomic transactions in PL/SQL от участника @Jan Kratochvil
Ответы (1 шт):
Во-первых, BEGIN-END это всего лишь синтаксические элементы, они не имеют никакого отношения к транзакциям.
Во-вторых, в Oracle БД все отдельные DML являются атомарными, т.е. они либо заканчиваются успехом в полном объеме, либо будет откат любых промежуточных изменений при первой ошибке (если только, не используется опция EXCEPTIONS INTO, о которой здесь не буду углубляться).
Если нужно, чтобы группа DML рассматривалась как единая атомная транзакция, то надо сделать что-то подобное:
BEGIN
SAVEPOINT start_trans;
INSERT INTO .... ; -- 1-й DML
UPDATE .... ; -- 2-й DML
BEGIN ... END; -- что-то еще в блоке
UPDATE .... ; -- последний DML
EXCEPTION WHEN OTHERS THEN
ROLLBACK TO start_trans;
RAISE;
END;
Таким образом, любое исключение приведёт к откату всех DML в этом блоке, но любые изменения, которые были произведены до этого блоке, не откатяться.
Заметте, что COMMIT не включен, т.к. последнее слово, фиксировать изменения или нет, должно осаться вызывающему процессу.
Это действительно так, что блок BEGIN-END без обработчика исключений неявно выполнит эту работу:
BEGIN
INSERT INTO .... ;
UPDATE .... ;
BEGIN ... END;
UPDATE .... ;
END;
Если будет исключение, все вставки и обновления будут откачены. Но как только добавить обработчик исключений, то отката не произойдёт. Поэтому, предпочтельно явно обрабатывать исключения с использованием точек сохранения траннзакции.
Свободный перевод ответа от участника @Jeffrey Kemp