通过将一个 DMSQL 语句块定义成自治事务,可以将该块中的 DML 语句和调用程序的事务环境隔离开。如此一来,该语句块就成为一个由其他事务启动的独立的事务,前一个事务被称为主事务。在自治事务块中,主事务是挂起的;等待自治事务完成后,会话自动切换回主事务。
一个定义了自治事务的语句块称为自治例程。
1.定义自治事务
定义自治事务,需要在 DMSQL 程序的声明部分添加如下语法的语句:
PRAGMA AUTONOMOUS_TRANSACTION;
自治事务的定义语句可以放在 DMSQL 程序声明部分的任何地方,但推荐放在数据结构声明之前。
作为自治事务的 DMSQL 语句块可以是下面中的一种:
最顶层的(不是嵌套的)匿名 DMSQL 语句块
函数和过程,或者在一个包里定义或者是一个独立的程序
对象类型的方法
数据库触发器
嵌套子过程
例如:
查询表 test:
SELECT * FROM test;
行号 C
---------- --------
1 自治事务
可以看到,表 test 中有记录“自治事务”,其所在自治事务提交,不受主事务回滚影响,而主事务插入的记录“主事务”被回滚。
2.自治事务完整性与死锁检测
自治事务的语句块执行完成时,如果事务仍处于活动状态,则系统需要报错:检测到活
动的自治事务处理,并将未提交事务回滚,所以需要在语句块结束处显式添加 COMMIT 或
ROLLBACK 语句。
另一方面,COMMIT 和 ROLLBACK 语句只是结束了活动的自治事务,但不会终止自治
例程。实际上,可以在一个自治块中使用多个 COMMIT、ROLLBACK 语句。
例如:
CREATE TABLE test (c VARCHAR);
executed successfully
used time: 10.401(ms). Execute id is 84.
SQL> INSERT INTO test VALUES('主事务');
affect rows 1
used time: 0.409(ms). Execute id is 85.
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO test VALUES('自治事务 1');
ROLLBACK;
INSERT INTO test VALUES('自治事务 2');
COMMIT;
END;
/
DMSQL executed successfully
used time: 4.979(ms). Execute id is 86.
SQL> ROLLBACK;
executed successfully
used time: 0.947(ms). Execute id is 87.
查询表 test:
SELECT * FROM test;
行号 C
---------- ---------
1 自治事务 2
自治事务相对主事务是完全独立的。由于执行自治事务时主事务处于挂起状态,如果自
治事务需要的锁资源已经被主事务拥有则会产生死锁报错。
3.自治事务嵌套
自治块中可以调用其它被定义自治事务的过程,从而产生嵌套的自治事务。例如:
CREATE TABLE TEST (C VARCHAR);
CREATE OR REPLACE PROCEDURE PROC_AUTO1
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
DELETE TEST WHERE C='嵌套事务';
COMMIT;
INSERT INTO TEST VALUES('自治嵌套事务');
COMMIT;
END;
/
CREATE OR REPLACE PROCEDURE PROC_AUTO2
IS
declare
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
CALL PROC_AUTO1;
INSERT INTO TEST VALUES('自治语句块');
COMMIT;
END;
/
INSERT INTO TEST VALUES('嵌套事务');
COMMIT;
INSERT INTO TEST VALUES('主事务');
CALL PROC_AUTO2;
ROLLBACK;
查询表 test:
SELECT * FROM test;
行号 C
---------- ------------
1 自治嵌套事务
2 自治语句块
DM 的 INI 参数 TRANSACTIONS 指定一个会话中可以并发的自治事务数量,其默认值为 75。如果实际生成自治事务数超出该参数限定值时,服务器将报错:“并发事务数超出上限”。该参数理论值上下限分别为 1000 和 1。