Результат функции 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 шт):
В документаци о поддержке 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