Entendendo o erro ORA-00845 com Oracle Internals
October 17, 2012

O erro ORA-00845 é disparado sempre no startup de uma instância Oracle 11g, falhando com a seguinte mensagem de erro:

 ORA-845: MEMORY_TARGET not supported on this system

O parâmetro MEMORY_TARGET define o tamanho a área que o Automatic Memory Management (AMM) irá poder trabalhar. O AMM permite o banco de dados Oracle realizar a redução e aumento das áreas SGA ou PGA como necessário, fazendo assim um tuning online do seu banco de dados.

Como esse artigo não se destina a explicar o que é AMM, você pode conferir mais detalhes na própria documentação Oracle: http://docs.oracle.com/cd/E11882_01/server.112/e25494/memory003.htm

O erro ORA-845 acontece quando você define um valor para o MEMORY_TARGET além do que o sistema consegue gerênciar. Vamos a um exemplo para ficar mais fácil

Em uma máquina de teste, tenho 5G de memória RAM:

[oracle@oracle11g ~]$ grep MemTotal /proc/meminfo 
MemTotal: 5079856 kB

Meu banco de dados, está com o MEMORY_TARGET para 1984M (quase 2G).

[oracle@oracle11g ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.2.0 Production on Tue Oct 16 23:13:59 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> show parameter memory

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
hi_shared_memory_address	     integer	 0
memory_max_target                    big integer 1984M
memory_target                        big integer 1984M
shared_memory_address		     integer	 0

Uma outra informação importante (você vai entender logo mais), o meu espaço em disco:

[oracle@oracle11g ~]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              19G  9.0G  8.5G  52% /
tmpfs                 2.5G  1.2G 1.3G  48%  /dev/shm

Quero agora aumentar  500M da minha AMM, vamo mudarentão o parâmetro MEMORY_TARGET para 2500M:

SQL> alter system set memory_max_target=2500M scope=spfile;

System altered.

SQL> alter system set memory_target=2500M scope=spfile;

System altered.

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>  
SQL> startup 

ORA-00845: MEMORY_TARGET not supported on this system

SQL>

A primeira vez que vi o erro não consegui entender muito bem do que se tratava. Já que tenho memória livre de sobra, como pode 500M interferir no startup da minha instância?

Tudo ficou ainda mais confuso, quando li uma note no site do supporte da Oracle:

 ORA-00845 When Starting Up An 11g Instance With AMM Configured. [ID 460506.1]

A nota diz claramente que o valor do parâmetro memory_target está relacionado com o tamanho da partição /dev/shm, e que para resolver o problema tenho que aumentar a partição /dev/shm para um valor maior:

# mount -t tmpfs shmfs -o size=7G /dev/shm

Feito isso minha instância subiu sem problema algum.

Ok … Perfeito, tudo funcionando …

Porém …

Surge agora o objetivo desse post, explicar o que o AMM tem q ver com a partição /dev/shm?!

A dúvida inicial era, por onde começar?

Bom … Existe um utilitário chamado sysresv sobre o diretório $ORACLE_HOME/bin para obter status da instância. Algumas vezes quando uma instância Oracle é abortada ou simplesmente um crash acontece, existe alguns “semaphores” ou “shared memory” que continuam ativados mesmo sem a instância no ar. Quando esses lixos (vamos dizer assim) ficam na memória a instância não consegui iniciar.

Para resolver esse problema a partir do 8i, a Oracle começou a fornecer o sysresv como um utilitário que limpa shared memory e sempahores além de visualizar processos IPC alocados, que é o que queremos. Mais detalhes veja a nota: Semaphores and Shared Memory – An Overview [ID 153961.1]

Em nosso ambiente:

[oracle@oracle11g ~]$ sysresv

IPC Resources for ORACLE_SID "dbtst" :
Shared Memory:
ID		KEY
3506180         0x3c8e282c
Semaphores:
ID		KEY
688129  	0x00fadcd4
Oracle Instance alive for sid "dbtst"

Ok, já temos a informação do Oracle que contém somente um segmento de memory shared definida pelo ID: 3506180

E no Linux? Como ele pode me falar?

No Linux assim como no Unix, é possível de obter detalhes das shared memories através do comando ipcs:

[oracle@oracle11g ~]$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 3080192    root      644        80         2                       
0x00000000 3112961    root      644        16384      2                       
0x00000000 3145730    root      644        280        2                       
0x3c8e282c 3506180  oracle      660        4096       0

Opa! Uma informação importante, o segmento 0x3c8e282c está sendo utilizado … porém existe somente um segmento de 4k (4096 bytes), valor muito pequeno comparado com  outras versões.

Na versão 9i por exemplo esse valor é bem maior bem maior veja:

[oracle@oracle9i ~]$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x90129508 65537      oracle    640        337641472   9

Com isso, percebemos que o segmento de memória do 11g, tornou-se muito menor em relação as outras versões. Mais isso nos leva a uma pergunta: Porque ele mudou isso?

A unica conclusão que cheguei foi que ele precisava desalocar e alocar rapidamente (função do AMM) e com segmentos menores isso se torna mais rápido. Precisava confirmar isso, e iniciei uma busca de como obter mais detalhes como tamanho e endereço dos segmentos de memória.

Em busca disso encontrei a resposta no “mapeamento dos segmentos de memória” que é visualizada através do comando pmap.

oracle@oracle11g ~]$ pmap `pgrep -f lgwr`
5601:   ora_lgwr_dbtst
0000000000400000 180232K r-x--  /u01/app/oracle/product/11.2.0/dbhome_1/bin/oracle
000000000b602000   1820K rwx--  /u01/app/oracle/product/11.2.0/dbhome_1/bin/oracle
000000000b7c9000    300K rwx--    [ anon ]
000000000d775000    276K rwx--    [ anon ]
0000000060000000      4K r-xs-  /dev/shm/ora_dbtst_3506180_0
0000000060001000  16380K rwxs-  /dev/shm/ora_dbtst_3506180_0
0000000061000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_1
0000000062000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_2
...
00000000da000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_122
00000000db000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_123
00000000dc000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_124
00000000dd000000  16384K rwxs-  /dev/shm/ora_dbtst_3506180_125
00007f962c052000   1088K rwx--  /dev/zero
00007f962c162000   1088K rwx--  /dev/zero
00007f962c272000   1920K rwx--  /dev/zero
00007f962c452000   1088K rwx--  /dev/zero
00007f962c562000   1088K rwx--  /dev/zero
...
00007f962cfe0000    128K rwx--  /dev/zero
00007f962d000000      8K rwx--  /dev/zero
00007f962d142000     40K r-x--  /lib64/libnss_files-2.5.so
00007f962d14c000   2044K -----  /lib64/libnss_files-2.5.so
00007f962d34b000      4K r-x--  /lib64/libnss_files-2.5.so
00007f962d34c000      4K rwx--  /lib64/libnss_files-2.5.so
00007f962e062000   2048K -----  /lib64/libdl-2.5.so (deleted)
00007f962e262000      4K r-x--  /lib64/libdl-2.5.so (deleted)
00007f962e263000      4K rwx--  /lib64/libdl-2.5.so (deleted)
...
00007f962feec000      4K rwx--  /lib64/ld-2.5.so (deleted)
00007fff02cdf000     84K rwx--    [ stack ]
00007fff02d8d000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]

A saída do comando pmap para o processo LGWR mostra que o Oracle usa o /dev/shm para o compartilhamento de memória. De fato, os arquivos realmente existem na partição /dev/shm

oracle@oracle11g ~]$ ls -ltr /dev/shm/
total 1210004
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_125
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_107
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_108
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_109
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_110
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_105
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_104
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_106
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_9
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_8
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_7
...
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_13
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_12
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_11
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_10
-rw-r----- 1 oracle oinstall        0 Oct 16 23:38 ora_dbtst_3506180_1
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:38 ora_dbtst_3506180_116
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:43 ora_dbtst_3506180_92
-rw-r----- 1 oracle oinstall 16777216 Oct 16 23:43 ora_dbtst_3506180_87
..
-rw-r----- 1 oracle oinstall 16777216 Oct 17 00:14 ora_dbtst_3506180_120
-rw-r----- 1 oracle oinstall 16777216 Oct 17 00:14 ora_dbtst_3506180_0
-rw-r----- 1 oracle oinstall 16777216 Oct 17 00:14 ora_dbtst_3506180_124

Existem aí vários arquivos de 16M de tamanho, o que responde nossa primeira dúvida. O Oracle utiliza desses pequenos arquivos para armazenar os dados de segmentos compartilhados, isso é feito devida a implementação POSIX onde tudo, inclusive um “segmento de memória compartilhada” é um arquivo.

A grande sacada do AMM é permitir deslocar memória compartilhada da SGA para a memória privada da PGA e com esses pequenos segmentos de 16M torna a operação rápida e tudo isso acontece na partição /dev/shm.

Na medida que aumento ou diminuo o tamanho da PGA através do parâmetro PGA_AGGREGATE_TARGET, os arquivos dentro da partição /dev/shm vão se movimentando de acordo com o valor passado, mostrando assim o deslocamento das memórias compartilhadas e privadas.

Um outro exemplo interessante acontece quando eu baixo a instância:

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

[oracle@oracle11g ~]$ ll /dev/shm/ 
total 0

Como era de imaginar, nenhum arquivo existe mais na /dev/shm

Ficou mais claro agora, porque do erro ORA-00845?

Oracle Goldengate 11.2.1.0.3 disponível para Linux
October 10, 2012

Hoje procurando pelo download do Oracle Goldengate 11g, eis que sem querer descubro que um novo release foi liberado para Linux x86-64:

Protegendo o Oracle – Parte 1
October 10, 2012

Essa é o início de uma série de artigos sobre proteção e segurança no banco de dados Oracle. Hoje estaremos falando sobre o controle de acesso ao dicionário de dados através do parâmetro de inicialização O7_DICTIONARY_ACCESSIBILITY.

De acordo com a documentação Oracle, esse parâmetro controla as restrições no privilégio de sistema. Caso esse parâmetro esteja habilitado (true) o acesso aos objetos SYS (consequentemente ao dicionário de dados) é permitida.

Vamos a um exemplo, veja que o parâmetro O7_DICTIONARY_ACCESSIBILITY está definido como false (padrão), assim mesmo que o usuário tenha privilégio de SELECT ANY TABLE ele não consegue acessas as tabelas do SYS. O mesmo vale para o privilégio EXECUTE ANY PROCEDURE, que permite executar qualquer procedure exceto as do usuário SYS, caso o parâmetro O7_DICTIONARY_ACCESSIBILITY esteja como false.

FSOARES@dbtst> create user usr1 identified by oracle;

User created.

FSOARES@dbtst> grant connect, resource to usr1;

Grant succeeded.

FSOARES@dbtst> grant select any table to usr1;

Grant succeeded.

FSOARES@dbtst> show parameter o7
NAME                                            TYPE        VALUE
---------------------------------------------- ----------- -------
O7_DICTIONARY_ACCESSIBILITY                    boolean     FALSE

Veja que criamos um usuário chamado usr1 e definimos a ele a permissão de SELECT ANY TABLE, porém o parâmetro O7_DICTIONARY_ACCESSIBILITY está definido como false, veja o que acontece caso o usuário USR1 tente selecionar qualquer tabela do usuário SYS.


USR1@dbtst> select name, password from sys.user$;
select name, password from sys.user$
                               *
ERROR at line 1:
ORA-00942: table or view does not exist

Mesmo com o privilégio SELECT ANY TABLE o usuário USR1 não consegue acessar as informações do schema SYS.

Vamos agora, inverter os papéis agora. Com o parâmetro O7_DICTIONARY_ACCESSIBILITY como true vamos ver o que acontece com as permissões no dicionário de dados:

SQL> alter system set O7_DICTIONARY_ACCESSIBILITY=TRUE scope=spfile;

System altered.

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup
ORACLE instance started.

Total System Global Area  845348864 bytes
Fixed Size		    1348216 bytes
Variable Size		  465571208 bytes
Database Buffers	  373293056 bytes
Redo Buffers		    5136384 bytes
Database mounted.
Database opened.

SQL> show parameter O7_DICTIONARY_ACCESSIBILITY

NAME				     TYPE	 VALUE
------------------------------------ ----------- -----
O7_DICTIONARY_ACCESSIBILITY	     boolean	 TRUE

USR1@dbtst> select name, password from sys.user$;

NAME                           PASSWORD
------------------------------ --------------------
SYS                            8A8F025737A9097A
PUBLIC
CONNECT
RESOURCE
DBA
SYSTEM                         2D594E86F93B17A1
SELECT_CATALOG_ROLE
EXECUTE_CATALOG_ROLE
DELETE_CATALOG_ROLE
OUTLN                          4A3BA55E08595C81
EXP_FULL_DATABASE
IMP_FULL_DATABASE
LOGSTDBY_ADMINISTRATOR
DBFS_ROLE
DIP                            CE4A36B8E06CA59C
AQ_ADMINISTRATOR_ROLE
AQ_USER_ROLE
DATAPUMP_EXP_FULL_DATABASE
DATAPUMP_IMP_FULL_DATABASE
ADM_PARALLEL_EXECUTE_TASK
GATHER_SYSTEM_STATISTICS
JAVA_DEPLOY
ORACLE_OCM                     5A2E026A9157958C
..
HR                             6399F3B38EDF3288
OE                             9C30855E7E0CB02D
IX                             2BE6F80744E08FEB
SH                             9793B3777CD3BD1A
PM                             72E382A52E89575A
BI                             FA1D2B85B70213F3
FSOARES                        3B789FED9DDFE9B9
USR1                           8FFA74CCAD48CE21
USR2                           6102DC4A88E79D5A

Com a conclusão dos testes acima, fica claro a grande necessidade de deixar o parâmetro O7_DICTIONARY_ACCESSIBILITY sempre como false, permitindo que qualquer sessão não pode obter informações sigilosas que são destinadas apenas ao Oracle e do DBA.

Movendo a tabela AUD$
October 10, 2012

Dependendo do nível e da quantidade de auditoria habilitada no banco de dados, os registros criados pelos audit trail, que geralmente são armazenados no banco através da tabela AUD$ pertencente ao schema SYS que consequentemente pertence ao tablespace SYSTEM, pode levar a números exorbitantes no tamanho desse tablespace.

Para mais informações precisas de auditoria, o Oracle fornece um controle ainda maior através do “Fine Grained Auditing” feature disponível para o Oracle 11g (estarei falando dela em breve). Com esse tipo de auditoria disponível um outra tabela é utilizada para armazenar as ações auditadas que é a FGA_LOG$ disponível também sobre o schema SYS.

Um procedimento muito interessante, antes da tabelas AUD$ e FGA_LOG$ do schema SYS começarem crescerem, recomendasse muda-lás para um outro tablespace de dados qualquer.

Esse metodo se faz interessante, já que se o tablespace SYSTEM crescer por causa dessas tabelas de auditoria o seu banco de dados pode parar caso o tablespace não encontre mais espaço para estender. Já com as tabelas de auditória fora do tablespace SYSTEM esse risco diminui.

Uma outra vantagem é a manutenção, já que caso alguma atividade (como shrink, move, etc …) seja necessária, ela será muito mais simples de ser executada caso for fora do tablepsace SYSTEM.

Segue o passo a passo para mudar a tabela AUD$ de tablespace:

oracle@oracle11g ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Tue Oct 9 23:42:18 2012

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQ> create tablespace "AUDIT" datafile '/u01/app/oracle/oradata/dbtst/audit_01.dbf' size 1G;

Tablespace created.

SQL> create table audx tablespace "AUDIT" 
  2  storage (initial 50k next 50k pctincrease 0)
  3  as select * from aud$ where 1 = 2; 

Table created.

SQL> rename AUD$ to AUD$$;

Table renamed.

SQL> rename audx to aud$;

Table renamed.

SQL> create index i_aud2
  2  on aud$(sessionid, ses$tid)
  3  tablespace "AUDIT" storage(initial 50k next 50k pctincrease 0);

Index created.

SQL> select tablespace_name from dba_tables where owner='SYS' and table_name='AUD$';

TABLESPACE_NAME
------------------------------
AUDIT
Instalando Oracle Statspack
October 3, 2012

Statspack tem sido utilizado desde a versão do Oracle 8i para análise e monitoramento de performance. Não muito diferente da versão Oracle 11g (mais nova até o momento), ele fornece um relatório rápido de seu ambiente afins de processos de tuning do seu banco de dados Oracle

Para mais informações do Statspack consulte o arquivo no seu ORACLE HOME: $ORACLE_HOME/rdbms/admin/spdoc.txt

É verdade sim, que o AWR fornece um relatório melhor comparado com o Statspack, porém usuário que não possuem licença para utilizar Enterprise Manager, devem continuar utilizando o Statspack.

StatsPack tem sido construido para ser instalado somente com uma conexão SYSDBA. A instalação é simples e trivial, uma vez conectado como SYSDBA no SQLPLUS basta executar o script:

FSOARES@oracle11g> @spcreate
Choose the PERFSTAT user's password
-----------------------------------
Not specifying a password will result in the installation FAILING
Enter value for perfstat_password:
...

Alguns perguntas serão feitas como:

  • Senha do usuário PERSTATS
  • Tablespace Default do usuário PERSTATS
  • Tablespace Temporário do usuário PERFSTATS

Caso queria remover Statspack basta executor o spdrop.sql encontrado no $ORACLE_HOME/rdbms/admin. Qualquer falha na execução do script no momento da criação ou algum cancelamento inadequado, deve-se primeiro remover o StatsPack com o script spdrop.sql depois sim criar com o spcreate.sql.

Na criação do script, um arquivo spckg.list é criado, reveja o arquivo para qualquer possível erro que encontrar.