terça-feira, 13 de setembro de 2016

VERIFICAR SNAPSHOTS EXISTENTES - AWR


Para verificar os snapshots existentes no banco de dados para o AWR, temos algumas opções, como descrito abaixo:

1) Listar os snapshts mais antigos e os mais novos

SQL> 

SELECT snap_id, begin_interval_time, end_interval_time
  FROM 
SYS.WRM$_SNAPSHOT 
  WHERE
 snap_id = ( SELECT MIN (snap_id) FROM SYS.WRM$_SNAPSHOT)

UNION 

SELECT snap_id, begin_interval_time, end_interval_time 
  FROM 
SYS.WRM$_SNAPSHOT 
  WHERE
 snap_id = ( SELECT MAX (snap_id) FROM SYS.WRM$_SNAPSHOT);


2) Listar todos os snapshts do AWR no banco de dados

SQL>

 SELECT snap_id, begin_interval_time, end_interval_time 
    FROM 
SYS.WRM$_SNAPSHOT order by 1;



3) Listar os snapshots com mais de 10 dias

SQL>

 SELECT snap_id, begin_interval_time, end_interval_time 
   FROM 
SYS.WRM$_SNAPSHOT
   WHERE
begin_interval_time<sysdate-10;

Gerar relatório AWR

Para gerar o relatório AWR, devemos conectar no banco de dados com um usuário privilegiado e executar um dos scripts AWR existente, como por exemplo:

awrrpt.sql - > gera relatório awr para uma instância de banco de dados 
awrgrpt.sql -> gera relatório awr para todas as instâncias de banco de dados de um cluster 

Os arquivos (scripts) para geração de relatórios AWR são armazenados por padrão da Oracle em: 

$ORACLE_HOME/rdbms/admin 

Os scripts (AWR) mais utilizados para verificação de performance são:

awrrpt.sql
awrgrpt.sql
awrinfo.sql
awrgrpti.sql
awrrpti.sql

Exemplos: 

Entar no banco de dados:

sqlplus / as sysdba 

Executar o AWR para instância única

SQL> @?/rdbms/admin/awrrpt.sql 

Executar o AWR para todas as instâncias de um RAC 

SQL> @?/rdbms/admin/awrgrpt.sql

BANCO DE DADOS NÃO GERA SNAPSHOTS PARA O AWR

Ao tentar gerar um AWR, percebemos que o o banco de dados não gerou os snapshots necessários para que o relatório AWR fosse executado.

Analisando o banco de dados, identificamos que o último snapshot foi gerado com uma data e hora bem anterior que a data atual e dessa forma não tem como gerar um AWR com dados atuais.

Pesquisando o que poderia estar ocorrendo, identificamos que o processo oracle MMON não estava ativo. 

Podemos fazer essa verificação através do comando: 

ps -ef | grep -i mmon 


Para que o AWR consiga gerar os snapshots para obtermos posteriormente os relatórios, esse processo (MMON) deve estar ativo, conforme demonstrado abaixo:

 ps -ef | grep -i mmon oracle 21102604 1 0 15:23:26 - 0:14 ora_mmon_DB 


Este problema ocorre devido ao Bug identificado pela Oracle "interim patch 19565533 for 11.2.0.4" 


A solução para esse problema é ativar o processo MMON no banco de dados e para isso, caso não seja possível aplicar o patch, temos 2 (duas) alternativas.

1) Parar e iniciar a base de dados 

     sqlplus / as sysdba

     shutdown immediate;
     startup;

2) Alterar o status do banco de dados como descrito abaixo:

   alter system enable restricted session; 
   alter system disable restricted session; 

Se for um ambiente RAC, devemos executar os comandos acima em todas as instâncias onde o MMON está desativado. 


Referências:

AWR Snapshots Are Not Being Created Because MMON Is Not Being Respawned (Doc ID 2023652.1)

Bug 18148383 - AWR snapshots stopped , MMON hung with "EMON to process ntnfs" (Doc ID 18148383.8)

ORA-27300: OS system dependent operation:fork failed with status: 12

Durante a coleta de estatística do dicionário de dados do banco de dados, foi apresentado o erro:

 ORA-27300: OS system dependent operation:fork failed with status: 12 

Verificando o arquivo alert.log do banco de dados, encontramos as seguintes informações:

Process startup failed, error stack: Errors in file 
/u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_psp0_20906206.trc:
ORA-27300: OS system dependent operation:fork failed with status: 12
ORA-27301: OS failure message: Not enough space 
ORA-27302: failure occurred at: skgpspawn3 Mon Sep 12 16:56:30 2016
Process J008 died, see its trace file kkjcre1p: unable to spawn jobq slave process 
Errors in file /u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_cjq0_17432706.trc:

Process startup failed, error stack: Errors in file
/u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_psp0_20906206.trc:
ORA-27300: OS system dependent operation:fork failed with status: 12 
ORA-27301: OS failure message: Not enough space 
ORA-27302: failure occurred at: skgpspawn3 Process J008 died, see its trace file kkjcre1p: unable to spawn jobq slave process 
Errors in file /u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_cjq0_17432706.trc:

Process startup failed, error stack: Errors in file 
/u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_psp0_20906206.trc: 
ORA-27300: OS system dependent operation:fork failed with status: 12
ORA-27301: OS failure message: Not enough space
ORA-27302: failure occurred at: skgpspawn3 
Process J008 died, see its trace file kkjcre1p: unable to spawn jobq slave process
Errors in file /u01/app/oracle/diag/rdbms/db_01/db_01/trace/db_01_cjq0_17432706.trc:
Mon Sep 12 16:56:40 2016 

Este erro pode ocorrer em diversos momentos, dependendo da atividade do banco de dados. 

Neste caso, o erro ocorreu durante a coleta de estatística do dicionário de dados do banco.

Causa: 

 Falta de espaço de swap no servidor. 

Solução

 Aumentar a área de swap do banco de dados. 

sexta-feira, 9 de setembro de 2016

AWR - Alterar tempo de execução e retenção dos snapshot do AWR

Dependendo do que é preciso investigar no ambiente, muitas vezes é necessário alterar o
tempo de execução dos snapshots do AWR, pois desta forma é possível obter informações em períodos de tempo mais adequado para a análise que está em execução. 

Devemos sempre levar em consideração que um período muito curto de coleta irá gerar uma quantidade grande de informações e dependendo do ambiente, será necessário ter um espaço disponível na tablespace SYSAUX para armazenar essas informações.

Abaixo seguem alguns exemplos de como alterar o tempo de geração de snapshots para o AWR: 

 a) Alterar o intervalo de geração de snapshot para 60 minutos

 SQL> execute dbms_workload_repository.modify_snapshot_settings(interval => 60);

- executa um snapshot a cada 60 minutos 

 b) Alterar o intervalo de geração de snapshot para 15 minutos 

SQL> execute dbms_workload_repository.modify_snapshot_settings(interval => 15);

 - executa um snapshot a cada 15 minutos 

c) Alterar o intervalo de geração de snapshot para 15 minutos e guarda o snapshot por 31 dias 

SQL> execute dbms_workload_repository.modify_snapshot_settings(interval =>15,retention =>44640);

 - executa um snapshot a cada 15 minutos e guarda por 31 dias 

AWR - Informações de execução e retenção

Para verificar as configurações de tempo e retenção dos snapshots do AWR, podemos 
utilizar os comandos abaixo, acessando a view dba_hist_wr_control :


select
       extract( day from snap_interval) *24*60+
       extract( hour from snap_interval) *60+
       extract( minute from snap_interval ) "Snapshot Interval",
       extract( day from retention) *24*60+
       extract( hour from retention) *60+
       extract( minute from retention ) "Retention Interval"
from dba_hist_wr_control;



Snapshot Interval Retention Interval
----------------- ------------------
               60              11520


Onde: 

Snapshot Interval é o tempo em minutos em que será gerado um snapshot para o AWR;
Retention Interval é o tempo em segundos em que o snapshot ficará guardado.



Ou ainda:

select * from dba_hist_wr_control;


      DBID SNAP_INTERVAL        RETENTION            TOPNSQL
---------- -------------------- -------------------- ----------
 883205600 +00000 01:00:00.0    +00008 00:00:00.0    DEFAULT


Onde:

 - RETENTION indica o número de dias de retenção dos dados;
 - SNAP_INTERVAL indica o intervalo de geração dos snapshots.


SYSAUX

A tablespace SYSAUX foi criada para auxiliar a tablespace SYSTEM, sendo criada automaticamente quando criamos um banco de dados. Alguns componentes de banco de dados que anteriormente eram criados e utilizavam a tablespace SYSTEM, agora ficam armazenados na tablespace SYSAUX. Essa mudança feita pela Oracle permitiu que se o espaço da tablespace SYSAUX ficar indisponível, ou atingir seu limite de utilização, o banco de dados permanecerá operacional, diferentemente do que ocorria quando tínhamos apenas a tablespace SYSTEM. Hoje, o que pode ocorrer caso a tablspace SYSAUX atinga seu limite de ocupação, é a falha ou o funcionamento limitado de alguns recursos que estejam armazenados na tablespace SYSAUX, mas não causando indisponibilidade do banco de dados. A tablespace SYSAUX é responsável também por armazenar informações do banco de dados, como por exemplo, os snapshots realizados para a coleta de informações dos relatórios do AWR. Uma retenção muito grande dos dados para esse tipo de relatório e uma grande quantidade de snapshots agendados por dia farão com que a tablespace SYSAUX tenha um tamanho muito grande. Podemos fazer a verificação da utilização da tablespace SYSAUX através dos comandos abaixo: 1) Verificar a utilização da SYSAUX por componente
select occupant_desc, space_usage_kbytes/1024/1024 as usage_GB from v$sysaux_occupants where space_usage_kbytes > 0 order by space_usage_kbytes desc;
OCCUPANT_DESC USAGE_GB -------------------------------------------------------------------------- ----------------- Server Manageability - Automatic Workload Repository 148223 Server Manageability - Other Components 3491,5625 Server Manageability - Advisor Framework 1674,0625 OLAP API History Tables 41,8750 Server Manageability - Optimizer Statistics History 335,1875 Enterprise Manager Repository 130,7500 Unified Job Scheduler 126,2500 Oracle Spatial 65,5625 XDB 57,5625 Analytical Workspace Object Table 41,8750 OLAP Catalog 15,6250 Oracle Text 6,3750 Transaction Layer - SCN to TIME mapping 15,3750 Oracle Multimedia ORDDATA Components 15,3125 LogMiner 10,2500 Enterprise Manager Monitoring User 9,6875 PL/SQL Identifier Collection 9,6250 Workspace Manager 7,3750 SQL Management Base Schema 7,0000 Expression Filter System 3,875 Logical Standby 1,375 Oracle Streams 1,0000 Oracle Multimedia ORDSYS Components 0,5625 Automated Maintenance Tasks 0,3125 Com a informação obtida acima, podemos perceber que o maior consumidor da SYSAUX são os snapshots do AWR, com 148GB de ocupação. 2) Verificar a utilização da SYSAUX por Item Outra forma de obtermos as informações da SYSAUX é: set linesize 120 set pagesize 100 COLUMN "Item" FORMAT A25 COLUMN "Space Used (GB)" FORMAT 999.99 COLUMN "Move Procedure" FORMAT A40 SELECT occupant_name "Item", EM_MONITORING_USER .01 DBSNMP space_usage_kbytes/1048576 "Space Used (GB)", schema_name "Schema", move_procedure "Move Procedure" FROM v$sysaux_occupants ORDER BY 1 / Item Space Used (GB) Schema Move Procedure ----------------------------------------------- -------------------------- ----------------- ----------------------------------- AO .04 SYS DBMS_AW.MOVE_AWMETA AUDIT_TABLES .00 SYS DBMS_AUDIT_MGMT.move_dbaudit_tables AUTO_TASK .00 SYS EM .13 SYSMAN emd_maintenance.move_em_tblspc PL/SCOPE .01 SYS EXPRESSION_FILTER .00 EXFSYS JOB_SCHEDULER .12 SYS LOGMNR .01 SYSTEM SYS.DBMS_LOGMNR_D.SET_TABLESPACE LOGSTDBY .00 SYSTEM SYS.DBMS_LOGSTDBY.SET_TABLESPACE ORDIM .00 ORDSYS ordsys.ord_admin.move_ordim_tblspc ORDIM/ORDDATA .01 ORDDATA ordsys.ord_admin.move_ordim_tblspc ORDIM/ORDPLUGINS .00 ORDPLUGINS ordsys.ord_admin.move_ordim_tblspc ORDIM/SI_INFORMTN_SCHEMA .00 SI_INFORMTN_SCHEMA ordsys.ord_admin.move_ordim_tblspc ULTRASEARCH_DEMO_USER .00 WK_TEST MOVE_WK SDO .06 MDSYS MDSYS.MOVE_SDO SM/ADVISOR 1.63 SYS SM/AWR 144.75 SYS SM/OPTSTAT .33 SYS SM/OTHER 3.41 SYS SMON_SCN_TIME .02 SYS SQL_MANAGEMENT_BASE .01 SYS STATSPACK .00 PERFSTAT STREAMS .00 SYS TEXT .01 CTXSYS DRI_MOVE_CTXSYS TSM .00 TSMSYS ULTRASEARCH .00 WKSYS MOVE_WK WM .01 WMSYS DBMS_WM.move_proc XDB .06 XDB XDB.DBMS_XDB.MOVEXDB_TABLESPACE XSAMD .02 OLAPSYS DBMS_AMD.Move_OLAP_Catalog XSOQHIST .04 SYS DBMS_XSOQ.OlapiMoveProc Para podermos diminuir a utilização da tablespace SYSAUX, precisaremos modificar o tempo de retenção das estatísticas do banco de dados. Abaixo, algumas opções que podemos utilizar para que consigamos fazer essa diminuição na tablespace SYSAUX. a) Obter o tempo de retenção das estatísticas no banco de dados SQL> select dbms_stats.get_stats_history_retention from dual; b) Alterar o tempo de retenção SQL> exec dbms_stats.alter_stats_history_retention(10); c) Fazer a limpeza das estatísticas armazenadas na SYSAUX SQL> exec DBMS_STATS.PURGE_STATS(SYSDATE-10); ** Aqui estamos limpando as estatísticas com mais de 10 dias. d) Verificar as estatísticas ativas que não podem ser removidas SQL> select dbms_stats.get_stats_history_availability from dual; Obs.: Podemos também alterar apenas o tempo de retenção e a quantidade de snapshots gerados por dia no banco de dados. Dessa forma a tablespace SYSAUX terá seu tamanho diminuído gradativamente, conforme o passar dos dias. Alteração de retenção do AWR
Referências: https://docs.oracle.com/cd/B28359_01/server.111/b28310/tspaces010.htm https://community.oracle.com/thread/2543974?tstart=0 https://jhdba.wordpress.com/2009/05/19/purging-statistics-from-the-sysaux-tablespace/ http://remidian.com/2009/08/purging-sysaux-tablespace-purging-awr-reports/

quinta-feira, 8 de setembro de 2016

ERRO: ORA-13541 >> system moving window baseline size ( ) greater than retention ( )

Este erro ocorre quando tentamos alterar a configuração de retenção dos relatórios AWR no banco de dados Oracle.

No exemplo abaixo, estamos alterando o tempo de retenção do relatório para 30 dias ou 43200 minutos.

SQL> execute dbms_workload_repository.modify_snapshot_settings (interval => 60, retention => 43200);

BEGIN dbms_workload_repository.modify_snapshot_settings (interval => 60, retention => 43200); END;

*
ERROR at line 1:
ORA-13541: system moving window baseline size (7862400) greater than retention
(2592000)
ORA-06512: at "SYS.DBMS_WORKLOAD_REPOSITORY", line 174
ORA-06512: at "SYS.DBMS_WORKLOAD_REPOSITORY", line 222
ORA-06512: at line 1


O erro acima acontece, devido a janela de retenção atual dos relatórios AWR estar configurarada para um período maior do que aquele que estamos tentando configurar.

Podemos obter essa informação com o SQL abaixo, que nos mostrará o tempo configurado para a janela de retenção:

SQL> SELECT moving_window_size FROM dba_hist_baseline WHERE  baseline_type = 'MOVING_WINDOW';

MOVING_WINDOW_SIZE
------------------
                91



Para podermos fazer a alteração que desejamos, precisamos alterar o tempo da janela de retenção antes de executarmos o comando bbms_workload_repository.modify_snapshot_settings, deixando essa janela com o mesmo tempo que iremos configurar, conforme descrito abaixo:

Para mudarmos a janela de retenção, devemos executar:

SQL> exec DBMS_WORKLOAD_REPOSITORY.modify_baseline_window_size( window_size =>30);

Neste caso, o window_size é igual a 30 dias que corresponde aos 43200 minutos que iremos configurar em nossa retenção.

1 hora = 60 minutos
1 dia = 24 horas
1 dia = 1440 minutos (60minX24h)
30 dias = 43200 minutos (1440min * 30dias)



Após a execução do comando de alteração da janela de retenção, podemos verificar se o valor foi realmente alterado:

SQL> SELECT moving_window_size FROM dba_hist_baseline WHERE  baseline_type = 'MOVING_WINDOW';

MOVING_WINDOW_SIZE
------------------
                30


Agora, que já temos a janela de retenção configurada de forma adequada para a nossa necessidade, podemos fazer a alteração na geração / retenção dos relatórios AWR.

SQL> execute dbms_workload_repository.modify_snapshot_settings (interval => 60, retention => 43200);

PL/SQL procedure successfully completed.



terça-feira, 6 de setembro de 2016

PLANO DE EXECUÇÃO DE SQL (QUERY) NO BANCO DE DADOS ORACLE

O plano de execução de uma query informa o tempo de execução e o "caminho" que a execução está tomando durante o processamento.

Esse plano, gerado através de comandos que iremos descrever abaixo, nos auxilia na análise de execução de um SQL, onde através da informação obtida, podemos tomar decisões de alteração da query na tentativa de melhorar o seu desempenho.



O plano de execução, é um auxiliar na análise do desempenho de um SQL e através dele podemos dar início na melhoria de uma query.

Outras ferramentas podem ser utilizadas em conjunto, além do conhecimento da aplicação e do produto que será entregue.

Podemos gerar o plano de execução de um SQL no banco de dados Oracle de algumas formas diferentes, além da forma gráfica gerada pelo OEM.

Abaixo seguem algumas formas de obtermos um plano de execução:


1) Com o set autotrace traceonly explain
Para isso, devemos nos conectar no banco de dados Oracle e:

a) Ativar o trace:

SQL> set autotrace traceonly explain

b) Em seguida, devemos "colar" ou digitar o comando SQL que queremos ter o plano de execução. 

Ex.:

SQL> set autotrace traceonly explain 
 SELECT * FROM DBA_TABLES;


2) Com o explain plan for

Para isso, devemos nos conectar ao banco de dados Oracle e:

a) Ativar a geração do plano 

SQL>explain plan for

b) Em seguida, devemos "colar" ou digitar o comando SQL que queremos ter o plano de execução

 Ex.:

SQL> explain plan for
 SELECT * FROM DBA_TABLES;


c) Em seguida executar o comando abaixo:

SQL> @?/rdbms/admin/utlxpls 


3) Gerar plano de execução através de um SQL_ID


Para isso, devemos nos conectar ao banco de dados Oracle e precisamos identificar o SQL_ID do SQL que queremos obter o plano de execução.

Para obtermos o SQL_ID desejado, podemos consultar a V$SESSION no caso do SQL estar em execução ou ainda a V$SQL, V$SQLAREA para tentarmos obter o SQL_ID de uma execução passada.


Com o SQL_ID em mãos podemos obter o plano de execução da seguinte forma: 

set lines 300
set pages 49000 
set long 2000000000

SELECT * FROM TABLE(dbms_xplan.display_awr('a93d1njnfsyvn')); 


4) - Gerar plano de execução de SQLs com variáveis BIND 

Para SQL com variável BIND, devemos ter em mãos o SQL que queremos obter o plano de execução, e:

a) Ativar o trace:

SQL> explain plan FOR


b) Em seguida, devemos "colar" ou digitar o comando SQL que queremos ter o plano de execução.

 Ex.:
SQL> explain plan FOR
 SELECT * FROM DBA_TABLES;


c) Em seguida executar o comando abaixo:

SQL> select plan_table_output from table(dbms_xplan.display('plan_table',null,'ALL'));

REDO LOG FILES

A estrutura mais crucial para as operações de recuperação de um banco de dados, é o log de redo, que consiste em dois ou mais arquivos pré-alocados, que armazenam todas as alterações feitas ao banco de dados à medida que ocorrem. 

Cada instância de um banco de dados Oracle tem um log redo associado para proteger o banco de dados em caso de uma falha da instância.

1) Localização dos arquivos de redo

Para identificarmos onde os arquivos de redo log do banco de dados são gravados, podemos utilizar o comando abaixo:

set lines 200
col member format a45

SELECT * FROM V$LOGFILE;


    GROUP#   STATUS   TYPE                MEMBER                                  IS_

         1                          ONLINE   +DG_REDO_01/redo_file_0101.log    NO
         1                          ONLINE   +DG_REDO_02/redo_file_0102.log    NO
         2                          ONLINE   +DG_REDO_01/redo_file_0201.log    NO
         2                          ONLINE   +DG_REDO_02/redo_file_0202.log    NO
         3                          ONLINE   +DG_REDO_01/redo_file_0301.log    NO
         3                          ONLINE   +DG_REDO_02/redo_file_0302.log    NO


2) Verificar o status do redo log file: 

Podemos verificar o status de utilização dos arquivos de redo. Para isso, podemos utilizar o SQL abaixo:


set lines 200
SELECT * FROM V$LOG;

GROUP#  THREAD#  SEQUENCE#  BYTES  BLOCKSIZE  MEMBERS ARC   STATUS    FIRST_CHANGE# FIRST_TIME  NEXT_CHANGE# NEXT_TIME

    1      1     1395775    1,0486E+10   512     2     NO   CURRENT  9,0767E+11 01/07/2016 11:41:51   2,8147E+14
    2      1     1395773    1,0486E+10   512     2     YES  INACTIVE  9,0767E+11 01/07/2016 11:09:07  9,0767E+11 01/07/2016 11:30:23
    3      1     1395774    1,0486E+10   512     2     YES  INACTIVE  9,0767E+11 01/07/2016 11:30:23  9,0767E+11 01/07/2016 11:41:51


3) Forçar a troca do redo log files:

Em alguns casos, podemos ter a necessidade de fazer com que o grupo de redo que está sendo utilizado no momento seja alterado. Isso geralmente ocorre quando criamos novos grupos de redo e queremos verificar se eles estão funcionando corretamente.

Para fazermos essa alteração, devemos utilizar o comando abaixo:

ALTER SYSTEM SWITCH LOGFILE;


Após a execução do SWITCH LOGFILE, podemos executar novamente o comando SELECT * FROM V$LOG; e veremos que o grupo de redo CURRENT, foi alterado em relação ao obtido anteriormente como o mesmo comando.



4) Adicionar grupos de redo log


Em muitos casos, pode existir a necessidade de adicionarmos grupos de redo log em nosso ambiente e para isso, podemos seguir o exemplo abaixo, onde segue um exemplo de inclusão de grupos de redo.

Para um ambiente single:

alter database add logfile thread 1 group 1 ('+DG_01/redo_0101.log','+DG_02/redo_0102.log') size 90M;


alter database add logfile thread 1 group 2 ('+DG_01/redo_0201.log','+DG_02/redo_0202.log') size 90M;


alter database add logfile thread 1 group 3 ('+DG_01/redo_0301.log','+DG_02/redo_0302.log') size 90M;



Para um ambiente cluster (RAC) com 2 nodes:

alter database add logfile thread 1 group 1 ('+DG_01/redo_0101.log','+DG_02/redo_0102.log') size 100M;

alter database add logfile thread 1 group 2 ('+DG_01/redo_0201.log','+DG_02/redo_0202.log') size 100M;

alter database add logfile thread 1 group 3 ('+DG_01/redo_0301.log','+DG_02/redo_0302.log') size 100M;


alter database add logfile thread 2 group 4 ('+DG_01/redo_0401.log','+DG_02/redo_0402.log') size 100M;


alter database add logfile thread 2 group 5 ('+DG_01/redo_0501.log','+DG_02/redo_0502.log') size 100M;


alter database add logfile thread 2 group 6 ('+DG_01/redo_0601.log','+DG_02/redo_0602.log') size 100M;



Onde:

- thread corresponde ao node do cluster que utilizará os arquivos de redo log criados;
- group é o grupo de redo criado, onde devemos ter 2 datafiles para cada grupo, como prevenção contra corrupção;

O valor padrão do Oracle para cada grupo de redo é de 50M, mas dependendo do ambiente esse valor pode ser aumentado, mas devemos tomar cuidado, pois os arquivos de redo não devem ser muito grandes, pois em caso de falha, a quantidade de registros em redo que podem ser perdidos será grande e não teremos como recuperá-los.


5) Excluir grupo de redo log files:

Para excluirmos um grupo de redo, podemos utilizar o comando abaixo:

ALTER DATABASE DROP LOGFILE GROUP  1;
ALTER DATABASE DROP LOGFILE GROUP  2;
ALTER DATABASE DROP LOGFILE GROUP  3;


Algumas informações importantes sobre a exclusão de grupos de redo:

1 - Quando excluímos um grupo de redo, os datafiles correspondentes não são excluídos do banco de dados, será necessário excluí-los manualmente;
2 - Só podemos excluir grupos de redo que não estejam em utilização, devem estar com o status INACTIVE.
3 - Muito cuidado para não remover datafiles de grupos de redo ativos, pois poderemos corromper arquivos necessários para o banco de dados.


Para verificar os grupos de redo ativos, devemos executar o comando abaixo:


set lines 200
SELECT * FROM V$LOG;

GROUP# THREAD# SEQUENCE# BYTES BLOCK MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIME NEXT_CHANGE# NEXT_TIME
   1     1  1395775 1,0486E+10    512       2 NO  CURRENT          9,0767E+11 01/07/2016 11:41:51   2,8147E+14
   2     1  1395773 1,0486E+10    512       2 YES INACTIVE         9,0767E+11 01/07/2016 11:09:07   9,0767E+11 01/07/2016 11:30:23
   3     1  1395774 1,0486E+10    512       2 YES INACTIVE         9,0767E+11 01/07/2016 11:30:23   9,0767E+11 01/07/2016 11:41:51


Em muitos casos, quando criamos novos grupos de REDO, os grupos antigos ainda estão em utilização pelo banco de dados.
Para excluirmos esses grupos antigos precisaremos aguardar que os grupos novos passem a ser utilizados pelo banco de dados ou podemos forçar que os novos grupos passem a ser utilizados, liberando os grupos antigos.

Para isso, podemos utilizar o comando abaixo:

ALTER SYSTEM SWITCH LOGFILE;


Ao executarmos o comando [ ALTER SYSTEM SWITCH LOGFILE; ] imediatamente é gerado um log file e um novo grupo de redo começa a ser utilizado.
Em seguida, devemos fazer uma nova verificação dos grupos de redo em utilização e quando o grupo antigo estiver com o status INACTIVE, podemos fazer a remoção do grupo de redo com o comando: ALTER DATABASE DROP LOGFILE GROUP .


Referência:

https://docs.oracle.com/cd/B28359_01/server.111/b28310/onlineredo001.htm

ORA-01792: maximum number of columns in a table or view is 1000

Este erro pode ocorrer no Oracle database nas versões 10.2.0.4 até a 12.1.0.2.
Uma das recomendações da Oracle é a não utilização de tabelas com mais de 1000 colunas. 
Uma observação importante é que se estivermos criando uma view e fazendo join entre
tabelas, a quantidade de colunas a ser contabilizada é a da view e não necessariamente da tabela original. Existem 3 formas de resolver o problema, sendo: 1) Patch de correção É recomendando a aplicação do patch 19509982. Este patch está incluso na atualização de produto Oracle 12c (database) a partir de Abril/2016 (19-04-16) * Mesmo tendo esse patch aplicado, podemos ainda receber o erro informado. 2) Alterar a sessão Podemos configurar o parâmetro "_fix_control"='17376322:OFF' para a sessão que estamos executando no banco de dados, através do comando abaixo: SQL> alter session set "_fix_control"='17376322:OFF';
3) Alterar o banco de dados (spfile) A outra alternativa que temos é alterar o arquivo spfile, incluindo o parâmetro diretamente nas configurações gerais do banco de dados. SQL> alter system set "_fix_control"='17376322:OFF' scope=both; Esse parâmetro é aplicado sem a necessidade de reiniciar o banco de dados.
Referências: https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=391695224838272&id=1951689.1&_afrWindowMode=0&_adf.ctrl-state=vvdi114x_170 Select Statement Throws ORA-01792 Error (Doc ID 1951689.1)

Estatísticas


A coleta de estatísticas no banco de dados é muito importante para o bom desempenho dos SQLs que são executados.

As estatísticas coletadas, ajudam o otimizador do banco de dados a encontrar planos de execução mais eficientes e consequentemente, teremos um melhor desempenho desses SQLs.

A periodicidade dessas coletas vai depender muito da quantidade de dados que as tabelas possuem e de quanto esses dados são modificados. Se temos muita alteração dos dados, essa coleta devrá ser feita em períodos mais curtos.

O Oracle possui uma coleta automática de estatística para o banco de dados.

Essa coleta é feita durante à noite, em um período onde o banco esteja "ocioso", mas em casos de bancos 24X7 que tenham acesso o tempo todo, essa coleta não é realizada e devemos fazer esse procedimento manualmente e/ou agendar um JOB para execução periódica da coleta de estatísticas.

Vale ressaltar, que em alguns casos, a coleta de estatística pode deixar a execução de um SQL mais lento do que ele era a algum tempo. Isso não é uma regra, mas pode acontecer e já tive essa experiência, onde um processamento que tinha uma duração de 2 dias passou para mais de uma semana após a coleta de estatística.

Claro que foi um caso excepcional onde as tabelas envolvidas possuem muitos dados e uma grande quantidade alteração, onde foi necessário encontrar o plano de execução anterior e configurá-lo para ser novamente utilizado pelo processamento, mas isso é  assunto para outro dia.

Abaixo, segue uma lista de comandos que podemos utilizar para verificar as tabelas e índices no banco de dados, verificar a data da última coleta de estatística, realizar a coleta manualmente e verificar o seu andamento.


Estatísticas do Banco de dados:

Para coletar estatística de todos os objetos (tablas, índices,...) do banco de dados, podemos utilizar:

EXEC DBMS_STATS.GATHER_DATABASE_STATS

EXEC DBMS_STATS.GATHER_DATABASE_STATS(cascade => TRUE, method_opt => 'FOR ALL COLUMNS SIZE AUTO' );

  
E para coletarmos estatísticas do dicionário de dados:
  
 EXEC DBMS_STATS.GATHER_DICTIONARY_STATS



Estatísticas dos Schemas:

Podemos fazer a coleta de estatísticas do banco de dados por schema/usuário.

Dessa forma, podemos coletar a estatística de todas as tabelas / índices que pertencem a um usuário / schema específico.

Ex.:

Coletar estatística para todas as tabelas do schema/usuário ABCD:

EXEC DBMS_STATS.GATHER_SCHEMA_STATS('ABCD', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'GLOBAL AND PARTITION');


Coletar estatística para todas as tabelas do schema/usuário ABCD, com paralelismo:

EXEC DBMS_STATS.GATHER_SCHEMA_STATS('ABCD', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'GLOBAL AND PARTITION',degree=>8);


Estatísticas das Tabelas:

a) Listar as tabelas do banco de dados com a data da última coleta de estatística 

SQL> select owner,table_name,last_analyzed from dba_tables;


b) Listar as tabelas do banco de dados ordenado pela data da última coleta de estatística

SQL> select owner,table_name,last_analyzed from dba_tables by last_analyzed;


c) Listar as tabelas de um determinado schema / usuário com a data da última coleta de estatística 

SQL> select owner,table_name,last_analyzed from dba_tables where owner ='ABCD';


d) Listar as tabelas de um determinado schema / usuário ordenado pela data da última coleta de estatística

SQL> select owner,table_name,last_analyzed from dba_tables where owner ='ABCD' order by 3;



Verificar a estatística das tabelas


a) Verificar tabelas especificas:

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN, TO_CHAR(LAST_ANALYZED, 'DD/MM/YYYY HH24:MI:SS') FROM DBA_TABLES WHERE TABLE_NAME IN ('ABC','XYZ','1234');


b) Verificar todas as tabelas do banco de dados:

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN, TO_CHAR(LAST_ANALYZED, 'DD/MM/YYYY HH24:MI:SS') FROM DBA_TABLES;



Coletar a estatística de uma tabela especifica

a) Informando o percentual de coleta:

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'ABCD', TABNAME=>'ABCD_123', ESTIMATE_PERCENT=>10, granularity=>'ALL');


b) Deixando o oracle decidir a coleta:

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'ABCD', TABNAME=>'ABCD_123', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'ALL', method_opt =>'FOR ALL COLUMNS SIZE AUTO');


c) Definindo paralelismo na coleta:

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'ABCD', TABNAME=>'ABCD_123', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'ALL', method_opt =>'FOR ALL COLUMNS SIZE AUTO',degree=>8);



Obs.: A Oracle recomenda na versão 11g do banco de dados, a utilização dos parâmetros :

ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'ALL', method_opt =>'FOR ALL COLUMNS SIZE AUTO' 


Estatísticas dos índices:

a) Listar os índices do banco de dados com a data da última coleta de estatística 

SQL> select owner,index_name,last_analyzed from dba_indexes;


b) Listar os índices do banco de dados com ordenado pela data da última coleta de estatística 

SQL> select owner,index_name,last_analyzed from dba_indexes order by last_analyzed;


c) Listar os índices de um determinado schema / usuário com a data da última coleta de estatística 

SQL> select owner,index_name,last_analyzed from dba_indexes where owner ='ABCD';


d) Listar os índices de um determinado schema /usuário ordenado pela data da última coleta de estatística 

SQL> select owner,index_name,last_analyzed from dba_indexes where owner ='ABCD' order by 3;


Verificar a estatística das tabelas de índices:


a) Verificar índices de usuário/schema específico:

SQL> SELECT INDEX_NAME "NAME", NUM_ROWS, DISTINCT_KEYS "DISTINCT", LEAF_BLOCKS, CLUSTERING_FACTOR "CF", BLEVEL "LEVEL", AVG_LEAF_BLOCKS_PER_KEY "ALFBPKEY" FROM DBA_INDEXES WHERE owner = 'ABCD' ORDER BY INDEX_NAME;


b) Verificar todos os índices do banco de dados:

SQL> SELECT INDEX_NAME "NAME", NUM_ROWS, DISTINCT_KEYS "DISTINCT", LEAF_BLOCKS, CLUSTERING_FACTOR "CF", BLEVEL "LEVEL", AVG_LEAF_BLOCKS_PER_KEY "ALFBPKEY" FROM DBA_INDEXES ORDER BY INDEX_NAME;


Coletar a estatística de um índice específico

a) Informando o percentual de coleta:

SQL> EXEC DBMS_STATS.GATHER_INDEX_STATS(OWNNAME=>'ABCD', INDNAME=>'ABCD_I', ESTIMATE_PERCENT=>10, granularity=>'ALL');


b) Deixando o oracle decidir a coleta:

SQL> EXEC DBMS_STATS.GATHER_INDEX_STATS(OWNNAME=>'ABCD', INDNAME=>'ABCD_I', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'ALL', method_opt =>'FOR ALL COLUMNS SIZE AUTO');


c) Definindo paralelismo na coleta:

SQL> EXEC DBMS_STATS.GATHER_INDEX_STATS(OWNNAME=>'ABCD', INDNAME=>'ABCD_I', ESTIMATE_PERCENT=>dbms_stats.auto_sample_size, granularity=>'ALL', method_opt =>'FOR ALL COLUMNS SIZE AUTO',degree=>32);


Verificar a estatística de colunas

a) Verificar estatística de Colunas de tabelas especificas:

SQL> SELECT COLUMN_NAME, NUM_DISTINCT, NUM_NULLS, NUM_BUCKETS, DENSITY FROM DBA_TAB_COL_STATISTICS WHERE TABLE_NAME ="ABCD" ORDER BY COLUMN_NAME;


b) Verificar estatística de todas as Colunas do banco:

SQL> SELECT COLUMN_NAME, NUM_DISTINCT, NUM_NULLS, NUM_BUCKETS, DENSITY FROM DBA_TAB_COL_STATISTICS ORDER BY COLUMN_NAME;



Verificar execução da coleta de estatística

Aqui, podemos verificar o tempo de andamento da execução da coleta de estatística e também o tempo que falta para sua conclusão:


SQL> SELECT SID, SERIAL#, opname, SOFAR, TOTALWORK, ROUND(SOFAR/TOTALWORK*100,2) COMPLETE FROM V$SESSION_LONGOPS WHERE TOTALWORK != 0 AND    SOFAR != TOTALWORK and OPNAME like '%Partition Statistics%' order by 1;



Verificar tabela com estatísticas bloqueadas


Com o select abaixo, podemos identificar as tabelas que estão marcadas para não terem a coleta de estatística executada.

Quando temos o parâmetro STATTYPE_LOCKED definido como ALL na tabela dba_tab_statistics, não conseguimos fazer a coleta de estatística para essas tabelas.

Antes de alterarmos seu status, precisamos identificar o motivo desse status (ALL) estar configurado.


SELECT OWNER,TABLE_NAME,STATTYPE_LOCKED from dba_tab_statistics where STATTYPE_LOCKED='ALL' order by 1


Views envolvidos nas coletas de estatísticas:

DBA_TABLES
DBA_TAB_COL_STATISTICS
DBA_INDEXES
DBA_CLUSTERS
DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS
DBA_IND_PARTITIONS
DBA_IND_SUBPARTITIONS
DBA_PART_COL_STATISTICS
DBA_SUBPART_COL_STATISTICS
DBA_TAB_COLUMNS
INDEX_STATS


Referencias:

http://docs.oracle.com/cd/B19306_01/server.102/b14211/stats.htm#i41448
https://docs.oracle.com/cd/A97630_01/server.920/a96533/stats.htm
How to Gather Optimizer Statistics on 11g [ID 749227.1]

ERRO - ORA-00030 : User session ID does not exist


Ao tentarmos excluir uma sessão do banco de dados, com o comando:

SQL> alter system kill session '11,20425' immediate;

recebemos o erro:

ORA-00030: User session ID does not exist.


Após esse erro, começamos a investigar a sessão e as formas possíveis para eliminá-la do banco de dados.


1) Verificar a sessão no banco de dados

SQL> select username,sid,serial#,status,osuser,inst_id from gv$session where username='USER_APP';

USERNAME            SID    SERIAL# STATUS   OSUSER                            INST_ID
------------ ---------- ---------- -------- ------------------------------ ----------
USER_APP             11      20431 ACTIVE   user_app                                1


Com isso, percebemos que a sessão existe no banco de dados.


2) Identificar o processo no sistema operacional


Com o SQL abaixo, podemos identificar o processo da sessão no sistema operacional.


SQL> select logon_time, sid, serial#, username, status, process from gv$session where username='USER_APP';

LOGON_TIME                 SID    SERIAL# USERNAME     STATUS    PROCESS
------------------- ---------- ---------- ------------ -------- ------------
21/07/2016 13:19:15       9233      15693 USER_APP     ACTIVE    65143038


Com o valor do PROCESS, podemos ir no sistema operacional e eliminar a sessão.


No S.O. Unix:
-------------

$ ps -ef | grep 65143038

user_app 65143038        1   0 13:36:48      -  0:00 oraclexpto (LOCAL=NO)



Em seguida, utilizamos o comando kill -9 para matar a sessão.

$ kill -9 65143038


Voltando ao banco de dados, veremos que a sessão não existe mais.

SQL> select username,sid,serial#,status,osuser,inst_id from gv$session where username='USER_APP';

no rows selected


Obs.: Matar uma sessão de banco de dados com kill -9 no sistema operacional, não é recomendado. Estamos utilizando neste caso, por ser uma sessão perdida no banco de dados.


3) Listar o SPID para eliminar o processo no sistema operacional.

Também podemos utilizar o SQL abaixo para identificarmos o processo no sistema operacional.

SQL>

SELECT S.SID, S.SERIAL#, S.USERNAME, P.SPID
  FROM (SELECT SID, SERIAL#, USERNAME, PADDR FROM V$SESSION where status <> 'KILLED') S,
  (SELECT SPID, ADDR, UPPER(USERNAME) FROM V$PROCESS ) P
  WHERE S.PADDR = P.ADDR(+)
 ORDER BY SPID, S.SID

Ex.:

       SID    SERIAL# USERNAME     SPID
---------- ---------- ------------ ------------------------
     11043          1              65143038


O resultado do SQL mostrará todas as sessões do banco de dados e sues respectivos SPID (Processos).

$ ps -ef | grep 65143038

    user_app 65143038        1   0 13:36:48      -  0:00 oraclexpto (LOCAL=NO)


Da mesma forma que mostramos no item anterior, utilizaremos o comando kill -9

$  kill -9 65143038



4) O PROCESS ou SPID não encontrado no S.O.


Mesmo consultando as tabela do banco de dados, não encontramos o processo indicado no banco no sistema operacional para podermos eliminar a sessão utilizando o kill -9 .

Verificamos o alert.log do banco de dados, onde encontramos o erro: ORA-24756: transaction does not exist

A solução que conseguimos encontrar para resolver o problema foi executar um startup force com o banco de dados online.

SQL> startup force


** A outra solução seria parar e reiniciar o banco de dados.


Referências:

https://community.oracle.com/thread/2314375?tstart=0
ORA-30 Received When Trying To Kill Session (Doc ID 1011386.6)
ORA-00030 When Trying to Kill a Session In a RAC database. (Doc ID 751638.1)
http://web3null.blogspot.com.br/2013/10/ora-00030-user-session-id-does-not-exist.html
http://glufke.net/oracle/viewtopic.php?f=6&t=9284



ERRO ORACLE ORA-1033


O erro ORA-1033, conforme descrito abaixo ocorre de forma intermitente no ambiente RAC 12c com pluggable database.

Em diversas tentativas de conexão, algumas ocorrem com sucesso e outras apresentam o erro abaixo:

ORA-01033: ORACLE initialization or shutdown in progress
ID do Processo: 0
ID da Sess o: 0 N mero de s rie: 0


Esse problema pode ocorrer devido a 2 fatores:


1 - O banco de dados pluggable (PDB) pode não estar "aberto" em todas as instâncias do RAC;
2 - O service name usado para conectar no PDB possui o mesmo nome do próprio PDB.

Obs.:

Usar o mesmo nome do PDB para o service name que fará a conexão ao banco (PDB) não é uma prática recomendável pela Oracle, pois poderá causar o erro ORA-1033


Para solucionar o problema podemos:

1 - Abrir o PDB em todas as instâncias do RAC

Para abir o PDB em todas as intâncias de um ambiente RAC, podemos utilizar o comando abaixo:

SQL> alter pluggable database PDB01 open;



2 - Criar um service name com um nome diferente do PDB

Para isso, devemos:

a) Criar um novo service

$ORACLE_HOME/bin/srvctl add service -database <nome_do_banco_de_dados> -pdb <nome_do_pdb> -s <nome_do_serviço> -r '<Instâncias_do_banco_1>,<Instâncias_do_banco_2>,<Instâncias_do_banco_3>'

Ex.:

$ORACLE_HOME/bin/srvctl add service -database cdb1 -pdb pdb_01 -s pdb_acesso -r 'cdb11,cdb12,cdb13'



b) Iniciar o serviço no ambiente

$ORACLE_HOME/bin/srvctl start service -database <nome_do_banco_de_dados> -service <nome_do_serviço>

Ex.:

$ORACLE_HOME/bin/srvctl start service -database cdb1 -service pdb_acesso


c) Verificar se o serviço está ativo

$ srvctl status service -d <nome_do_banco_de_dados>

Ex.:

$ srvctl status service -d cdb1

Service pdb_acesso is running on instance(s) cdb11,cdb12,cdb13



d) Alterar o arquivo tnsnames.ora

Após a criação do serviço no ambiente do banco de dados, é necessário incluir a entrada desse serviço no arquivo tnsnames.ora

cd $ORACLE_HOME/network/admin

Editar o arquivo tnsnames.ora

vi tnsnames.ora

Exemplo de entrada no arquivo tnsnames.ora


pdb_acesso=
(description=
(load_balance=on)
         (failover=on)
           (address=
             (protocol=tcp)
               (host=10.12.123.12)
               (port=1521)
           )
           (address=
             (protocol=tcp)
             (host=10.12.123.21)
             (port=1521)
           )
           (connect_data=
             (server=dedicated)
             (service_name=pdb_acesso)
           )
          )



Podemos ainda testar a entrada configurada no arquivo tnsnames.ora com o comando tnsping

$ tnsping pdb_acesso

Se a configuração estiver correta, teremos uma resposta semelhante a descrita abaixo:

TNS Ping Utility for IBM/AIX RISC System/6000: Version 12.1.0.2.0 - Production on 15-JUL-2016 08:50:46

Copyright (c) 1997, 2014, Oracle.  All rights reserved.

Used parameter files:
$ORACLE_HOME/network/admin/sqlnet.ora

Used TNSNAMES adapter to resolve the alias
Attempting to contact (description=(load_balance=on)(failover=on)(address=(protocol=tcp)(host=10.12.123.12)(port=1521))(address=(protocol=tcp)(host=10.12.123.21)(port=1521))(connect_data=(server=dedicated)(service_name=pdb_acesso)))
OK (0 msec)




e) Verificar dentro do banco de dados se o serviço está criado

Podemos também verificar por dentro do banco de dados se o serviço que criamos está realmente sendo reconhecido.

Para isso, devemos executar:

$ sqlplus / as sysdba

Set lines 200

SQL> select name, pdb, inst_id from gv$services;

NAME                                                             PDB                               INST_ID
----------------------------------------------------- ------------------------------ ----------
pdb_acesso                                                          PDB                                  1
pdb                                                                      PDB                                  1
cdb1XDB                                                         CDB$ROOT                        1
cdb1.world                                                       CDB$ROOT                        1
SYS$BACKGROUND                                    CDB$ROOT                        1
SYS$USERS                                                    CDB$ROOT                        1
pdb_acesso                                                          PDB                                  2
pdb                                                                      PDB                                  2
cdb1XDB                                                         CDB$ROOT                        2
cdb1.world                                                       CDB$ROOT                        2
SYS$BACKGROUND                                    CDB$ROOT                        2
SYS$USERS                                                    CDB$ROOT                        2



Podemos perceber que o serviço criado está na lista de serviços do banco de dados.




Referências:

https://en.wikibooks.org/wiki/RAC_Attack_-_Oracle_Cluster_Database_at_Home/RAC_Attack_12c/Service_Failover

Connecting To A 12c RAC Pluggable Database Intermittently Fails With ORA-1033 (Doc ID 1998112.1)