Coleta de estatísticas fora da Maintenance Window
Recentemente, analisando o comportamento de alguns jobs de coleta de estatísticas, me deparei com uma situação interessante: a coleta de estatísticas estava sendo iniciada fora da janela de manutenção configurada no banco de dados. Neste post vou falar um pouco sobre as Maintenance Windows, as Auto Tasks e sobre o problema que causou esse comportamento. Vamos lá!
Sobre Maintenance Windows e Auto Tasks
Maintenance Windows, ou janelas de manutenção, são intervalos de tempo dentro dos quais tarefas automáticas de manutenção ocorrem no Oracle Database. Dados sobre as Maintenance Windows podem ser vistos na view DBA_SCHEDULER_WINDOWS:
SQL> set lines window SQL> col window_name for a20 SQL> col repeat_interval for a70 SQL> col duration for a20 SQL> SELECT window_name, repeat_interval, duration, enabled FROM DBA_SCHEDULER_WINDOWS; WINDOW_NAME REPEAT_INTERVAL DURATION ENABL -------------------- ---------------------------------------------------------------------- -------------------- ----- MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 TRUE SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 TRUE WEEKNIGHT_WINDOW freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0 +000 08:00:00 FALSE WEEKEND_WINDOW freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0 +002 00:00:00 FALSE 9 rows selected.
Na coluna REPEAT_INTERVAL acima, podemos verificar a repetição com que as janelas ocorrem, através da “Calendar Syntax” apresentada. Por exemplo, a janela TUESDAY_WINDOW tem frequência diária (freq-daily) mas só fica ativa nas terças feiras (byday=TUE) às 22:00 (byhour=22;byminute=0; bysecond=0). Ao final do post vou deixar a referência dessa sintaxe pra quem quiser se aprofundar.
Uma vez aberta a janela de manutenção, jobs do Oracle Scheduler criados pelo usuário, que foram configurados para rodar naquela janela, passam a ser executados. Além destes, o Oracle inicia os jobs das chamadas Automated Tasks (ou Auto Tasks, para os mais íntimos).
O Oracle possui diversas Auto Tasks default, como a coleta de estatísticas, e diversos advisors, como o SQL Tuning Advisor e o Automatic Segment Advisor. Para verificar quais estão habilitados no ambiente, podemos utilizar a view DBA_AUTOTASK_CLIENT:
SQL> SELECT client_name, status FROM DBA_AUTOTASK_CLIENT; CLIENT_NAME STATUS ---------------------------------------------------------------- -------- sql tuning advisor ENABLED auto optimizer stats collection ENABLED auto space advisor ENABLED
A relação entre as Auto Tasks e as Maintenance Windows nas quais rodam, pode ser encontrada na view DBA_AUTOTASK_WINDOW_CLIENTS:
SQL> SELECT window_name, optimizer_stats, segment_advisor, sql_tune_advisor FROM DBA_AUTOTASK_WINDOW_CLIENTS; WINDOW_NAME OPTIMIZE SEGMENT_ SQL_TUNE -------------------- -------- -------- -------- MONDAY_WINDOW ENABLED ENABLED ENABLED TUESDAY_WINDOW ENABLED ENABLED ENABLED WEDNESDAY_WINDOW ENABLED ENABLED ENABLED THURSDAY_WINDOW ENABLED ENABLED ENABLED FRIDAY_WINDOW ENABLED ENABLED ENABLED SATURDAY_WINDOW ENABLED ENABLED ENABLED SUNDAY_WINDOW ENABLED ENABLED ENABLED 7 rows selected.
Análise do job de coleta de estatísticas
Para a análise da coleta de estatísticas, podemos utilizar a view DBA_AUTOTASK_JOB_HISTORY:
SQL> alter session set NLS_TIMESTAMP_TZ_FORMAT='DD/MM/YYYY HH24:MI:SS TZH:TZM'; Session altered. SQL> SET LINES WINDOW SQL> COL CLIENT_NAME FOR A40 SQL> COL WINDOW_NAME FOR A25 SQL> COL WINDOW_START_TIME FOR A40 SQL> COL JOB_NAME FOR A25 SQL> COL JOB_START_TIME FOR A40 SQL> COL JOB_DURATION FOR A20 SQL> SELECT CLIENT_NAME, WINDOW_NAME, WINDOW_START_TIME, JOB_NAME, JOB_START_TIME, JOB_DURATION, JOB_STATUS FROM DBA_AUTOTASK_JOB_HISTORY WHERE JOB_START_TIME > SYSDATE - 8 AND CLIENT_NAME LIKE 'auto optimizer%' ORDER BY JOB_START_TIME DESC; CLIENT_NAME WINDOW_NAME WINDOW_START_TIME JOB_NAME JOB_START_TIME JOB_DURATION JOB_STATUS -------------------------------- ----------------- --------------------------- ------------------------- ---------------------------- -------------- ------------ auto optimizer stats collection MONDAY_WINDOW 08/04/2025 02:00:03 -03:00 ORA$AT_OS_OPT_SY_6923 07/04/2025 22:02:13 -07:00 +000 00:04:10 SUCCEEDED auto optimizer stats collection SUNDAY_WINDOW 06/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6921 06/04/2025 22:30:10 -07:00 +000 00:01:24 SUCCEEDED auto optimizer stats collection SUNDAY_WINDOW 06/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6919 06/04/2025 18:29:41 -07:00 +000 00:00:13 SUCCEEDED auto optimizer stats collection SUNDAY_WINDOW 06/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6917 06/04/2025 14:19:16 -07:00 +000 00:00:15 SUCCEEDED auto optimizer stats collection SUNDAY_WINDOW 06/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6915 06/04/2025 10:18:50 -07:00 +000 00:00:07 SUCCEEDED auto optimizer stats collection SUNDAY_WINDOW 06/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6912 06/04/2025 06:08:28 -07:00 +000 00:01:20 SUCCEEDED auto optimizer stats collection SATURDAY_WINDOW 05/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6910 05/04/2025 22:27:30 -07:00 +000 00:00:20 SUCCEEDED auto optimizer stats collection SATURDAY_WINDOW 05/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6908 05/04/2025 18:27:04 -07:00 +000 00:00:09 SUCCEEDED auto optimizer stats collection SATURDAY_WINDOW 05/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6906 05/04/2025 14:26:39 -07:00 +000 00:00:25 SUCCEEDED auto optimizer stats collection SATURDAY_WINDOW 05/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6904 05/04/2025 10:16:11 -07:00 +000 00:00:12 SUCCEEDED auto optimizer stats collection SATURDAY_WINDOW 05/04/2025 10:00:02 -03:00 ORA$AT_OS_OPT_SY_6901 05/04/2025 06:05:40 -07:00 +000 00:00:22 SUCCEEDED auto optimizer stats collection FRIDAY_WINDOW 05/04/2025 02:00:03 -03:00 ORA$AT_OS_OPT_SY_6898 04/04/2025 22:04:32 -07:00 +000 00:01:05 SUCCEEDED auto optimizer stats collection THURSDAY_WINDOW 04/04/2025 02:00:03 -03:00 ORA$AT_OS_OPT_SY_6895 03/04/2025 22:02:21 -07:00 +000 00:01:29 SUCCEEDED auto optimizer stats collection WEDNESDAY_WINDOW 03/04/2025 02:00:02 -03:00 ORA$AT_OS_OPT_SY_6892 02/04/2025 22:09:38 -07:00 +000 00:01:05 SUCCEEDED auto optimizer stats collection TUESDAY_WINDOW 02/04/2025 02:00:01 -03:00 ORA$AT_OS_OPT_SY_6889 01/04/2025 22:07:30 -07:00 +000 00:00:53 SUCCEEDED auto optimizer stats collection MONDAY_WINDOW 01/04/2025 02:00:02 -03:00 ORA$AT_OS_OPT_SY_6886 31/03/2025 22:05:36 -07:00 +000 00:00:57 SUCCEEDED 16 rows selected.
No retorno da consulta, dois pontos chamam a atenção: a WINDOW_START_TIME ocorre quatro horas após o horário verificado na view DBA_SCHEDULER_WINDOWS e o JOB_START_TIME mostra o início da janela usando uma timezone diferente (-07:00). Nesse caso conseguimos entender o porquê do nosso job estar rodando em um horário fora da janela de manutenção: ele está usando uma timezone diferente do horário local.
Para confirmar, podemos verificar a propriedade default_timezone do Oracle Scheduler:
SQL> SET SERVEROUTPUT ON SQL> DECLARE PROCEDURE display(p_param IN VARCHAR2) AS l_result VARCHAR2(50); BEGIN DBMS_SCHEDULER.get_scheduler_attribute( attribute => p_param, value => l_result); DBMS_OUTPUT.put_line(RPAD(p_param, 30, ' ') || ' : ' || l_result); END; BEGIN display('current_open_window'); display('default_timezone'); display('email_sender'); display('email_server'); display('event_expiry_time'); display('log_history'); display('max_job_slave_processes'); END; / current_open_window : default_timezone : PST8PDT email_sender : email_server : event_expiry_time : log_history : 30 max_job_slave_processes : PL/SQL procedure successfully completed.
E aí está o problema, a timezone default utilizada é a PST8PDT (equivalente a UTC/GMT -7). Alterando este ponto resolvemos o problema:
SQL> EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone','America/Sao_Paulo'); PL/SQL procedure successfully completed. SQL> DECLARE PROCEDURE display(p_param IN VARCHAR2) AS l_result VARCHAR2(50); BEGIN DBMS_SCHEDULER.get_scheduler_attribute( attribute => p_param, value => l_result); DBMS_OUTPUT.put_line(RPAD(p_param, 30, ' ') || ' : ' || l_result); END; BEGIN display('current_open_window'); display('default_timezone'); display('email_sender'); display('email_server'); display('event_expiry_time'); display('log_history'); display('max_job_slave_processes'); END; / current_open_window : default_timezone : America/Sao_Paulo email_sender : email_server : event_expiry_time : log_history : 30 max_job_slave_processes : PL/SQL procedure successfully completed.
Conclusão
Como a execução dos jobs das Auto Tasks é regida pelo timezone configurado no Oracle Scheduler, uma vez alterada a propriedade, as próximas execuções ocorrerão no horário correto. Vale citar que esses jobs não são influenciados pelo DBTIMEZONE ou SESSIONTIMEZONE. Para jobs criados pelo usuário, caso não seja especificada uma timezone no START_DATE do job, a propriedade default_timezone também será utilizada.
Dizer o porquê essa configuração estava usando essa timezone específica é difícil. Geralmente o timezone dessa propriedade tem o valor default da timezone do SO, que nesse caso era America/Sao_Paulo. Uma causa provável é que o SO tenha sido instalado em uma timezone diferente, e ela foi alterada somente após a instalação do banco de dados.
Algumas referências usadas para o artigo:
Managing Automated Database Maintenance Tasks;
Setting Scheduler Preferences;
DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained (Doc ID 467722.1).
Publicar comentário