À partir da versao 10g do banco de dados, a Oracle disponibilizou um novo pacote para criação de jobs/schedulers o DBMS_SCHEDULER. Esse pacote não vem para substituir a antiga DBMS_JOB, mas sim para ampliar sua funcionalidade.
Nesse post vou falar um pouco sobre as principais funcionalidades desse novo pacote.
DIFERENÇA EM RELAÇÃO À DBMS_JOB
A principal diferença em relação à DBMS_JOB, é que agora é possível ter uma estrutura mais modular, onde é possível ter o programa/tarefa/rotina que será executada separada do tempo de execução(periodicidade). Assim, temos agora 3 novos termos, programa, schedule e job.
PROGRAMA
Um programa é a tarefa que será executada, seja ela um bloco anônimo, uma Stored Procedure ou um executável do sistema operacional. Ao criar um programa, não se define quando o mesmo será executado, apenas faz-se o registro do quê será executado.
Exemplo:
-- Criando um programa de teste
BEGIN
-- Bloco PL/SQL .
DBMS_SCHEDULER.create_program (
program_name => 'test_plsql_block_prog',
program_type => 'PLSQL_BLOCK',
program_action => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
enabled => TRUE,
comments => 'Programa para coletar as estatísticas do usuário SCOTT''s usando um bloco PL/SQL.');
-- Shell Script.
DBMS_SCHEDULER.create_program (
program_name => 'test_executable_prog',
program_type => 'EXECUTABLE',
program_action => '/u01/app/oracle/dba/gather_scott_stats.sh',
number_of_arguments => 0,
enabled => TRUE,
comments => 'Programa para coletar as estatísticas do usuário SCOTT''s usando shell script.');
-- Stored Procedure com argumentos.
DBMS_SCHEDULER.create_program (
program_name => 'test_stored_procedure_prog',
program_type => 'STORED_PROCEDURE',
program_action => 'DBMS_STATS.gather_schema_stats',
number_of_arguments => 1,
enabled => FALSE,
comments => 'Programa para coletar as estatísticas do usuário SCOTT''s usando uma stored procedure.');
-- Definindo um argumento para a stored procedure criado anteriormente
DBMS_SCHEDULER.define_program_argument (
program_name => 'test_stored_procedure_prog',
argument_name => 'ownname',
argument_position => 1,
argument_type => 'VARCHAR2',
default_value => 'SCOTT');
-- habilitando o programa criado anteriormente
DBMS_SCHEDULER.enable (name => 'test_stored_procedure_prog');
END;
/
PL/SQL procedure successfully completed.
Podemos em seguida consultar os programas criados no bloco acima:
SELECT owner, program_name, enabled FROM dba_scheduler_programs; OWNER PROGRAM_NAME ENABL ------------------------------ ------------------------------ ----- SYS PURGE_LOG_PROG TRUE SYS GATHER_STATS_PROG TRUE SYS TEST_PLSQL_BLOCK_PROG TRUE SYS TEST_EXECUTABLE_PROG TRUE SYS TEST_STORED_PROCEDURE_PROG TRUE 5 rows selected.
Podemos verificar na 3ª coluna o status do programa criado, todos são criados como enabled por default. É possível desabilitá-los através da procedure DBMS_SCHEDULER.DISABLE.
Para eliminar um programa, basta executar a procedure abaixo:
DBMS_SCHEDULER.drop_program (program_name => 'test_plsql_block_prog');
SCHEDULE
Um schedule define um horário ou período para execução de um/vários programa(s). Essa é a grande sacada dessa nova estrutura de jobs da versão 10g, é possível associar um schedule a mais de programa, o que facilita a administração.
Para criar um schedule, usamos os exemplos abaixo:
-- Criando o schedule.
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'test_hourly_schedule',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly; byminute=0',
end_date => NULL,
comments => 'Repetir a cada hora, por tempo indeterminado.');
END;
/
PL/SQL procedure successfully completed.
Para consultarmos se um schedule foi realmente criado, utilizamos a query abaixo:
SELECT owner, schedule_name FROM dba_scheduler_schedules; OWNER SCHEDULE_NAME ------------------------------ ------------------------------ SYS DAILY_PURGE_SCHEDULE SYS TEST_HOURLY_SCHEDULE 2 rows selected.
Para eliminar um schedule, utilizamos o exemplo abaixo:
BEGIN DBMS_SCHEDULER.drop_schedule (schedule_name => 'TEST_HOURLY_SCHEDULE'); END; / PL/SQL procedure successfully completed.
JOB
A essas alturas você já deve estar se perguntado: "Pra tanto trabalho pra se criar um job, sendo que até hoje eu criei tudo com uma única linha de comando?". Calma, existe também a possibilidade de criar tudo em um único passo, tudo como era antigamente, a diferença é que agora quando for utilizado a built-in DBMS_SCHEDULER, o job já vai ser criado modularizado, ou seja, tanto a rotina quando o período podem ser reaproveitados.
Vamos ver um pouco mais sobre a variação de formas de se criar um job:
BEGIN
-- Job criado totalmente através da procedure CREATE JOB.
DBMS_SCHEDULER.create_job (
job_name => 'test_full_job_definition',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly; byminute=0',
end_date => NULL,
enabled => TRUE,
comments => 'Job criado totalmente através da procedure CREATE JOB.');
-- Job criado usando um programa e schedule existentes.
DBMS_SCHEDULER.create_job (
job_name => 'test_prog_sched_job_definition',
program_name => 'test_plsql_block_prog',
schedule_name => 'test_hourly_schedule',
enabled => TRUE,
comments => 'Job criado usando um programa e schedule existentes.');
-- Job criado por um programa existente e um schedule inline(não existente).
DBMS_SCHEDULER.create_job (
job_name => 'test_prog_job_definition',
program_name => 'test_plsql_block_prog',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly; byminute=0',
end_date => NULL,
enabled => TRUE,
comments => 'Job criado por um programa existente e um schedule inline(não existente).');
-- Job criado por um programa e um schedule inline(não existentes).
DBMS_SCHEDULER.create_job (
job_name => 'test_sched_job_definition',
schedule_name => 'test_hourly_schedule',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
enabled => TRUE,
comments => 'Job criado por um programa e um schedule inline(não existentes).');
END;
/
PL/SQL procedure successfully completed.
Para confirmar se os jobs foram criados, usamos a query abaixo:
SELECT owner, job_name, enabled FROM dba_scheduler_jobs; OWNER JOB_NAME ENABL ------------------------------ ------------------------------ ----- SYS PURGE_LOG TRUE SYS GATHER_STATS_JOB TRUE SYS TEST_FULL_JOB_DEFINITION TRUE SYS TEST_PROG_SCHED_JOB_DEFINITION TRUE SYS TEST_PROG_JOB_DEFINITION TRUE SYS TEST_SCHED_JOB_DEFINITION TRUE 6 rows selected.
Ou seja, através dos exemplos acima, vemos que é possível criar os jobs com programas e schedules existentes ou não. Complementando a resposta à questão do início do tópico, eu adiciono uma outra pergunta: "Você pretende reutilizar o período ou a rotina que será executada?" se a sua resposta foi não, continue utilizando a boa e velha DBMS_JOB, se foi sim....
Para excluir um job, utilizamos o bloco abaixo:
BEGIN
DBMS_SCHEDULER.drop_job (job_name => 'test_full_job_definition');
END;
CONTROLE DE EXECUÇÃO DE JOBS
Um job tem sua execução de forma assíncrona, ou seja, é o próprio banco quem controla sua execução de acordo com os atributos definidos na criação do mesmo. Porém, é possível ter um controle manual, como abaixo:
BEGIN
-- Forçando a execução de um job
DBMS_SCHEDULER.run_job (job_name => 'test_full_job_definition',
use_current_session => FALSE);
-- Parando a execução de um job
DBMS_SCHEDULER.stop_job (job_name => 'test_full_job_definition, test_prog_sched_job_definition');
END;
/
PRIVILÉGIOS
Nessa versão de banco, uma nova rule foi criado para controlar o Scheduler, o SCHEDULER_ADMIN. Esse grant inicialmente só é concedido ao DBA e permite ao mesmo qualquer ação sobre um Job criado por ele ou por qualquer outro usuário. Esse grant é poderoso, portanto deve-se ter muito cuidado ao concedê-lo aos usuários. Porém, existe também a rule
MANAGE SCHEDULER, que permite ao usuário consultar atributos de um Job ou alterá-los através das procedures GET_SCHEDULER_ATTRIBUTE e SET_SCHEDULER_ATTRIBUTE respectivamente.Artigos relacionados:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sched.htm
http://www.oracle-base.com/articles/10g/Scheduler10g.php
That´s all Folks

Didático, prático e claro.
ResponderExcluirObrigado