Автономные транзакции позволяют вам оставить контекст транзакции запроса, выполнить независимую транзакцию, и возвратиться к транзакции запроса, не влияя на ее состояние. У автономной транзакции нет ссылки к транзакции запроса, таким образом, только что зафиксированные данные могут быть совместно использованы обеими транзакциями.
Следующие типы PL/SQL блоков могут быть определены как автономные транзакции:
- Хранимые процедуры и функции.
- Локальные процедуры и функции, определяемые в PL/SQL блоке.
- Процедуры и функции PL/SQL пакетов.
- Методы типов.
- Верхний уровень анонимных PL/SQL блоков.
Самый легкий способ понять автономные транзакции состоит в том, чтобы увидеть их в действии. Чтобы сделать это, мы составим тестовую таблицу и заполним ее двумя строками. Заметьте, что данные не коммитятся.
CREATE TABLE at_test (
id NUMBER NOT NULL,
description VARCHAR2(50) NOT NULL
);
INSERT INTO at_test (id, description) VALUES (1, 'Description for 1');
INSERT INTO at_test (id, description) VALUES (2, 'Description for 2');
SELECT * FROM at_test;
ID DESCRIPTION
---------- --------------------------------------------------
1 Description for 1
2 Description for 2
2 rows selected.
SQL>
[/cc]
Затем мы вставляем еще 8 строк, используя анонимный блок, объявленный как автономная транзакция, которая содержит оператор фиксации.
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
FOR i IN 3 .. 10 LOOP
INSERT INTO at_test (id, description)
VALUES (i, 'Description for ' || i);
END LOOP;
COMMIT;
END;
/
PL/SQL procedure successfully completed.
SELECT * FROM at_test;
ID DESCRIPTION
---------- --------------------------------------------------
1 Description for 1
2 Description for 2
3 Description for 3
4 Description for 4
5 Description for 5
6 Description for 6
7 Description for 7
8 Description for 8
9 Description for 9
10 Description for 10
10 rows selected.
SQL>
Как ожидалось у нас теперь есть 10 строк в таблице. Если мы теперь сделаем откат транзакции, то получим следующий результат:
ROLLBACK;
SELECT * FROM at_test;
ID DESCRIPTION
---------- --------------------------------------------------
3 Description for 3
4 Description for 4
5 Description for 5
6 Description for 6
7 Description for 7
8 Description for 8
9 Description for 9
10 Description for 10
8 rows selected.
SQL>
Эти 2 строки, вставленные нашим текущим сеансом (транзакцией), откатились, в то время как строки, вставленные автономными транзакциями, остались. Присутствие PRAGMA AUTONOMOUS_TRANSACTION сделал анонимный блок выполняемым в его собственной транзакции, таким образом, внутренний оператор фиксации не влиял на сеанс запроса. В результате откат смог повлиять только на DML текущего оператора.
Автономные транзакции обычно используются подпрограммами регистрации ошибок, где сообщения об ошибках должны быть сохранены независимо от фиксации/отката транзакции. Например, следующая таблица содержит основные сообщения об ошибках.
CREATE TABLE error_logs (
id NUMBER(10) NOT NULL,
log_timestamp TIMESTAMP NOT NULL,
error_message VARCHAR2(4000),
CONSTRAINT error_logs_pk PRIMARY KEY (id)
);
CREATE SEQUENCE error_logs_seq;
Создадим процедуру, чтобы регистрировать сообщения об ошибках как автономную транзакцию.
CREATE OR REPLACE PROCEDURE log_errors (p_error_message IN VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO error_logs (id, log_timestamp, error_message)
VALUES (error_logs_seq.NEXTVAL, SYSTIMESTAMP, p_error_message);
COMMIT;
END;
/
Следующий код вызывает ошибку, которая перехватывается и регистрируется.
BEGIN
INSERT INTO at_test (id, description)
VALUES (998, 'Description for 998');
-- Force invalid insert.
INSERT INTO at_test (id, description)
VALUES (999, NULL);
EXCEPTION
WHEN OTHERS THEN
log_errors (p_error_message => SQLERRM);
ROLLBACK;
END;
/
PL/SQL procedure successfully completed.
SELECT * FROM at_test WHERE id >= 998;
no rows selected
SELECT * FROM error_logs;
ID LOG_TIMESTAMP
---------- ---------------------------------------------------------------------------
ERROR_MESSAGE
----------------------------------------------------------------------------------------------------
1 28-FEB-2006 11:10:10.107625
ORA-01400: cannot insert NULL into ("TIM_HALL"."AT_TEST"."DESCRIPTION")
1 row selected.
SQL>
В этом коде мы можем видеть, что транзакция LOG_ERRORS была отдельной в анонимном блоке. Если бы это не было не так, то мы ожидали бы, что первая вставка в анонимном блоке будет сохранена оператором фиксации в процедуре LOG_ERRORS.
Будьте осторожны при использовании автономных транзакций. Если они используются без разбора, то могут привести к мертвым блокировкам (deadlocks), и вызвать проблемы при анализе трассировки сеанса.
Где обычно используют автономные транзакции?
< Предыдущая | Следующая > |
---|