MigraTI - Soluções em banco de dados

terça-feira, 10 de agosto de 2010

PL/SQL: Item ignored, PLS-00201, PLS-00302, ORA-06550

Pensa no quanto apanhei para descobrir que códigos PL/SQL não encontra OWNER dentro das aplicações.

Procedimento abaixo mostra como a solução é simples para quando um código PL não encontra objetos do próprio schema.

CREATE TABLE lana.user1 (x NUMBER);

Table created


DECLARE
x lana.user1.x%TYPE;
BEGIN
NULL;
END;

ORA-06550: line 3, column 12:
PLS-00302: component 'LANA' must be declared
ORA-06550: line 3, column 6:
PL/SQL: Item ignored


CREATE OR REPLACE SYNONYM LANA FOR LANA.LANA;

Synonym created


DECLARE
x lana.x%TYPE;
BEGIN
NULL;
END;
/

PL/SQL procedure successfully completed


Desde já agradeço.

domingo, 18 de abril de 2010

Alterando alguns dados do Enterprise Manager

Me deparei com um problema esta semana.
O cliente alterou a porta do listener do db dele e utilizou a mesma porta para outro banco.
Mas como o EM vai funcionar? Precisa alterar a porta dele também.
Para você alterar existe uma solução mais classica do que recriar o repositório todo.

No diretório $ORACLE_HOME/$HOSTNAME_$ORACLE_SID/sysman/emd/
altere o arquivo target.xlm la vai ter uma linha com a porta do listener.

property NAME="Port" VALUE="1521"/


Facil,rapido e seguro.

Evitando disputa de IO em disco.

Bom estou empenhado em entender melhor os niveis de performance, então logicamente posso começar a postar varias dicas sobre este topico =].

Hoje vou escrever algo bem interessante e facil de se aplicar em qualquer ambiente.

Bem como qualquer DBA sabe é sempre criar os datafiles de indices e dados em locais/discos diferentes, para melhorar o IO mais balanceado.

Não basta apenas dividirmos os dados dos indices, vamos selecionar os datafiles com mais IO e assim conseguiremos analisar quais datafiles precisam trocar de lugar.

Segue select abaixo:
col name for a60
select name,PHYRDS,PHYWRTS,READTIM,WRITETIM
from v$filestat a, v$dbfile b
where a.file#=b.file#
order by READTIM desc;


NAME PHYRDS PHYWRTS READTIM WRITETIM
------------------------------------------------------------ ---------- ---------- ---------- ----------
/u01/app/oracle/oradata/lana/system01.dbf 1377 6 2248 0
/u01/app/oracle/oradata/lana/sysaux01.dbf 130 49 213 30
/u01/app/oracle/oradata/lana/undotbs01.dbf 67 26 44 16
/u01/leolana1.dbf 5 2 11 0
/u01/app/oracle/oradata/lana/lana_LOB.DBF 5 2 11 3
/u01/app/oracle/oradata/lana/users01.dbf 5 2 6 0
/u01/app/oracle/oradata/lana/TEIKO.dbf 5 2 4 0


Uma grande diferença no número de escritas e leitura fisica entre os discos mostra quando o disco esta sendo sobrecarregado.
Observe que o filesystem "/u01/app/oracle/oradata/lana/system01.dbf" tem muitas leituras logicas mas tem poucas leitura/gravações fisicas, no caso não esta gerando IO.
Quanto mais leituras fisicas mais IO.

Esses números mostram que o banco ganharia performance de IO se dividissemos os filesystem dos datafiles system,sysaux e undo.

logicamente os esses números são inexpressivos pois base de teste não são muito utilizados.
Esses valores podem fazer uma grande diferença em bancos de produção.

[]'s

segunda-feira, 22 de março de 2010

Unamed Files.

ORA-00283: recovery session canceled due to errors
ORA-01111: name for data file 192 is unknown - rename to correct file
ORA-01110: data file 192: '/orastb01/app/oracle/product/9.2.0/dbs/UNNAMED00192'
ORA-01157: cannot identify/lock data file 192 - see DBWR trace file
ORA-01111: name for data file 192 is unknown - rename to correct file
ORA-01110: data file 192: '/orastb01/app/oracle/product/9.2.0/dbs/UNNAMED00192'
ORA-06512: at line 12


Este erro pode ocorrer caso o parametro "standby_file_management" não estiver parametrizado como "auto".

caso isso ocorrer em algum servidor de standby vc deve seguir os seguintes passos.

############################################
# fazer select na maquina de produção. #
############################################

select file_name,file_id from dba_data_files where file_ID=192;
--Observe que o número do file_id esta no final do arquivo de standby. "UNNAMED00192"

FILE_NAME FILE_ID
------------------------------------------------------------ ----------
/oraprd04/oradata/prod/TESTE01.dbf 192




######################################################################
# Ao descobrir o arquivo basta executar o comando abaixo no standby. #
######################################################################

SQL> alter database create datafile '/orastb01/app/oracle/product/9.2.0/dbs/UNNAMED00192' as '/orastd04/oradata/prod/TESTE01.dbf';

Database altered.


Efetuar shutdown no banco de standby
e executar novamente a atualização.

Caso o paremetro standby_file_management estiver como auto, verifique se você não esta utilizando alguns parametros de conversão de nome "db_filename_convert" provavelmente não há as entradas necessárias para este novo datafile.
caso isso ocorrer você deve retirar o parametro de standby_file_management do pfile efetuar o procedimento acima e adicionar os devidos caminhos no db_filename_convert, conforme abaixo.

db_filename_convert='/oraprd04/','/orastd04/'

Qualquer duvida comente abaixo.

terça-feira, 16 de março de 2010

EXP-00079

Este erro pode ocorrer apenas em Oracle Enterprise edition.

Mas é simples de resolver.

ERRO:
EXP-00079: Data in table "NOMEDATABELA" is protected. Conventional path may only be exporting partial table.

Solução:
SQL> grant exempt access policy to OWNER_DO_BACKUP;

segunda-feira, 25 de janeiro de 2010

ORA-01704: string literal too long

Tae hoje apanhei neste problema simples. =]

Então como minha decisão de criar este blog ser para catalogar conhecimento proprio decidi escrever aqui a solução para nunca mais esquecer.

Um campo long deveria permitir que você insira mais de 4000 caracteres, porem se vc tentar isto no sqlplus você irá receber este erro em tela.

ORA-01704: string literal too long

Conforme abaixo.

SQL> CREATE TABLE LANA.TESTE_LONG (
2 nr_linh NUMBER(5,0) NOT NULL,
3 ds_linh LONG NULL
4 );

Table created.

SQL> Insert into LANA.TESTE_LONG values ( 1,
2 '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
4 ...
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
39 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000');
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
*
ERROR at line 2:
ORA-01704: string literal too long

SQL> SELECT COUNT(*) FROM LANA.TESTE_LONG;

COUNT(*)
----------
0


Para resolver este erro sugiro jogar o campo long para dentro de uma variavel e fazer o insert com a variavel conforme abaixo.


SQL> declare
2 ww_TEXTO LONG;
3
4 BEGIN
5
6 ww_texto :=
7 '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
8 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
9 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
10
...
41 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
42 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
43 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
44 45
46
47
48 Insert into LANA.TESTE_LONG values (
49 2,
50 Ww_texto
51 );
52 end;
53 /

PL/SQL procedure successfully completed.

SQL> SELECT COUNT(*) FROM LANA.TESTE_LONG;

COUNT(*)
----------
1

SQL>

segunda-feira, 18 de janeiro de 2010

Jobs

Vou começar a postar algumas coisas sobre job's conforme vou me lembrando vou editando este post.

Desde já agradeço.

Para forçar a execução de algum job.
exec dbms_job.run(numero do job);

Para remover um job.
exec dbms_job.remove(numero do job);

Para colocar um job em Broken.
exe DBMS_JOB.BROKEN(numero do job,true);

Para retirar um job em broken.
exe DBMS_JOB.BROKEN(numero do job,false);
-- Aconselho a forçar a execução do mesmo.


Para alterar um job completo.
DBMS_JOB.CHANGE (
job IN BINARY_INTEGER,
what IN VARCHAR2,
next_date IN DATE,
interval IN VARCHAR2,
instance IN BINARY_INTEGER DEFAULT NULL,
force IN BOOLEAN DEFAULT FALSE);

-- Aconselho a utilizar o script abaixo.

Para recriar um job a partir de outro job.
set line 155
set feedback off
set pagesize 0
select 'DECLARE ' || CHR(10) || ' JOBNO INTEGER; ' || CHR(10) || ' BEGIN ' ||
CHR(10) || ' DBMS_JOB.SUBMIT(JOBNO, ''' || replace(WHAT,'''','''''') || ''',' || CHR(10) ||
'to_date('''|| to_char(next_date,'DD/MM/YYYY HH24:MI:SS') ||''',''DD/MM/YYYY HH24:MI:SS'')'||',' || CHR(10) || '''' || INTERVAL || ''');' || CHR(10) ||
'END;' || CHR(10) || '/'
from dba_jobs where log_user = upper('&log_user');
set line 132
set feedback on
set pagesize 14
/


Para alterar o what de um job.
exec DBMS_JOB.WHAT(numero do job,'novo what');


Para alterar a instance de um job.
exec DBMS_JOB.INSTANCE(numero do job,'instance');


Lembrando que todos os comandos foram escritos como se você fosse o dono do job.
Caso você não seja o dono do job você terá de efetuar a seguinte sintaxe.
exec sys.dbms_ijob.comando...
exemplo:
exec sys.dbms_ijob.run(numero do job);


Conforme comentei acima. Se eu for lembrando de outros comandos vou editando este post.

Desde já agradeço.

quarta-feira, 13 de janeiro de 2010

Export em Memória.

Bom desde que eu resolvi descrever meus conhecimentos aqui no blog eu tinha em mente um dia escrever esta tecnica q por sinal nos ajuda e muito resolver problemas em ambientes que não tenham espaço em disco.

Como a correria do dia a dia esta complicado encontrar tempo de descrever corretamente todos os passos. Então vou pegar emprestado os passos do rafael Stoever para não ter de digitar tudo, até o porque aprendi esta tecnica mais a fundo lendo este artigo do blog dele. Segue abaixo o post completo, caso você queira ler o post direto da fonte clique aqui

Bom uma prática do tempo do Unix 32bits na hora de fazer export ou import utilizar um recurso para descompactar ou partir os arquivos na hora que eles estao sendo criados. É +/- isso ai mesmo.
No momento que tais fazendo um exp system/senha full=y file=/backup/expfull.dmp este arquivo pode mtas vezes ter centenas de gigas, mas compactados podem ficar com pequenos megas.
Bom muito DBA nos seus scripts de backup no Linux ou Unix fazem esse export e dps passam um gzip expfull.dmp para compactar ai mora outro problema, o gzip compacta mas se o arquivo dmp ficou com 20Gb e o .gz for ficar 4Gb no total vai ter que ter pelo menos de espaco livre uns 24,5Gb para essa maratona toda ai.....
Mas como eu estava dizendo há uma forma mais simplificada nisso tudo ai, como o unix ou linux todos os arquivos sao concatenados, é o termo nao é bem esse mas é algo assim, entao no momento q estou criando um arquivo posso estar pegando a informacao de dentro dele e jogando para outro lugar.
bom para nao enrolar mto vou fazer um exemplo que ficará mais fácil de enteder.

1. Tens que criar um arquivo temporario, é .... aquele que eu disse que vai ser alimentado mas vai ser jogado o seu conteudo para outro
[oracle@localhost oracle] mknod /tmp/exp_pipe p # criando um arquivo para o export
[oracle@localhost oracle] gzip < /tmp/exp_pipe > /backup/expfull.dmp.gz & # gzip recebendo a informacao do exp_pipe e a saida do gzip está sendo para /backup/expfull.dmp.gz já compactado e o & quer dizer em segundo plano
[oracle@localhost oracle] exp system/senha full=y file=/tmp/exp_pipe log=/backup/expfull.log # aqui o export vai jogar as informacoes para o exp_pipe onde o gzip que está em segundo plano esperando estas para compactar.

Não há necessidade de matar o gzip pois ele fica em segundo plano, no momento que termina o export o gzip finaliza o export e ai está o seu export de 20Gb já saiu compactado em 4Gb.
Ok pode perder um pouco de performace pois será dois processos de arquivos no servidor mas nao será tao problemático em questão de espaco.

E em relação a importar esse gzip, nao há necessidade de descompactar e dai fazer o import, vou colocar somente o código e dai com a explicação anterior já irão induzir o que ele está fazendo.

[oracle@localhost oracle] mknod /tmp/imp_pipe p
[oracle@localhost oracle] gzip -d < /backup/expfull.dmp.gz > /tmp/exp_pipe &
[oracle@localhost oracle] imp system/senha full=y file=/tmp/exp_pipe log=/backup/impfull.log fromuser=deUsuario touser=paraUsuario

Obs.: O ideal depois de compactar usando esse recurso se certificar que o arquivo está ok, como foi usado o gzip posso recomendar o seguinte comando:
gunzip -t /backup/expfull.dmp.gz ; RC=$?
if test ${RC} -ne 0
then
# aqui vc fazer um comando mail para enviar um email para o DBA dizendo que o backup falhou
fim