Lost in time

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;

Calendaring Syntax;

Setting Scheduler Preferences;

DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained (Doc ID 467722.1).

Publicar comentário