quinta-feira, 20 de junho de 2013

GUOB TECH DAY 2013

Fala Pessoal,

Estamos nos aproximando do GUOB desse ano, como a maioria já sabe esse é o único evento TÉCNICO de Oracle do Pais.
É o melhor local para renovar idéias, ficar por dentro das novidades, rever conhecidos e amigos.
Eu estarei lá pelo 3º ano seguido.
Evento mais que recomendado, para quem não esta em São Paulo e ta pensando se vale a pena ir, não pense , faça a inscrição e compre a sua passagem, e para quem esta em São Paulo não tem a menor desculpa para não ir.

Abraços !

quarta-feira, 27 de março de 2013

Oracle In-Memory Database Cache


Nesse artigo vamos apresentar o timesten database e mostrar sua funcionalidade que é o timesten in memory cache database. Nessa primeira parte vamos instalar o timesten criar algumas estruturas realizar o cachê de algumas tabelas. No próximo artigo irei explicar melhor os conceitos apresentados aqui e um benchmarking.

Oracle TimesTen In-Memory Database (TimesTen) é utilizado para o gerenciamento de dados em tempo real na camada da aplicação; Utilizamos ele como armazenamento em cache para armazenar tabelas acessadas com frequência de um servidor de banco de dados Oracle para a camada da aplicação(cachê)  mantendo a consistência dos dados armazenados; e um componente de replicação de dados transacionais para garantir a alta disponibilidade entre camadas.

Escrevi esse artigo no portal do GPO, para continuar lendo acesse:

segunda-feira, 10 de setembro de 2012

Mudando a Prioridade do Processo VKTM no Oracle 11G R2



Fala Pessoal,

Tive um problema recente com o processo VKTM em um ambiente linux(RED HAT) virtualizado.
Esse Processo tem a seguinte descrição segundo a documentação:
VKTM is responsible for providing centralized time tracking

• wall-clock time (updated every second)
• reference-time counter (updated every 20 ms)

Ele é utilizado pelo scheduler.
Porém ele tem um consumo altíssimo de CPU .
No meu ambiente ele consumia 13% de CPU

13.2 19414 oracle   ora_vktm_opscgold          RR

Dando um trace no processo verifiquei que ele chama a função gettimeofday mais de 100 vezes por segundo.

[root@orarac1 ~]# strace -p 6723
Process 6723 attached – interrupt to quit
gettimeofday({1323711237, 10495}, NULL) = 0
gettimeofday({1323711237, 10555}, NULL) = 0
nanosleep({0, 10000000}, {1323711237, 10495}) = 0
gettimeofday({1323711237, 21947}, NULL) = 0
gettimeofday({1323711237, 21999}, NULL) = 0
nanosleep({0, 10000000}, {1323711237, 21947}) = 0

Estudando mais afundo verifiquei que esse processo(VKTM) e o (LMS) são os únicos que rodam em RR (Roud Robin) alta prioridade de CPU , comentando tambem pelo kerry osborne


Esse processo estava realmente prejudicando a performance do ambiente e como era um ambiente de teste no meu caso foi melhor diminuir a prioridade dele e colocalo em TS (SCHED_NORMAL) .
Para mudar a prioridade de um processo basta alterar o parâmetro não documentado.

_high_priority_processes

Então alterei meu ambiente da seguinte forma

alter system set “_high_priority_processes”=’LMS*’ scope=spfile;

Após isso o consumo de CPU caiu drasticamente, porém é valido ressaltar que essa mudança provavelmente ira causar problemas no scheduler e algumas outras anomalias.

Mas no meu caso, no meu ambiente foi melhor assim, já passou 2 meses e a melhora foi significativa.
Abraços !!

segunda-feira, 30 de julho de 2012

Integrando o Oracle Database com o NoSQL Database MongoDB


Integrando as soluções para problemas de relatórios em bases transacionais

Bases de dados cada vez maiores, grande número de usuários concorrendo por dados e relatórios cada vez mais complexos gerando particionamento de tabelas, visões materializadas e etc. Tem horas que é preciso escalar o banco de dados e dividir transações de relatórios e nessa hora entram em discussão as perguntas, pode? Como? Quanto?

Abraços !!

quarta-feira, 23 de maio de 2012

O mito do “apagão de talentos”

Fala Pessoal,

Acabei de ler um post muito interessante sobre o suposto “apagão de talentos”, tenho visto cada vez mais esse suposto apagão se referir a area de banco de dados e eu discordo muito disso, esse post excelente do Fabio Luiz retrata perfeitamente a minha visão sobre o assunto, vale a pena dar uma lida.

http://blog.jumping.com.br/2012/05/o-mito-do-apagao-de-talentos/?goback=%2Egde_148535_member_117679150

Abraços !

segunda-feira, 21 de maio de 2012

Muitos Índices em uma Tabela


Fala pessoal vou falar de um assunto que sempre gera alguma discussão nos ambientes em que esse assunto foi levantado

Ultimamente tenho percebido certo padrão dizendo que nenhuma tabela pode ter mais de seis índices ou sete índices em alguns clientes. Então algumas instruções SQL podem executar bem, mas algumas podem não executar tão bem assim e se precisarmos de mais índices não podemos adicionar porque já existem 6 índices então algum teria que morrer para criar mais.

Entendendo que muitas vezes alguns índices podem ser redundantes, podemos pensar no índice IDX_OMT_NAME_ID_01 em (COL1, COL2), IDX_OMT_NAME_ID_02 em (COL1, COL2,COL3), e IDX_OMT_NAME_ID_03 em (COL1, COL2,COL3,COL4).

Nesses casos é comum que alguns DBAs pensem em dropar os primeiros dois índices porque eles são redundantes, ou seja, eles têm as mesmas colunas principais e na mesma ordem, como IDX_OMT_NAME_ID_03. 

Mas dropar índices redundantes pode causar problemas com a seleção de uma tabela de condução de um join. (No post sobre métodos de join eu falo sobre tabelas de condução ou driving tables).

Quando temos muitos índices em uma tabela, não vamos obter um impacto grande em questões de desempenho isso se estamos falando de sistemas OLTP, porque apenas algumas linhas são processadas ​​uma única transação, e o impacto de vários índices de em uma atualização geralmente não é tão grande se comparado a ao desempenho de uma consulta.

Agora um número alto de índices em uma tabela pode ser extremamente prejudicial para ambientes com grande número de processos batch de atualização, ou seja com um número alto de insets, updates e deletes.


Veja um leve comparativo:
Quantidade Linhas
Quantidade de Índices
Tempo
1000
0
00:00:00.41
10000
0
00:00:02.99
10000
1
00:00:05.88
10000
3
00:00:07.82
20000
5
00:00:59.69

Da para imaginar o problema quando temos uns 8 índices de uma tabela com alguns GB de tamanho, e inserindo mais alguns GB em um processo batch.

Um workaround para esse problema é dropar on índices antes da execução da batch e recriar os mesmos após a execução . Com opções como NOLOGGING e PARALLEL é possível reconstruir um índice com mais velocidade, porém mesmo com esses recursos o trabalho de reconstruir um índice pode demorar as vezes mais que o próprio processo batch se for o caso.

Minha experiência me diz que o melhor é não criar regras em relação a um número especifico de índices que uma tabela possa ter, porque literalmente cada caso é um caso.O melhor é sempre analisar a relação de custo e beneficio de um novo índice e o Oracle nos ajuda bastante porque podemos usar recursos como o ALTER INDEX MONITORING USAGE  para monitorar e verificar a eficiência e uso dos índices.

sexta-feira, 11 de maio de 2012

Como converter Oracle DB para MongoDB

Fala Pessoal,


Tenho pesquisado e estudado bastante as soluções NoSQL depois que grandes empresas passaram a integrar essa tecnologia como solução de escalabilidade para seus problemas. Discordo totalmente da visão de alguns profissionais os quais acreditam na total substituição dos bancos relacionais pelos NoSQL, isso para mim é sonho de programador que nunca soube escreve uma linha em SQL.
Mas acredito que é uma grande solução que pode ser integrada em quase todos os negócios junto com um banco relacional e outras soluções de cache e motor de busca, gerando assim escalabilidade, exemplos de arquitetura que integram as duas tecnologias como facebook e twitter mostram isso claramente. 


Usando como base a idéia do Jean Nascimento que criou um conversor de MySQL para MongoDB.
que esta disponivel no link :


http://imasters.com.br/artigo/17078/mongodb/como-converter-mysql-para-mongodb

Tive a idéia de criar um conversor de Oracle para MongoDb utilizando o PHP.


O MongoDB é uma aplicação de código aberto, de alta performance, sem esquemas, orientado a documentos. Foi escrito na linguagem de programaçãoC++. Além de orientado a documentos, é formado por um conjunto de documentosJSON. Muitas aplicações podem, dessa forma, modelar informações de modo muito mais natural, pois os dados podem ser aninhados em complexas hierarquias e continuar a ser indexáveis e fáceis de buscar. (Font Wikipedia)

Eu já vinha testando o MongoDB ha algum tempo e realmente é rápido e simples, não vejo sentido em benchmarks com um bancos relacionais pois acredito que em focos diferenciados. Acredito que o MongoDB é excelente para tudo o que não precisa ser relacional.


No link do Jean Nascimento acima tem a explicação para quem deseja instalar o MongoDB.


Segue o Link do conversor:


http://code.google.com/p/sql-hudson/downloads/list


quarta-feira, 29 de fevereiro de 2012

Monitorar SQLs que geram Locks no Oracle

Essa semana eu precisei monitorar alguns locks que estavam ocorrendo em uma base de produção.
Só que os locks eram esporádicos, não dava para ficar na frente de uma tela de OEM esperando acontecer, além disso eu precisava descobrir o SQL que estava bloqueando algum recurso e o SQL que estava esperando pelo recurso.

Eu criei um job que roda de 2 em 2 minutos , ele verifica se existe alguma sessão com evento de espera tipo o : enq: TX - row lock contention.
Caso exista e o tempo de espera seja maior que X ele loga os SQLSs que estao bloqueando e esperando por um recurso,o SID das sessões,a data e o tempo de espera da sessão em uma tabela que criei para isso.

O Mais legal nisso foi que descobri a coluna Prev_sql_id da V$SESSION, com ela conseguimos saber o SQL que esta bloqueando algum recurso.

Abaixo segue o comando de criação do JOB e da Tabela para logar.

UPDATE:
 Legal olhar um post de quase 4 anos atrás, vendo agora não gosto muito desse código, então decide realizar algumas pequenas modificações , graças ao comentário do Mauro rafael, modifiquei na hora mesmo, só por capricho,rs.

Tabela:

CREATE TABLE LOG_LOCK (SQL_BLOCKER VARCHAR2(1000),
SID_BLOCKER INT, SQL_BLOCKED VARCHAR2(1000),
SID_BLOCKED INT,DATA_LOG DATE,WAIT INT);


Job:

BEGIN
  DBMS_SCHEDULER.create_job (
 job_name        => 'Monitor_Lock',
 job_type        => 'PLSQL_BLOCK',
 job_action      => '
DECLARE

V_BLOCKER INT;
V_BLOCKED INT;
V_SQL VARCHAR2(1000);
V_SQL2 VARCHAR2(1000);
V_TIME INT;
V_CTR INT;

BEGIN

    SELECT COUNT(*) INTO V_CTR
    FROM v$session s
    WHERE event LIKE ''enq: %'';


       FOR CRS IN (select s1.sid BLOCKER, s2.sid BLOCKED
       from v$lock l1, v$session s1, v$lock l2, v$session s2
       where s1.sid=l1.sid and s2.sid=l2.sid
       and l1.BLOCK=1 and l2.request > 0
       and l1.id1 = l2.id1
       and l2.id2 = l2.id2)

       LOOP

          IF V_CTR >= 1 THEN

             V_BLOCKED:=CRS.BLOCKED;
             V_BLOCKER:=CRS.BLOCKER;

                 SELECT SQL_TEXT INTO V_SQL FROM V$SQL S
                 INNER JOIN V$SESSION V ON (V.Prev_sql_id=S.SQL_ID)
                 WHERE V.SID=V_BLOCKER;

                 SELECT SQL_TEXT ,V.SECONDS_IN_WAIT INTO V_SQL2,V_TIME FROM V$SQL S
                 INNER JOIN V$SESSION V ON (V.sql_id=S.SQL_ID)
                 WHERE V.SID=V_BLOCKED;


                 IF V_TIME > 30 THEN
                     INSERT INTO LOG_LOCK (SID_BLOCKER,SQL_BLOCKER,SID_BLOCKED,SQL_BLOCKED,DATA_LOG,WAIT) VALUES
                     (V_BLOCKER,V_SQL,V_BLOCKED,V_SQL2,SYSDATE,V_TIME);
                     COMMIT;

                END IF;

          END IF;

        END LOOP;


END;
 ',

 start_date      => trunc(sysdate)+18/24,
 repeat_interval => 'FREQ=MINUTELY;INTERVAL=2',
 end_date        => NULL,
 enabled         => TRUE,
 comments        => 'Job defined entirely by the CREATE JOB procedure.');
END;
/


quarta-feira, 23 de novembro de 2011

Tuning na Instruçao SQL LIKE no Oracle


Fala pessoal, vou postar aqui um dica simples, que é quando se precisa de um tunning rápido nas declarações "LIKE"  que o CBO naturalmente ignora os índices existentes nas colunas utilizadas pelo LIKE para uso de um FTS. Quando ocorre isso temos o recurso de utilizar um hint forçando a utilização do índice.

No Blog do Laurent Schneider tem um demo bem legal.
Abaixo a demonstração.

CREATE TABLE lsc_t AS
SELECT
  ROWNUM ID,
  SUBSTR(DBMS_RANDOM.STRING ('n', DBMS_RANDOM.VALUE (2, 8))
 || ' '
 || DBMS_RANDOM.STRING ('n', DBMS_RANDOM.VALUE (2, 8))
 ,1,17) NAME,
  TRUNC(SYSDATE-ABS(10000*DBMS_RANDOM.NORMAL)) birthdate,
  LPAD('X',4000,'X') address
FROM DUAL
CONNECT BY LEVEL <= 1e5;

ALTER TABLE lsc_t ADD PRIMARY KEY(ID);

CREATE INDEX lsc_i ON lsc_t(NAME);

EXEC dbms_stats.gather_table_stats(user,'LSC_T',cascade=>true);

SQL> SELECT ID, NAME, birthdate
  FROM lsc_t WHERE NAME LIKE '%ABC%';  2
---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |  5044 |   123K| 22123   (1)| 00:04:26 |
|*  1 |  TABLE ACCESS FULL| LSC_T |  5044 |   123K| 22123   (1)| 00:04:26 |
---------------------------------------------------------------------------

Statistics
----------------------------------------------------------
  379  recursive calls
    0  db block gets
  100090  consistent gets
  100016  physical reads
    0  redo size
    2066  bytes sent via SQL*Net to client
  491  bytes received via SQL*Net from client
    4  SQL*Net roundtrips to/from client
    5  sorts (memory)
    0  sorts (disk)
   35  rows processed

SWLQL> SELECT /*+INDEX(LSC_T,LSC_I)*/  ID, NAME, birthdate
  FROM lsc_t WHERE NAME LIKE '%ABC%';  2

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  5044 |   123K|  3574   (1)| 00:00:43 |
|   1 |  TABLE ACCESS BY INDEX ROWID| LSC_T |  5044 |   123K|  3574   (1)| 00:00:43 |
|*  2 |   INDEX FULL SCAN           | LSC_I |  5000 |       |   220   (2)| 00:00:03 |
-------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
    1  recursive calls
    0  db block gets
  360  consistent gets
  322  physical reads
    0  redo size
  142849  bytes sent via SQL*Net to client
  491  bytes received via SQL*Net from client
    4  SQL*Net roundtrips to/from client
    0  sorts (memory)
    0  sorts (disk)
   35  rows processed


segunda-feira, 21 de novembro de 2011

Habilitar DDL no alert.log Oracle

Fala pessoal, o 11g tem um recurso interessante que é habilitar o log de comandos DDLs no alert.log, para habilitar é bem simples basta alterar o parâmetro ENABLE_DDL_LOGGING para true, segue abaixo um pequeno step by step que altera o parâmetro e cria alguns objetos para teste.


COLUMN DESCRIPTION FORMAT A30
COLUMN VALUE FORMAT A30
SET LINESIZE 120

SQL> select value,isdefault,isses_modifiable, issys_modifiable,isbasic,description  
from v$parameter  where name='enable_ddl_logging';

VALUE  ISDEFAULT ISSES ISSYS_MOD ISBAS DESCRIPTION
------ --------- ----- --------- ----- -------------------
FALSE   TRUE    TRUE  IMMEDIATE FALSE enable ddl logging

SQL> alter system set ENABLE_DDL_LOGGING=true ;

System altered.

SQL> conn hudson/c402d92

Connected

SQL> create table t_hudson as select * from user_tables;

Table created.

SQL> grant select on t_hudson to public;

Grant succeeded.

SQL> alter table t_hudson read only;

Table altered.

SQL> drop table t_hudson ;

Table dropped.

Após a alteração do parâmetro vamos verificar se foi gerado o log no alert.log:


[oracle@rjhud trace]$ tail -f alert_centro.log

Mon Nov 21 15:58:43 2011
SMCO started with pid=31, OS id=5981
Mon Nov 21 16:08:37 2011
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=SPFILE;
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=BOTH;
Mon Nov 21 16:09:41 2011
create table t_hudson as select * from user_tables
Mon Nov 21 16:10:09 2011
alter table t_hudson read only
drop table t_hudson


Para maiores informações sobre o parâmetro é só consultar o link:

 http://download.oracle.com/docs/cd/E14072_01/server.112/e10820/initparams078.htm

sexta-feira, 18 de novembro de 2011

Exportar linhas sem dump ou backup no Oracle

Muitas vezes é necessário obter um número pequenos de linhas de algumas ou todas tabelas de um ambiente de produção, mas nem sempre um dump ou um backup esta disponível ou ainda o tempo de demora pode atrasar muito uma atuação, quem trabalha em consultorias, fabricas e qualquer lugar onde ambiente de produção é um lugar onde você não pode entrar em 1000 seguranças do seu lado sabe do que eu estou falando.
Então um meio muito utilizado é gerar "Inserts" concatenando via selects os famosos :

SELECT 'INSER INTO ..... '  || COLUMNS  .....
Dessa forma é possível obter os dados da tabela de uma forma simples e rápida, o problema é o tempo gasto na hora de gerar esses selects, principalmente se estamos falando de uma tabela com muitas colunas, ou se você precisa de muitas tabelas.
Pensando nisso eu fiz uma package que gera esses selects dinamicamente , recebendo como argumentos o nome de uma tabela com o número de linhas que deseja, ou passando diretamente um onwer e as linhas que precisa.
Óbvio que esse método só é útil quando precisa de um número pequeno de linhas e não tem em mãos outras ferramentas.

Abaixo o código de criação das packages :


CREATE OR REPLACE PACKAGE PKG_DUMP AS

  PROCEDURE P_DUMP(V_OWNER VARCHAR2,V_ROWS INT);
  FUNCTION V_DUMP(v_table_name VARCHAR2,V_ROWS INT) RETURN VARCHAR2;

END;
/
CREATE OR REPLACE PACKAGE BODY PKG_DUMP AS

PROCEDURE P_DUMP(V_OWNER VARCHAR2,V_ROWS INT)
IS
  V_SMT VARCHAR2(3000);
  V_TABLE_NAME VARCHAR2(100);
  CURSOR trip_cursor IS SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER=V_OWNER AND TABLE_NAME IN 
  ('ACTION','ROLE','ROLE_ACTION','URL','MENU');
BEGIN
  FOR trip_record IN trip_cursor LOOP
  SELECT V_DUMP(trip_record.TABLE_NAME,V_ROWS) INTO V_SMT FROM DUAL;
  V_TABLE_NAME := trip_record.TABLE_NAME;
  dbms_output.new_line();
  dbms_output.new_line();
  DBMS_OUTPUT.PUT_LINE('/************* ' || V_TABLE_NAME || '***************/');
  dbms_output.new_line();
  DBMS_OUTPUT.PUT_LINE(V_SMT);
  END LOOP;
--EXECUTE IMMEDIATE V_SMT ;
EXCEPTION
    WHEN OTHERS THEN
    PKG_ERR.PRC_HANDLE(-20001, 'Problems in P_DUMP  ' || V_TABLE_NAME );
END P_DUMP;

FUNCTION V_DUMP(v_table_name VARCHAR2,V_ROWS INT) 
RETURN VARCHAR2
IS

  v_column_name VARCHAR2(5000);
  v_column_name2 VARCHAR2(5000);
  v_column_name3 VARCHAR2(5000);
  v_column_name4 VARCHAR2(5000);
  v_column_name5 VARCHAR2(5000);
  V_SMT VARCHAR2(5000);
   
  CURSOR trip_cursor IS SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME=v_table_name ORDER BY COLUMN_ID;

BEGIN

  FOR trip_record IN trip_cursor LOOP
  v_column_name2 := trip_record.column_name ;
  v_column_name := v_column_name || ',' || v_column_name2;

  END LOOP;
  SELECT REGEXP_REPLACE(v_column_name, ',' , '' ,1,1)  into v_column_name3 FROM DUAL;
  --SELECT REGEXP_REPLACE(v_column_name, ',' , '|| '',''||' ,2) into v_column_name4 FROM DUAL;
  SELECT REGEXP_REPLACE(v_column_name, ',' , '|| '''''''' || '',''||'''''''' ||' ,2) into v_column_name4 FROM DUAL;
  SELECT REGEXP_REPLACE(v_column_name4, ',' , ',''''||''''''''||' ,1,1)  into v_column_name5 FROM DUAL;
  --DBMS_OUTPUT.PUT_LINE(v_column_name);
  V_SMT:= ' SELECT ''INSERT INTO ' || v_table_name || ' ( ' || v_column_name3 || ' ) VALUES (''' || v_column_name5
  || '||'''''''' ||'');''  FROM ' || v_table_name || ' WHERE ROWNUM < ' || V_ROWS || ';';
  --EXECUTE IMMEDIATE V_SMT ;
  --DBMS_OUTPUT.PUT_LINE(V_SMT);
  RETURN V_SMT;
EXCEPTION
    WHEN OTHERS THEN
    PKG_ERR.PRC_HANDLE(-20001, 'Problems in V_DUMP  ' || v_table_name );
END V_DUMP;
END PKG_DUMP;
/
Agora as formas de Utilizar a package, a primeira forma é gerar o insert de apenas uma tabela. Primeiro executando a function PKG_DUMP.V_DUMP passando o nome da tabela e depois o número de linhas.
new@ORACLE> SELECT PKG_DUMP.V_DUMP('TESTE',29) FROM DUAL;
 SELECT 'INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (',''||''''||X|| '''' || ','||'''' ||C|| '''' || ','||'''' ||H|| '''' || ','||'''' ||G|| '''' || ','||'''' ||HG||'''' ||');'  FROM TESTE WHERE ROWNUM <
 29;
Após o resultado executa o select gerado e já se tem o insert pronto.
new@ORACLE>  SELECT 'INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (',''||''''||X|| '''' || ','||'''' ||C|| '''' || ','||'''' ||H|| '''' || ','||'''' ||G|| '''' || ','||'''' ||HG||'''' ||');'  FROM TESTE WHERE ROWNUM <
 29;  2
INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'1','2','1','1','A');

INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'4','5','1','1','A');

INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'4','5','1','1','A');
A outra forma é tendo todas as tabelas, executando a procedure PKG_DUMP.P_DUMP passando o owner e o número de linhas:
new@ORACLE> set pagesize 0
set long 90000
set linesize 200
set trimspool ON
set feedback off
set echo off 

new@ORACLE>EXECUTE PKG_DUMP.P_DUMP('NEW',100);
Ele vai gerar o output de todos os selects para geraçao de inserts de todas as tabelas que esse owner possui, é aconselhável utilizar um spool para receber esse conteúdo.

That's all folks 

quarta-feira, 24 de agosto de 2011

Descobrindo o DBID quando o banco esta em nomount

Fala pessoal, uma situação chata mas que pode acontecer é recuperar os controlfiles depois de alguma perda. Se você não usa a FRA para uma recuperação automática dos controlfiles com o rman, você vai precisar setar o DBID e o control-file autobackup location manualmente.
Mas ai que mora a questão, se seu banco não esta aberto e você não tem o DBID anotado, como descobrir ele ??
Então vamos a boa dica :

Primeira coisa vamos logar no rman:

[oracle@rjhud ~]$ rlwrap rman target=sys/c402d92@centro

Recovery Manager: Release 11.2.0.1.0 - Production on Wed Aug 24 11:46:23 2011

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

connected to target database (not started)

RMAN>


Agora que começa o legal da história , precisamos descobrir o DBID e como o banco não esta montado não iremos conseguir acessar a V$DATABASE então o que vamos fazer, vamos no diretório onde os backups estão armazenados ou no diretório dos datafiles e vamos fazer a seguinte busca atraves do comando strings do sistema operacional.
Os comandos vão variar para o tipo de backup que você vai pesquisar, se é um backup do datafile system ou undo ou um backupset.

strings file_name |grep MAXVALUE, (No caso do SYSTEM datafile or FULL Backup)
strings file_name |grep MAXVALUE (No caso do UNDO datafile )

Exemplos :

[root@rjhud backup2]# ls -lh

-rw-r----- 1 oracle oinstall 972K Aug 23 16:42 01mknoqp_1_1_TAGBACKUP_FULL
strings 01mknoqp_1_1_TAGBACKUP_FULL |grep MAXVALUE,

1287652985, MAXVALUE,

Esse é o meu DBID :1287652985

Agora é só seguir a sequencia para restaurar o controlfile e da próxima vez mantenha o seu DBID guardado em uma planilha ou repositório qualquer.

That's all folks

quarta-feira, 3 de agosto de 2011

ORA-16179: incremental changes to "log_archive_dest_1" not allowed with SPFILE

Estava agora configurando uma base nova, antes de passar ela para ARCHIVELOG no momento que estava configurando o diretório dos archives recebi o famoso:


SQL> Alter system set log_archive_dest_1='/u01/app/oracle/archives/iraja';

ORA - 16179 : incremental changes to "log_archive_dest_1" not allowed with

Meu cenário era um Oracle Database 11G R2 com um Red Hat 5.5.

A Solução é bem simples galera e eu achei no metalink que tem o Doc ID: 194494.1.
Só adicionar a palavra LOCATION antes do caminho do diretório.


SQL> ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=/u01/app/oracle/archives/iraja' ;

System altered.


That's all folks

terça-feira, 2 de agosto de 2011

Problema com DISPLAY no VirtualBox com Oracle

Post simples e com muito conteúdo na Internet, mas que de vez em quando me dava trabalho e eu não vi/não achei nada tão simples na internet.
Problema :

>>> Could not execute auto check for display colors using command /usr/bin/xdpyinfo. Check if the DISPLAY variable is set. Failed <<<<

Cenário:
VirtualBox 4.4 Instalando o Oracle Database 11G R2

Soluçao :
Como root executar :
xhost +localhost

Depois loga com o oracle na mesma sessão e zaz(Como diria o chaves).

That's all folks !!

segunda-feira, 1 de agosto de 2011

Recuperando Variável Bind com a V$SQL_BIND_CAPTURE

Segue abaixo uma forma bem simples de pegar o valor de uma variável bind utilizando a view V$SQL_BIND_CAPTURE . Precisei recentemente pegar os valores de uma consulta que uma sessão estava realizando e o trace não estava ajudando por "n" fatores e utilizando o velho dicionario de dados foi bem mais simples nesse caso.

1_ Buscando o valor o sql_id na V$SQL :

SELECT SQL_ID,SQL_TEXT FROM V$SQL WHERE SQL_TEXT LIKE '%all_tab_columns%';

SQL_TEXT SQL_ID
---------------------------------------- -------------
select col.*, com.Comments from sys.all_ 032n4avhdnaz3
tab_columns col, sys.all_col_commen
WHERE o.owner LIKE :1 ESCAPE '/'
AND o.object_name LIKE 2: ESCAPE '/'


Atenção a identificação das binds , essa mesma posição vai ser recuperada logo a frente.

2_ Olhando a V$SQL_BIND_CAPTURE

SQL>
 desc V$SQL_BIND_CAPTURE

Name Null? Type
----------------------------------------------------------------- -------- --------------------------------------------
ADDRESS RAW(8)
HASH_VALUE NUMBER
SQL_ID VARCHAR2(13)
CHILD_ADDRESS RAW(8)
CHILD_NUMBER NUMBER
NAME VARCHAR2(30)
POSITION NUMBER
DUP_POSITION NUMBER
DATATYPE NUMBER
DATATYPE_STRING VARCHAR2(15)
CHARACTER_SID NUMBER
PRECISION NUMBER
SCALE NUMBER
MAX_LENGTH NUMBER
WAS_CAPTURED VARCHAR2(3)
LAST_CAPTURED DATE
VALUE_STRING VARCHAR2(4000)
VALUE_ANYDATA ANYDATA

3_Buscando o valor da bind desejada :

SQL_ SELECT NAME,TO_CHAR(LAST_CAPTURED,'DD/MM/YYYY HH24:MI:SS'),VALUE_STRING FROM V$SQL_BIND_CAPTURE WHERE SQL_ID='0prhvnya3f97z' ;

NAME TO_CHAR(LAST_CAPTUR VALUE_STRING
------------------------------ ------------------- ------------------------------
:1 01/08/2011 16:24:39 REPORT_SERVER_AALTAMIRANO
:2 01/08/2011 16:24:39 ROLE
Pronto, de forma simples foi recuperado os valores passados no filtro da consulta SQL.

terça-feira, 26 de julho de 2011

GUOB Tech Day 2011 - Minha Visão !

Revigorante, essa é a palavra que pra mim traduziu o GUOB Tech Day 11. Sabe quando você precisa respirar novos ares, conhecer novas tendências e buscar inspiração mesmo para seguir na nossa “batalha” diária ? Então o GUOB forneceu esse conteúdo para todos os presentes.

As Palestras foram de alto nível, a começar pela parte da manhã com as palestras internacionais, dentre todas destaco a palestra do Pablo Ciccarello que apresentou a OTN de uma forma que muitos não conheciam com um ótimo conteúdo técnico e espaço para divulgação, e as palestras do Arup Nanda e a do Graham Wood nas quais ambos falaram de Exadata, o Graham Wood conseguiu mostrar em minutos o porquê que o Exadata tem essa fama, vou usar a frase do Rodrigo Almeida para descrever o que ele fez:

“...1 hora de palestra e uma VPNzinha consegue montar um Data Warehouse de 1 TB ao vivo, direto de uma Oracle Exadata X2-2 e carregar 8 bilhões de registros ...”

E na palestra do Arup Nanda ele simplesmente desmitificou o Exadata e deu o caminho das pedras para qualquer DBA conseguir se tornar um DMA (Database Machine Administrator).

Na parte da tarde eu assisti as duas palestras do Kai yu na qual ele deu um show em boas praticas para RAC e deu um belo overview sobre virtualização de RAC utilizando a Oracle VM, me deu motivações suficiente para testar a Oracle VM e talvez largar o VMWare.

Assisti também a concorrida palestra do Rodrigo Mulafani sobre certificações e a do Thomas Glufke sobre EBS.

E pra finalizar assisti a uma das melhores palestras do dia do Arup Nada sobre Boas praticas para DBAs.

O Evento pelo seu conteúdo técnico foi um dos melhores que eu já fui, e falando de Oracle com certeza o melhor, como disse o Ricardo Portilho não tenho saco para o Oracle Open World com seu conteúdo quase que todo para Gerentes.

O Evento foi ótimo para fazer, fortalecer e ampliar o networking, ele contou com presença dos maiores Blogueiros de Oracle do País tais como Rodrigo Almeida, Ricardo Portilho ( Que eu já conhecia porque fiz o ótimo curso de RAC na nerv com ele), Eduardo Legatti, David Ricardo e quase todos donos de blogs que com certeza já te ajudaram ou que você achou algum conteúdo interessante em algum momento. Nesse ponto eu falhei por ter ido sozinho para o evento e falando no popular, “dei mole” nesse requisito, mas fica a dica pro próximo: Conheça e fale com todo mundo e não vá sozinho, mas e for não tem problema.

Pra finalizar acho mais que justo agradecer ao Eduardo Hahn, presidente do GUOB, que com certeza deve ter ficado bem orgulhoso do resultado final do evento e parabenizar todas as pessoas que ajudaram pra realizar esse Evento.

Abaixo tem a cobertura de outros blogs, é legal quem não foi ler para observar a visão das pessoas que foram e no Final tem o link do GUOB para o download das palestras, tem que realizar um cadastro e fazer a associação ao grupo (Relaxa é Free) e se eu você fosse eu com certeza faria o download das palestras.

Cobertura

Ricado Portilho:

http://itweb.com.br/blogs/guob-tech-day-2011-eu-fui/

Rodrigo Almeida:

http://www.rodrigoalmeida.net/blog/resumo-guob-tech-day-2011

Mauro Pichiliani:

imasters.com.br/artigo/21478/outros/cobertura-do-guob-tech-day-2011

Alessandro Guimarães:

http://aguimaraes.wordpress.com/2011/07/23/guob-2011-comentarios-feedbacks-e-impressoes/

Eduardo Legatti:

http://eduardolegatti.blogspot.com/2011/07/minha-experiencia-no-guob-tech-day-2011.html

William do Carmo:

http://aprenderoracle.com/2011/07/review-do-evento-guob-2011/

Paulo Henrique:

http://phpdba.wordpress.com/2011/07/22/guob-tech-day-2011-attendant-feedback/

Fernando Franquini:

http://franquini.wordpress.com/2011/07/17/guob-tech-day-2011/

Leandro Lana:

http://leandrolana.blogspot.com/2011/07/guob-tech-day.html

Rodrigo Almeida:

http://www.rodrigoalmeida.net/blog/resumo-guob-tech-day-2011

Palestras:

http://www.guob.com.br

terça-feira, 14 de junho de 2011

GUOB Tech Day 2011


Agende-se para mais este grande evento organizado pelo GUOB com apoio do LAOUC e OTN. Acontecerá no dia 16/07/2011,sábado, em São Paulo no Hotel Blue Tree Morumbi, a edição 2011 do grande encontro de usuários de tecnologia Oracle do Brasil com a participação de palestrantes internacionais e nacionais.
Este ano contamos com a presença de Arup Nanda, Graham Wood, Debra Lilley, Kay Yu, Hans Forbrich e Francisco Munoz.
Aproveite esta grande oportunidade de estar próximo de grande autores e referências em tecnologia Oracle no mundo.
Faça sua associação gratuita ao GUOB através da opção no menu ASSOCIE-SE em nosso site. Você poderá ser o ganhador de um dos 3 convites para associados ao GUOB para um almoço com os palestrantes durante o GUOB TECH DAY 2011.
Participem e divulguem o evento.
Acesse nosso site para maiores informações. GUOB TECH DAY 2011.
GUOB - Grupo de Usuários de Tecnologia Oracle do Brasil

quinta-feira, 19 de maio de 2011

Matar job do Datapump Oracle

Pessoal vou passar um dica, quando se precisa matar um job do datapump. Quando você esta executando o export ou import do datapump, nao basta dar Control-C para parar esse job, quando se faz isso apenas pausa o job, em alguns casos nem isso. Vou listar o Procedimento para eliminar realmente o Job.

 1) Verifique as informações para eliminação do job.
SELECT OWNER_NAME,JOB_NAME FROM DBA_DATAPUMP_JOBS;
2) Saia do sqlplus e entre no datapump novamente com o commando abaixo:
impdp username/password@database attach=nome_do_job
3) Elimine o job com o commando :
$ Import>kill_job
Are you sure you wish to stop this job (y/n): y
4) Verifique se o job realmente foi eliminado
SELECT OWNER,JOB_NAME FROM DBA_DATAPUMP_JOBS;

sexta-feira, 13 de maio de 2011

Gerar Schema (DDL) no Oracle sem Datapump ou Exp


Vou disponibilizar um script que fiz, para situações que voce precisa exportar um schema só com ddl e sem os dados.
Ok, o datapump e o exp podem fazer isso perfeitamente, mas existem situações onde você não tem acesso a essas ferramentas e/ou nao pode esperar o DBA do cliente disponibilizar isso para voce.
Além disso esse script não traz nenhuma definição de tablespace, armazenamento,ele separa a criação de constraints para o final, podendo ser executado novamente para a criação do schema depois direto, sem se preocupar com a ordem da criação dos objetos em relação a integridade.
Ele também exporta procedures,triggers,sequences,views .
Enfim uma mão na roda quando não se tem acesso a quase nada e precisa de informações em tempo rápido.
Para acessar o link, va no meu outro blog, lá o código esta formatado .
-- Comments and Script Documentation
-- Script Name   : extract_schema_ddl.sql
-- Requirements  : User calling script must be owner the objects, and have privileges the package
     DBMS_METADATA. 
-- Author        : HUDSON SANTOS
-- Created Date  : 05/05/2011


set pagesize 0
set long 90000
set linesize 32767
set trimspool ON
set feedback off
set echo off 
column txt format a121 word_wrapped

BEGIN
dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 'PRETTY', TRUE );
dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', false );
dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE );
dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', false ); 
dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 'REF_CONSTRAINTS',false);
END;
/


spool schema.sql 

-- TABELAS

SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name) txt
     FROM USER_TABLES u ;

-- CONSTRAINTS R1

SELECT DBMS_METADATA.GET_DDL('CONSTRAINT',u.constraint_name) txt
     FROM USER_constraints u WHERE CONSTRAINT_TYPE IN ('P','C');

-- CONSTRAINTS R2

SELECT DBMS_METADATA.GET_DDL('REF_CONSTRAINT',u.constraint_name) txt
     FROM USER_constraints u WHERE CONSTRAINT_TYPE IN ('R');

-- INDICES 
SELECT DBMS_METADATA.GET_DDL('INDEX',u.index_name) txt
     FROM USER_INDEXES u ;

-- TRIGGERS

SELECT dbms_metadata.get_ddl('TRIGGER', u.trigger_name) txt
 FROM USER_TRIGGERS u;

-- PROCEDURES

SELECT dbms_metadata.get_ddl('PROCEDURE', u.object_name) txt
 FROM USER_objects u WHERE OBJECT_TYPE='PROCEDURE' ;

-- FUNCTIONS

SELECT dbms_metadata.get_ddl('FUNCTION', u.object_name) txt
 FROM USER_objects u WHERE OBJECT_TYPE='FUNCTION' ;

-- SEQUENCES

SELECT dbms_metadata.get_ddl('SEQUENCE',u.SEQUENCE_NAME) txt
 FROM USER_SEQUENCES u;

-- VIEWS

SELECT dbms_metadata.get_ddl('VIEW',u.VIEW_NAME) txt
 FROM USER_VIEWS u;

-- VIEW_MATERIALIZED

SELECT dbms_metadata.get_ddl('MATERIALIZED_VIEW',u.MVIEW_NAME) txt
 FROM USER_MVIEWS u;

--PACKAGE

SELECT dbms_metadata.get_ddl('PACKAGE',u.object_name) txt
 FROM USER_OBJECTS u WHERE OBJECT_TYPE='PACKAGE';

--PACKAGE_BODY

SELECT dbms_metadata.get_ddl('PACKAGE_BODY',u.object_name) txt
 FROM USER_OBJECTS u WHERE OBJECT_TYPE='PACKAGE_BODY';


spool off;


quinta-feira, 7 de abril de 2011

Métodos de Joins no Oracle Parte III


HASH JOIN
Os dois conjuntos de dados processados por um Hash Join são chamados de build input e probe input. A build input é a esquerda, e a probe input é a entrada à direita. Como ilustrado na Figura abaixo, usando cada linha da entrada da build input, uma tabela hash na memória (ou espaço temporário, se não há memória suficiente está disponível) é construída.
Observe que a chave de hash usada para esse fim é calculada com base nas colunas usadas como condição de join. Uma vez que a tabela hash contém todos os dados do build input, o processamento da probe input começa.
Cada linha é testada contra a tabela hash, a fim de descobrir se ele cumpre a condição de join. Obviamente, apenas registros coincidentes são retornados.


                * Visão do processo de um Hash Join

Hash Joins são caracterizados pelas seguintes proriedades :
·         Cada operação Filha só é executada uma vez
·         A tabela hash é construída sobre a entrada da esquerda. Por conseqüência , é geralmente construída na menor entrada.
·         Antes de retornar a primeira linha, somente a entrada deesquerda deve ser totalmente processado.
·         Cross joins, theta joins e partitiouned outer joins não são suportados.
Exemplo de Hash Join.
O exemplo a seguir é um simples plano de execução mostrando o processamento de um Hash Joins entre duas tabelas, O exemplo também mostra como forçar uma hash join por meio das dos hints leading  e use_hash.

SQL_IRAJA  > SELECT /*+ leading(t1) use_hash(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n = 19
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    10 |  1180 |    30   (4)| 00:00:01 |
|*  1 |  HASH JOIN         |      |    10 |  1180 |    30   (4)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| T1   |     1 |    57 |     5   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |   100 |  6100 |    24   (0)| 00:00:01 |
---------------------------------------------------------------------------

   1 - access("T1"."ID"="T2"."T1_ID")
   2 - filter("T1"."N"=19)

 O processamento do plano de execução pode ser resumido da seguinte forma  :

·         Todas as linhas da tabela t1 são lidas através de um full table scan, a restrição n = 19 é aplicada, e uma tabela de hash é construído com as linhas resultantes.  Para construir a tabela de hash, uma função hash é aplicada para as colunas usadas na condição de join (id).
·         Todas as linhas da tabela T2 são ligas através de um full table scan, uma função hash é aplicada para as colunas usadas na condição de join (t2_id) e a tabela de hash entra no modo probed. Se for encontrado os dados correspondentes as linhas são retornadas

A limitação mais importante para a operação HASH JOIN (como para as outras operações combinadas não relacionadas) é a incapacidade de tirar proveito dos índices para aplicar nas condições de join. Isto significa que os índices podem ser utilizados como caminho de acesso somente se as restrições estão disponíveis. Por exemplo, se a restrição n = 19 fornece boa seletividade, pode ser útil para criar um índice para aplicá-la.

SQL_IRAJA > CREATE INDEX t1_n ON t1 (n)

In fact, with this index in place, the following execution plan might be used. Note that the
table t1 is no longer accessed through a full table scan.

Na verdade, com esse índice em vigor, o plano de execução a seguir pode ser usado. Observe que a tabela t1 já não é mas acessada através de um full table scan.

-------------------------------------------------------------------------------------                                                                                                                                                          
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                          
-------------------------------------------------------------------------------------                                                                                                                                                          
|   0 | SELECT STATEMENT             |      |    10 |  1180 |    27   (4)| 00:00:01 |                                                                                                                                                           
|*  1 |  HASH JOIN                   |      |    10 |  1180 |    27   (4)| 00:00:01 |                                                                                                                                                           
|   2 |   TABLE ACCESS BY INDEX ROWID| T1   |     1 |    57 |     2   (0)| 00:00:01 |                                                                                                                                                           
|*  3 |    INDEX RANGE SCAN          | T1_N |     1 |       |     1   (0)| 00:00:01 |                                                                                                                                                           
|   4 |   TABLE ACCESS FULL          | T2   |   100 |  6100 |    24   (0)| 00:00:01 |                                                                                                                                                           
-------------------------------------------------------------------------------------                                                                                                                                                           
                                                                                                                                                
   1 - access("T1"."ID"="T2"."T1_ID")                                                                                                                                                                                                          
   3 - access("T1"."N"=19)