Результат функции SYS_CONTEXT с параметром BG_JOB_ID отличается от предыущих версий

В выпусках Oracle БД до 19c функция SYS_CONTEXT('USERENV','BG_JOB_ID') возвращала идентификатор задания (колонка user_jobs.job), если она выполнялась в фоновом процессе. Что соответствовало документации:

BG_JOB_ID
Job ID of the current session if it was established by an Oracle Database background process. Null if the session was not established by a background process.

Начиная с выпуска 19c, эта же функция возврашает совершенно непонятное число, к которому нет никакого соответствия в колонке user_jobs.job.

create table joblog (jobid int, memo varchar2 (256));
var jobid number;
begin
    dbms_job.submit (:jobid, q'[
        begin 
            insert into joblog values (sys_context ('USERENV','BG_JOB_ID'), 'running'); 
        end;]');
end;
/
select job from user_jobs where job=:jobid;

       JOB
----------
        34

commit;

select * from joblog;

     JOBID MEMO
---------- ----------------
     73517 running

Это баг или новые функциональные возможности? Как теперь связать выполнение задачи в фоновом процессе с идентификатором задачи полученом при её запуске?

Пробовал связать через представления v$Scheduler_Running_Jobs и dba_jobs_running. Так можно, но не уверен, что правильно.


Ответы (1 шт):

Автор решения: 0xdb

В документаци о поддержке API DBMS_JOB к выпуску 19c по сравнению с 18c добавленно:

Oracle continues to support the DBMS_JOB package. However, you must grant the CREATE JOB privilege to the database schemas that submit DBMS_JOB jobs.

То есть, потребуется дополнительная привилегия, которая до 19c была не нужна. Зачем?

18c> var jobid number;
exec dbms_job.submit (:jobid, 'begin null; end;')

18c> select job, what from user_jobs;

       JOB WHAT
---------- --------------------------------
        41 begin null; end;

18c> select job_name, job_action from user_scheduler_jobs;

no rows selected

То же самое в 19c даст:

19c> select job, what from user_jobs;

       JOB WHAT
---------- --------------------------------
        44 begin null; end;

19c> select job_name, job_action from user_scheduler_jobs;

JOB_NAME         JOB_ACTION
---------------- --------------------------------
DBMS_JOB$_44     begin null; end;

Видно, что начиная с выпуска 19c задания созданые со старым API DBMS_JOB будут неявно конвертированы в задания нового API DBMS_SCHEDULER, для которых собственно и необходима привилегия CREATE JOB.


Функция sys_context ('USERENV','BG_JOB_ID') теперь возвращает внутренний идентификатор для заданий (колонка v$scheduler_running_jobs.job_id), который больше не коррелирует с колонкой user_jobs.job статрого API и на момент создания задания неизвестен.

Пока баг не будет устранён, пока такое решение:

create or replace function getBgJobId return number is
begin
    for r in (
        select job_name, regexp_substr (job_name, '\d+$') jobid   
        from user_scheduler_running_jobs
        where session_id = sys_context ( 'userEnv', 'SID')
        and running_instance = sys_context ( 'userEnv', 'Instance')
        ) loop return r.jobid; end loop;
    return null;    
end getBgJobId;
/
exec dbms_job.submit (:jobid, q'[begin dbms_output.put_line ('getBgJobId()='||getBgJobId); end;]') 
commit;

select job_name, output 
from  user_scheduler_job_run_details 
where job_name = 'DBMS_JOB$_'||:jobid;

JOB_NAME         OUTPUT                          
---------------- --------------------------------
DBMS_JOB$_51     getBgJobId()=51                 
→ Ссылка