SQL> select * from user_source where lower(text) like '%commit%';
NAME TYPE LINE TEXT
---------------- ------------ ---------- ----------------------------------------
PKG_GENERAL PACKAGE BODY 297 -- transaction ended without commit or rollback
PKG_GENERAL PACKAGE BODY 320 COMMIT;
PKG_LOG PACKAGE BODY 45 COMMIT;
PKG_LOG PACKAGE BODY 134 COMMIT;
PKG_MAIL PACKAGE BODY 219 COMMIT;
create table cannot_have_rows
(
a number,
constraint cannot_have_rows_ck check(a is null and a is not null) deferrable initially deferred
);
comment on table cannot_have_rows is 'This table exists only to prevent unwanted commits.';
下面是一个如何使用表CANNOT_HAVE_ROWS禁用和启用提交的示例。
declare
procedure disable_commits is
begin
insert into cannot_have_rows values(1);
end disable_commits;
procedure enable_commits is
begin
delete from cannot_have_rows;
end enable_commits;
procedure prevent_commits_in_this_code is
begin
-- Most transaction control statements still work.
savepoint savepoint1;
insert into test1 values(1);
rollback to savepoint1;
--This line will raise an exception.
commit;
end;
begin
disable_commits;
prevent_commits_in_this_code;
enable_commits;
exception when others then
--You probably always want to re-enable commits at the end, even if there's an error.
enable_commits;
raise;
end;
/
上面的匿名块将生成此错误:
ORA-02091: transaction rolled back
ORA-06512: at line 29
ORA-02290: check constraint (JHELLER.CANNOT_HAVE_ROWS_CK) violated
ORA-06512: at line 20
ORA-06512: at line 24
2条答案
按热度按时间bjp0bcyl1#
什么叫“非法犯罪”?
也许你想查询
user_source
,看看代码的哪些部分包含对commit
的引用,检查它们并做一些事情:就像这样:
sqyvllje2#
您可以使用可推迟约束来阻止提交。在运行目标过程之前,创建一个违反可推迟约束的行,在过程完成之后,删除该行以再次启用提交。如果在过程中有任何提交,则可推迟约束将失败,事务将回滚,并且Oracle将引发一个异常,该异常指向导致提交的代码行。
首先,创建一个具有可推迟约束的表,该约束很容易被违反:
下面是一个如何使用表CANNOT_HAVE_ROWS禁用和启用提交的示例。
上面的匿名块将生成此错误:
上面的代码不是一个很好的解决方案,但是在许多代码库中,几乎不可能保证不发生某些事情。当你考虑到CURRENT_SCHEMA、SYNONYMS、重写对象名(例如,想象一下创建一个名为DBMS_OUTPUT的自定义包)、动态SQL、间接运行代码(如触发器、作业、调度器作业、高级重写指令和其他计划控制功能)等时,Oracle代码路径可能非常难以理解。我曾经花了整整一周的时间来检查代码,以100%确定没有不必要的提交。对于与停机问题等价的问题,并不总是有一个简单的解决方案。