Nos últimos tempos tenho trabalhado com jobs em base de dados Oracle.
Mesmo que a base de dados utilizada fosse a 10g é ainda utilizado o DBMS_JOB
. Recentemente li o [1] e descobri o DBMS_SCHEDULER
.
Dou dois
exemplos de dificuldades que senti com o DBMS_JOB
:
- definir o intervalo de execução: fraca legibilidade, demasiado código para conseguir o agendamento desejado;
- configurar o deploy de um job: apenas um campo númérico identifica univocamente o job na lista.
Neste post vou falar sobre o segundo ponto: o deploy de um job.
Oracle 9i: o DBMS_JOB
Na versão 9i a gestão de jobs é feita com o package DBMS_JOB
.
Eis o script de deploy mais simples:
DECLARE
V_JOB NUMBER;
BEGIN
DBMS_JOB.SUBMIT(
JOB => V_JOB,
WHAT => 'BEGIN MY_PKG.MY_EXEC_PROC; END;',
NEXT_DATE => SYSDATE);
commit;
dbms_output.put_line('Created MY_PKG.MY_EXEC_PROC job: '||v_job);
END;
/
Este script tem o seguinte problema: se executarmos o script outra vez o resultado vai ser a criação de outro job igual ao primeiro. Este foi alias a situação com que me deparei de início: a base de dados tinha dezenas de jobs a realizar a mesma tarefa!
Posto o problema de apenas o campo job
(do tipo número) identificar univocamente o job, utilizei o campo what
para o identificar. Criei o seguinte script de deploy:
DECLARE
V_JOB NUMBER;
V_WHAT VARCHAR2(100) := 'BEGIN MY_PKG.MY_EXEC_PROC; END;';
V_NEXT_DATE DATE := SYSDATE;
BEGIN
dbms_output.put_line('Deleting all MY_PKG.MY_EXEC_PROC jobs:');
FOR jobs_to_delete IN (
SELECT job
FROM user_jobs
WHERE what like V_WHAT
) LOOP
dbms_output.put_line('...removing MY_PKG.MY_EXEC_PROC job ' || jobs_to_delete.job);
dbms_job.remove(jobs_to_delete.job);
END LOOP;
dbms_output.put_line('Deleted all MY_PKG.MY_EXEC_PROC jobs.');
commit;
DBMS_JOB.SUBMIT(V_JOB, V_WHAT, V_NEXT_DATE);
commit;
dbms_output.put_line('Created MY_PKG.MY_EXEC_PROC job: '||v_job);
END;
/
Reparar no loop para resolver o caso de fazerem deploy do mesmo job.
Este script não resolve outro problema: se numa fase de desenvolvimento alterarmos o what
do job não iremos remover os jobs antigos – claro que esta situação tem pouco impacto com algum controlo regular sobre o que existe na base de dados.
Este script poderia ser isolado num procedimento com a assinatura
DEPLOY_JOB(
job OUT BINARY_INTEGER,
what IN VARCHAR2,
next_date IN DATE DEFAULT sysdate,
interval IN VARCHAR2 DEFAULT 'null',
job_name IN VARCHAR2); -- 'job_name' serve apenas para dbms_output
que não é mais do que estender as funcionalidades do DBMS_JOB.SUBMIT
.
Oracle 10g: o DBMS_SCHEDULER
Mas eis que a 10g apresenta uma solução muito mais completa: o package DBMS_SCHEDULER
.
Eis o novo script de deploy proposto
DECLARE
V_JOB_NAME VARCHAR2(100) := 'MY_PKG_MY_EXEC_PROC';
BEGIN
DBMS_SCHEDULER.DROP_JOB(
job_name => V_JOB_NAME );
DBMS_SCHEDULER.CREATE_JOB(
job_name => V_JOB_NAME,
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN MY_PKG.MY_EXEC_PROC; END;');
start_date => SYSDATE );
END;
/
job_name
This attribute specifies the name of the job and uniquely identifies the job.
The name has to be unique in the SQL namespace. For example, a job cannot have the same name as a table in a schema.
If job_name is not specified, an error is generated. If you want to have a name generated by the Scheduler, you can use the GENERATE_JOB_NAME procedure to generate a name and then use the output in the CREATE_JOB procedure. The GENERATE_JOB_NAME procedure call generates a number from a sequence, which is the job name. You can prefix the number with a string. The job name will then be the string with the number from the sequence appended to it.
Além do job ter um identificador descritivo, não é apenas único na lista de jobs mas também em todo o schema.
E com o DBMS_SCHEDULER.GENERATE_JOB_NAME
nem precisariamos de nos preocupar com o nome do job, similar ao DBMS_JOBS
.
E óptimo disponibilizar a geração de valores para job_name
com prefixo, muito útil em aplicações que geram internamente jobs e que teriam de implementar esta geração do nome.
Nota importante: ao contrário do DBMS_JOB.SUBMIT
, o DBMS_SCHEDULER.CREATE_JOB
faz commit, tentando ser similar a um statement DDL.
Leituras