我的情况很奇怪
很难解释,但我会尽力的
包括3个不同的数据库
我从DB1调用DB2上的函数(通过dblink)
该过程调用另一个将数据插入DB3上的表的过程
DB2上的函数具有EXCEPTION句柄,该句柄应在发生异常的情况下回滚它所做的一切
我确实运行了示例,并且一切顺利(没有错误),但是没有回退过程3中的插入,因此我必须从DB1回滚到真正的回滚
如果我从db1中提交,则会插入行
我做错什么了吗,有没有办法直接从db2上的函数回滚
这是一些示例代码:
--DB1
PROCEDURE 1
BEGIN
x := function2@dblink_to_db2();
END;
--DB2
FUNCTION 2
BEGIN
procedure3();
RAISE SOME EXCEPTION;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
do_something_else();
RETURN 0;
END;
PROCEDURE 3
BEGIN
INSERT INTO tableA@dblink_to_db3 VALUES ... ;
END;
因此不会引发任何错误,但是不会回滚到db3上的表中
答案 0 :(得分:0)
您必须在引发异常之前或在Procedure3中在代码中的某个位置进行提交。我只是测试了下面的代码,它回滚了异常之前的所有内容。请忽略命名约定,由于时间限制而不得不使用。
数据库3 创建表温度 (col1 NUMBER);
create or replace procedure testp(i number)
as
BEGIN
INSERT INTO temp VALUES (i);
END;
/
数据库2
CREATE OR REPLACE FUNCTION DLR_TRANS.testf(i number)
return number
as
e exception;
BEGIN
testp@TO_DB3(i);
RAISE e;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RETURN 0;
END;
/
数据库1
declare
x number;
BEGIN
x := testf@TO_DB2(15);
DBMS_OUTPUT.PUT_LINE ( 'x = ' || x );
commit;
END;
由于DB2函数异常,x返回0。
下面是我在DB3上运行以下语句时的数据
select * from temp;
希望这会有所帮助
答案 1 :(得分:0)
问题在于您已“处理” [功能2]中的异常。您完全不应将异常块放在[功能2]中。并让异常传播到[过程1]。在这里,您将隐式或显式回滚。
如果在[功能2]中必须有一个异常块,那么末尾应该有[筹集]。处理这样的异常是说[我已处理,并且出于所有实际目的,调用方不应认为已发生任何不良情况