oracle过程中非法提交的识别

6ljaweal  于 2023-05-16  发布在  Oracle
关注(0)|答案(2)|浏览(137)

我想知道,在我的Oracle PL/SQL代码中是否有非法提交,也许嵌套得很深。因此,我执行了“alter session disable commit in procedure”。如果发生这种情况,将引发错误。
但是..可能是代码中定义了保存点,并且可能会回滚到这些保存点。这是可以的,因为这不会创建不一致的数据。
不幸的是,Oracle似乎不允许任何事务控制语句时,“禁用提交过程”设置。
因此,我正在寻找一种方法来禁止代码中的提交,但允许有用的事务控制。

bjp0bcyl

bjp0bcyl1#

什么叫“非法犯罪”?
也许你想查询user_source,看看代码的哪些部分包含对commit的引用,检查它们并做一些事情:

  • 或者因为您确实需要它们(例如在自治事务处理过程中)而保留它们,或者
  • remove(comment?(因为你不需要他们

就像这样:

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;
sqyvllje

sqyvllje2#

您可以使用可推迟约束来阻止提交。在运行目标过程之前,创建一个违反可推迟约束的行,在过程完成之后,删除该行以再次启用提交。如果在过程中有任何提交,则可推迟约束将失败,事务将回滚,并且Oracle将引发一个异常,该异常指向导致提交的代码行。
首先,创建一个具有可推迟约束的表,该约束很容易被违反:

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

上面的代码不是一个很好的解决方案,但是在许多代码库中,几乎不可能保证不发生某些事情。当你考虑到CURRENT_SCHEMA、SYNONYMS、重写对象名(例如,想象一下创建一个名为DBMS_OUTPUT的自定义包)、动态SQL、间接运行代码(如触发器、作业、调度器作业、高级重写指令和其他计划控制功能)等时,Oracle代码路径可能非常难以理解。我曾经花了整整一周的时间来检查代码,以100%确定没有不必要的提交。对于与停机问题等价的问题,并不总是有一个简单的解决方案。

相关问题