Páginas

quarta-feira, 29 de junho de 2011

Database size - MySQL

A query abaixo retorna um relatório com todos os databases do banco e seu tamanho em MB. Além do tamanho total, retorna separadamente o tamanho em dados e índices e ainda a quantidade de tabelas.

SELECT table_schema,
 COUNT(1) as COUNT_TABLES,
 SUM(data_length+index_length)/1024/1024 as TOTAL_MB,
 SUM(data_length)/1024/1024 as DATA_MB,
 SUM(index_length)/1024/1024 AS INDEX_MB
FROM information_schema.tables
GROUP BY table_schema
ORDER BY 3 DESC;

segunda-feira, 27 de junho de 2011

Dicas sobre swap em Linux

Para servidores de banco de dados dedicados, o uso da área de swap é muito ineficiente e deve ser evitado ao máximo. Podemos alterar o comportamento default de como o kernel (a partir da versão 2.6) "julga" a utilização ou não da área de swap através do parâmetro swappiness:

[root@localhost ~] sysctl vm.swappiness
vm.swappiness = 60 --valor default

Quanto maior esse valor, maior a tendência com que o kernel faça swap (mais info: http://kerneltrap.org/node/3000). Setando esse valor para zero, o kernel fará swap apenas em último caso (que é o desejável):

[root@localhost ~] sysctl -w vm.swappiness=0

IMPORTANTE: Para persistir as configurações, é necessário adicionar a entrada ao arquivo /etc/sysctl.conf:

vm.swappiness = 0

Caso a área de swap já esteja sendo utilizada, podemos forçar as páginas em disco irem para a memória desligando o swap (temporariamente):

[root@localhost ~] swapoff /dev/swap01

DICA: Em outra sessão, é possível acompanhar o andamento do swapoff através do vmstat.

Após isso, podemos voltar a ativar a área de swap:
[root@localhost ~] swapon /dev/swap01

Caso não haja espaço livre em memória para receber as páginas em disco, podemos fazer um procedimento para dropar o cache em memória, liberando assim espaço para receber as páginas em disco (a partir do kernel 2.6.16):

Liberar pagecache:
[root@localhost ~] sync; echo 1 > /proc/sys/vm/drop_caches
 
Liberar dentries e inodes:
[root@localhost ~] sync; echo 2 > /proc/sys/vm/drop_caches
 
Liberar pagecache, dentries e inodes: 
[root@localhost ~] sync; echo 3 > /proc/sys/vm/drop_caches 

Essa operação não é destrutiva e pode ser feita online. Deve-se atentar ao fato que dropando o cache de memória, a carga de CPU do servidor tende a aumentar momentaneamente até o cache ser reconstruído.

terça-feira, 21 de junho de 2011

Foreign Key sem índice

A query abaixo lista todas as FKs existentes na instância que não tem índice na tabela filha:

with
  dados as
   (select
      cc.owner, cc.table_name, cc.constraint_name, cc.column_name, cc.position, i.index_name, i.column_position index_position, r.owner r_ownwer, r.table_name r_table_name,
      count(distinct cc.column_name) over(partition by cc.owner, cc.table_name, cc.constraint_name) qtde_cons_columns,
      count(distinct i.column_name) over(partition by cc.owner, cc.table_name, cc.constraint_name, i.index_name) qtde_ind_columns
    from dba_ind_columns i, dba_cons_columns cc, dba_constraints r, dba_constraints c
    where
      c.constraint_type = 'R' and
      r.owner = c.r_owner and
      r.constraint_name = c.r_constraint_name and
      cc.owner = c.owner and
      cc.constraint_name = c.constraint_name and
      i.table_owner (+) = cc.owner and
      i.table_name (+) = cc.table_name and
      i.column_name (+) = cc.column_name and
      i.column_position (+) = cc.position),
  cons_ok as
   (select distinct owner, constraint_name
    from dados
    where
      qtde_cons_columns = qtde_ind_columns) select * from dados where
  (owner, constraint_name) not in (select * from cons_ok) order by 1, 2, 3, 5, 6;

Colunas que são FK e não tem índice podem causar problemas de performance caso a query utilizada faça join através deste campo (o que geralmente ocorre, justamente por ser FK).



Mais informações sobre quando é necessário criar índices em FK's:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:292016138754

quarta-feira, 15 de junho de 2011

Criando um standby físico com RMAN DUPLICATE (online)

Passo a passo para se criar um standby físico utilizando o comando DUPLICATE do RMAN a partir de um database master ativo.

  • A feature de criação online está disponível a partir da versão Oracle 11g.
  • O comando duplicate do RMAN está disponível em versões anteriores, porém não é feito de forma "online": é necessário restaurar um backup para criar a criação do standby nas versões anteriores a 11g.
  • Documentação Oracle: Step by Step Guide on Creating Physical Standby Using RMAN DUPLICATE...FROM ACTIVE DATABASE Without Shutting down the Primary and using Primary Active Database Files [ID 1075908.1]
Passo a passo:

1.Make the necessary changes to the primary database.
   a. Enable force logging.
   b. Creating the password file if one does not exist.
   c. Create standby redologs.
   d. Modify the parameter file suitable for Dataguard.
2. Ensure that the sql*net connectivity is working fine.
3. Create the standby database over the network using the active(primary) database files.
   a. Create the password file
   b. Create the initialization parameter file for the standby database (auxiliary database)
   c. Create the necessary mount points or the folders for the database files
   d. Run the standby creation ON STANDBY by connecting to primary as target database.

O passo acima em destaque é o que efetivamente cria o standby. O banco standby deve estar no estado NOMOUNT com o pfile que foi criado no passo 3.b (pfile com apenas o parâmetro db_name='$NOME')

Depois de subir em NOMOUNT, a partir do primary deve-se conectar ao rman com o standby de auxiliar:

rman target sys/$PASS@$primary auxiliary sys/$PASS@standby

connected to target database: PRIMARY(DBID=XXXXXXXX)
connected to auxiliary database: STANDBY (not mounted)
 

IMPORTANTE: A conexão de ambos os lados deve ser feita usando entradas no TNS da máquina standby (netservices). Conectando-se localmente ( auxiliary /) não vai funcionar.

IMPORTANTE2: Os dois servidores envolvidos tem que ter a mesma entrada no tns (lembre-se de usar UR=A).


IMPORTANTE3: Em caso de FS, crie todos os diretórios antes.

IMPORTANTE4: Forçar o tns a se conectar no nó 1 do cluster (primary e standby) em caso de Oracle RAC

RMAN DUPLICATE:

run {
allocate channel prmy1 type disk;
allocate channel prmy2 type disk;
allocate channel prmy3 type disk;
allocate channel prmy4 type disk;
allocate auxiliary channel stby type disk;
duplicate target database for standby from active database nofilenamecheck
spfile
parameter_value_convert ' $NOME ',' $NOME '
set db_unique_name=' $NOME '
set db_file_name_convert='+DG_DATA1/ $NOME ','+DG_DATA/ $NOME '
set log_file_name_convert='+DG_REDO1/ $NOME ','+DG_REDO/ $NOME '
set control_files='+DG_CONTROL','+DG_DATA'
set log_archive_max_processes='5'
set audit_file_dest='/u00/app/oracle/diag'
set db_create_file_dest='+DG_DATA'
set fal_client=' $NOME_STD '
set fal_server=' $NOME_MASTER '
set standby_file_management='AUTO'
set log_archive_dest_1='LOCATION=+DG_ARCH'
set log_archive_format='SGA_%t_%s_%r.arc';
}


Caso o standby não tenha o mesmo nome do primary, retire a entrada nofilenamecheck e altere os valores de $NOME para:
Primeiro valor: SID_MASTER
Segundo valor: SID_STANDBY

OBS.: Já passei por casos onde é necessário setar manualmente o SID no standby para evitar problemas no serviço durante o processo (pois o duplicate restarta o banco).
OBS2: Esta solução se mostrou bastante ineficiente para standby com db_unique_name diferente e estrutura de diretórios diferentes. Cai várias vezes no erro ORA-29760 e tentei todas as formas de setar o parâmetro parameter_value_convert. Fica bem mais simples nesses casos configurar o pfile do standby manualmente e, ao invés de spfile, setar pfile='/tmp/init.ora' no script duplicate.

Instalação agent11g com responseFile (RAC e Standalone)

Download dos binários:

http://www.oracle.com/technetwork/oem/grid-control/downloads/agentsoft-090381.html


Documentação completa Oracle: http://download.oracle.com/docs/cd/E11857_01/install.111/e16847/install_agent_on_clstr_slnt.htm

Criar o seguinte responseFile (/tmp/response.file), dando atenção aos parâmetros em vermelho:


RESPONSEFILE_VERSION=2.2.1.0.0
SECURITY_UPDATES_VIA_MYORACLESUPPORT=false
DECLINE_SECURITY_UPDATES=true
INSTALL_UPDATES_SELECTION="skip"
ORACLE_AGENT_HOME_LOCATION="/u00/app/oracle/product/"
DEINSTALL_LIST={"oracle.sysman.top.agent","11.1.0.1.0"}
b_silentInstall=true
#CLUSTER_NODES={"node01","node02"} # DESCOMENTAR PARA INSTALAÇÃO EM RAC
TOPLEVEL_COMPONENT={"oracle.sysman.top.agent","11.1.0.1.0"}
COMPONENT_LANGUAGES={"en"}
OMS_HOST="$OMS_HOSTNAME"
OMS_PORT="4900"
AGENT_REGISTRATION_PASSWORD="$PASSWORD"
FROM_LOCATION="../stage/products.xml"
b_upgrade=false
EM_INSTALL_TYPE="AGENT"

Executar o instalador:

./linux_x64/agent/runInstaller -silent -responsefile /tmp/response.file

Rodar root.sh como root:

$AGENT_HOME/root.sh

OBS.: Para instalar o agent em ambiente RAC com um nome de cluster diferente do nome utilizado na instalação (checar $ORA_CRS_HOME/bin/cemutlo -n), basta setar a variável CLUSTER_NAME com o nome desejado antes de executar o instalador.

Grid Control - debug de targets

Limpar agent (remoção de todos os targets, inclusive o agent):

exec mgmt_admin.CLEANUP_AGENT('svr0000.adm.infra:3872');


    Apagar targets manualmente:

    exec mgmt_admin.delete_target('$NOME_TARGET','$TIPO_TARGET');


      Forçar exclusão de targets:

      exec mgmt_admin.delete_target_internal('$NOME_TARGET','$TIPO_TARGET');

        Bug para inserir novo target:



        java.sql.SQLException: ORA-20600: The specified target is in the process of being deleted.(target name = SID)(target type = oracle_database)(target guid = 21D8EFD67CCF409D7CDB41DCFD1F9D94)
        ORA-06512: at “SYSMAN.TARGETS_INSERT_TRIGGER”, line 36
        ORA-04088: error during execution of trigger ‘SYSMAN.TARGETS_INSERT_TRIGGER’
        ORA-06512: at “SYSMAN.EM_TARGET”, line 1918
        ORA-06512: at “SYSMAN.MGMT_TARGET”, line 2705
        ORA-06512: at line 1


        Workround:


        select * from MGMT_TARGETS_LOAD_TIMES where target_guid='21D8EFD67CCF409D7CDB41DCFD1F9D94';

          delete from MGMT_TARGETS_LOAD_TIMES where target_guid='21D8EFD67CCF409D7CDB41DCFD1F9D94';