【问题标题】:Find the job ID of the currently running job / allow only a single job to update a table查找当前正在运行的作业的作业 ID/只允许单个作业更新表
【发布时间】:2013-11-16 04:24:09
【问题描述】:

我有一个“明星”数据库。一是做一些工作;另外两个的作业将元数据从第一个数据库中提取到他们的参考表中。我想阻止任何人更新、删除或插入两个“奴隶”中参考表上的任何记录;这些表应该只由计划的作业更新。

我目前正在使用一个触发器来执行此操作,该触发器检查当前 SID 是否在 USER_SCHEDULER_RUNNING_JOBS 中以及我希望运行的作业名称。我想将其更改为使用我正在运行的作业的 JOB_ID。

这是我目前的设置;假设一个非常简单的表格:

create table a ( b number );

还有以下工作:

begin
   dbms_scheduler.create_job(
          job_name        => 'test_job'
        , job_type        => 'PLSQL_BLOCK'
        , job_action      => 'begin
                                 merge into a a 
                                 using ( select 1 x from dual@db2 ) b 
                                    on (1 = 2)
                                  when not matched then 
                                       insert values (b.x);
                                 commit;
                              end;'
        , start_date      => sysdate
        , repeat_interval => 'FREQ = MINUTELY;'
        , enabled => true
          );
end;
/

我正在使用这个触发器:

create or replace trigger tr_blah
before insert or update on a
declare
   l_ct number;
begin
   select count(*) into l_ct
     from user_scheduler_running_jobs
    where session_id = sys_context('USERENV','SID')
      and job_name = 'TEST_JOB'
          ;

   if l_ct = 0 then
      raise_application_error(-20000, 'FAIL');
   end if;
end;
/

这很不雅;但是,更糟糕的是,我必须为每个数据库中的每个表创建一个单独的触发器,并且每次都更改作业名称。无法动态创建触发器;这会让人厌烦,而且有很大的错误空间。

SYS_CONTEXT() 具有参数FG_JOB_IDBG_JOB_ID。它们的描述,尤其是FG_JOB_ID 的描述暗示它们可能是当前正在运行的作业的 JOB_ID。将触发器更改为以下(我都尝试过):

create or replace trigger tr_a
before insert or update or delete on a
declare
   l_ct number;
begin
      raise_application_error(-20000, sys_context('USER_ENV', 'BG_JOB_ID'));
end;
/

结果如下

ORA-20000: 
ORA-06512: at "REF.TR_A", line 4
ORA-04088: error during execution of trigger 'REF.TR_A'
ORA-06512: at line 2

这意味着FG_JOB_IDBG_JOB_ID 都为空。有没有一种方法可以确定当前会话中运行的作业的 ID,这样我就不需要每次都使用 JOB_NAME 了?

【问题讨论】:

    标签: oracle triggers oracle11g dbms-scheduler


    【解决方案1】:

    最优雅的解决方案是使用不同的数据库用户。确保作业在对表具有更新、插入和删除授权的用户下运行(可能是表的架构所有者)。不要将这些授权授予其他用户。

    无需搞乱触发器等。

    【讨论】:

    • 那是一个更优雅的解决方案;虽然它并不能阻止事故......我试图禁止不混淆。 (我也对答案很感兴趣-是否可以找到工作ID)
    • 不同的用户有不同的密码和不同的访问权限。这绝不是一种混淆方式。
    猜你喜欢
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 2015-10-05
    相关资源
    最近更新 更多