BLOG RODRIGO ALMEIDA

Administração

Básicas diferenças entre Oracle e SQL Server discutido no site stackoverflow.com

by Rodrigo Almeida on fev.25, 2010, under Administração

Olá,

Acompanhando o twitter do Eddie Awad, ele postou um link super interessante sobre básicas diferenças entre o Oracle Server e MS SQL Server, vale a pena dar uma olhada e analisar os pontos que um DBA que trabalha com ambas bases de dados descreveu como fundamentais.

O link para acompanhar a discussão está aqui: Basic Differences between Oracle and SQL Server.

Quem tiver mais sugestões, dúvidas e ideias, vamos comentando abaixo.

Abraços,

  • Share/Bookmark
3 Comments :, , , , , , more...

Técnica de hack em senhas armazenadas pelo Oracle

by Rodrigo Almeida on fev.05, 2010, under Administração

Olá,

Uma das táticas mais “sujas”, diga-se de passagem, é a alteração de senha do usuário sem a sua permissão, pois pode ocorrer em diversos momentos do dia-a-dia, por exemplo:

  • O cara saiu de férias, é deixou algum objeto no owner dele.
  • Preciso pegar algumas informações da tabela do FULANO.
  • É necessário fornecer algumas permissões do usuário X para Y.
  • Ou a MELHOR! Existe um owner na aplicação que foi criado em 1900 e bolinhas, e agora, precisa de manutenção e ninguém tem acesso a esse usuário, porque ninguem sabe a senha.

Bom, para resolver esses “probleminhas”, existe uma técnica no Oracle que podemos utilizar para ter acesso completo a um específico usuário, um pequeno “hack” no dicionário Oracle, mas para conseguir a façanha, é necessário que tenha acesso a view DBA_USERS, que foi utilizado nesse exemplo.

LEMBRANDO

Lógicamente, que todos os exemplos que citei acima, poderiam ser feitos pelo DBA da empresa ou alguém que tenha acesso a usuários gerenciais do banco de dados, como SYSTEM, usuários com role de DBA e etc. Isso é apenas um exemplo de como se aplicar a técnica.

Agora, vou passar o exemplo prático de como funciona.

1) Vamos criar um usuário.

@id
HORA EXECUTADA ------------------- 09-09-2008 11:45:57 INSTANCE_NAME HOST_NAME STATUS --------------- -------------------- ---------- xe DBARODRIGO OPEN USER IS "SYS"
create user RODRIGO
identified by rodrigo;

Usuário criado.

grant create session to RODRIGO;

Concessão bem-sucedida.

disco

Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

2) Teste a conexão do novo usuário no banco de dados.

conn rodrigo/rodrigo

Conectado.

disco

Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

3) Conectado com um usuário administrativo, faça um select básico na view DBA_USERS.

conn system

Informe a senha:

Conectado.

select username, account_status, password
    from dba_users
    where username = 'RODRIGO';

USERNAME ACCOUNT_STATUS PASSWORD

—————————— ——————————– ——————————

RODRIGO OPEN F697FBF0BB2DA2EC

4) Altere a senha do usuário desejado, no exemplo, vou alterar a senha para FERNANDA.

alter user RODRIGO identified by FERNANDA;

Usuário alterado.

5) Pegue o valor gerado para a nova senha.

select username, account_status, password
  from dba_users
  where username = 'RODRIGO';

USERNAME ACCOUNT_STATUS PASSWORD

—————————— ——————————– ——————————

RODRIGO OPEN FB34D454E9FFDE18

Observação
Pode parecer confuso, mais vamos recapitular os valores que são equivalentes as senhas:
F697FBF0BB2DA2EC = RODRIGO
FB34D454E9FFDE18 = FERNANDA

6) Para voltar a senha anterior, apenas utilize a opção VALUES junto com IDENTIFIED BYcom o valor da coluna password.

conn system

Informe a senha:

Conectado.

alter user RODRIGO identified by values 'F697FBF0BB2DA2EC';

O valor F697FBF0BB2DA2EC (gerado por um algoritmo HASH), é equivalente ao valor RODRIGO.
Agora, veja os testes.

conn rodrigo/fernanda

Conectado.

disco

Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

conn system

Informe a senha:

Conectado.

alter user RODRIGO identified by values 'F697FBF0BB2DA2EC';

Usuário alterado.

disco

Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

conn rodrigo/rodrigo

Conectado.

disco

Desconectado de Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Como eu não alterei o valor para a senha FERNANDA, se eu tentar logar com essa senha, terei erros, veja.

conn rodrigo/fernanda

ERROR:

ORA-01017: invalid username/password; logon denied

FINISH!

Uma técnica de hack bem conhecida entre os DBAS, que até a versão 10gR2 (no Patchset 10.2.0.4) ainda continua, eu não sei ainda se nas versões 11g já possui algum tipo de segurança nesse ponto, então aprecie com moderação.

ATUALIZAÇÃO

Para as versões 11g essa técnica não é mais aplicada devido as alterações estruturais no banco de dados por parte de segurança, que ficou muito mais confiável. Então, essa técnica se aplica até a versão Oracle Database 10g Release 2.

Abraços,

  • Share/Bookmark
2 Comments :, , , , , , , , , , , more...

Diminuindo físicamente um banco de dados Oracle

by Rodrigo Almeida on jan.29, 2010, under Administração

Olá,

Vou mostrar uma tática bem legal de diminuir um banco de dados Oracle físicamente, sem mexer em extents (por shrink table), rebuild de índices ou realizar desfragmentação de segmentos (por Export\Import Utility) no banco de dados.

O principal ponto que iremos atacar será os espaços livres desnecessários alocados na tablespace, que consomem espaços em disco preciosos no sistema operacional, toda essa tarefa será guiada atráves da marca d’água (HWM - High Water Mark) dos datafiles onde podemos realizar um RESIZE no datafile para um valor menor sem a perda de dados.

Lembrete

Essa tarefa envolve alguns conceitos de Oracle, como os de Marca D’água, ou HWM - High Water Mark, esse tema eu vou abordar em outro post para melhor entendimento. OK!

Para iniciarmos os trabalhos, vamos analisar o tamanho do nosso banco de dados e quanto ele está ocupando em disco, abaixo, vou fazer dois SELECTS que passa essas informações para nós e depois um print da quantidade em disco utilizado e livre no sistema operacional.

select sum(bytes)/1024/1024 as "TamanhoFisico(MB)" from dba_data_files;

TamanhoFisico(MB)
—————–
76000

col "FileSystem" format a12
select substr(file_name,1,4) as "FileSystem", sum(bytes)/1024/1024 as "Tamanho(MB)"
from dba_data_files
group by rollup(substr(file_name,1,4))
order by substr(file_name,1,4);

FileSystem Tamanho(MB)
———— ———–
/u01 25800
/u02 50200
76000

Percebemos, que no meu banco de dados, tenho quase 26GB de datafiles no FileSystem /u01 e mais 50GB no FileSystem /u02, totalizando os 76GB que é o tamanho total do meu banco de dados. O importante é saber o que esse valor representa na minha máquina, em questão de consumo e escabilidade, veja o que a máquina ainda pode oferecer.

[oracle@pelspos18 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 9.9G 3.2G 6.3G 34% /
/dev/sda1 190M 13M 168M 8% /boot
none 2.0G 0 2.0G 0% /dev/shm
/dev/sda5 2.0G 36M 1.9G 2% /tmp
/dev/sda6 114G 51G 58G 48% /u01
/dev/sdb1 134G 50G 78G 40% /u02

Para o FileSystem /u01, representa 48% de utilização, já para o FileSystem /u02, representa 40% de utilização. Claro, que tudo isso, irá depender de como o aplicativo e banco de dados se comporta, se é um banco de dados com crescimento acentuado diário, mensal ou semestral, tudo isso influência. Mas, no exemplo que estou utilizando, o banco de dados tem um crescimento em média de 3GB por mês, então, está adequado.

Mas, eu preciso liberar mais espaço em disco para fazer alguns backups em disco, exports e etc. Então, vou diminuir meu banco de dados físicamente de forma segura, como eu disse no início do post.

Para fazer isso, preciso da mais algumas informações como, Tamanho Físico e Livre das tablespace, que pode ser pego facilmente pelos SELECTS abaixo.

select tablespace_name, sum(bytes)/1024/1024 as "TAMANHO(MB)"
from dba_data_files
group by tablespace_name
order by sum(bytes);

TABLESPACE_NAME TAMANHO(MB)
——————– ———–
FIN_CPAG 400
FIN_CEXT_IDX 800
USERS 800
TOOLS 1500
SYSAUX 2000
SYSTEM 2000
FIN_CORP 3500
FIN_CORP_IDX 5000
FIN_CPAG_IDX 8000
UNDOTBS 10000
FIN_CREC_IDX 12000
FIN_CREC 30000

12 linhas selecionadas.

Bom, as tablespaces SYSTEM e SYSAUX não é novidade para ninguem, então, elas vou deixar-las de fora da atividade, para não ocorrer nenhum tipo de problema. Vou apenas pensar nas demais, inclusive na de UNDO. Perceba que esse é apenas um SELECT para ver o tamanho total das tablespaces, agora, quero saber quanto cada uma tem livre, para poder direcionar os RESIZES. Abaixo segue o tamanho livre por tablespace.

select tablespace_name, sum(bytes)/1024/1024 as "TAMANHO(MB)"
from dba_free_space
group by tablespace_name
order by sum(bytes);

TABLESPACE_NAME TAMANHO(MB)
——————– ———–
FIN_CREC_IDX 2,1875
FIN_CPAG 398,5625
USERS 642,5625
FIN_CEXT_IDX 799,5625
TOOLS 1495,3125
SYSTEM 1738,8125
SYSAUX 1869,125
FIN_CORP_IDX 2456,4375
FIN_CORP 3259,6875
FIN_CPAG_IDX 5289,375
FIN_CREC 8625,125
UNDOTBS 9865,375
12 linhas selecionadas.

Apenas mudei a view do primeiro SELECT, de dba_data_files para dba_free_space. Com isso, podemos ver quem tem mais espaço livre e saber quem precisa, existe tablespace com 8GB livres, e outros com 2,3 e 5G livres, só nisso, deixando apenas 10% livre, podemos economizar 12GB em disco. E ainda sem pensar no UNDO.

Agora, vamos executar um SELECT que irá analisar a marca d’água dos datafiles e verificar se existe a possibilidade de realizar um RESIZE para um valor menor, com isso, liberar espaço em disco no sistema operacional. Esse SELECT precisa de uma atenção especial, pois, é necessário informar o tamanho do db_block_size do seu banco de dados para efetuar corretamente os cálculos.

Para saber o tamanho do seu db_block_size, basta fazer o seguinte procedimento.

NO SQLPLUS, faça:

show parameters db_block_size

NAME TYPE VALUE
———————————— ———– ——————————
db_block_size integer 8192

Se preferir, poderá ver na v$parameter, como no exemplo.

col name format a15
col value format a15
select name, value from v$parameter where name = 'db_block_size';

NAME VALUE
————— —————
db_block_size 8192

Agora, o momento esperado, o SELECT para realizar a operação de resize, veja.

select 'alter database datafile ''' || file_name || ''' resize ' ||
ceil( (nvl(hwm,1)*8192*1.2)/1024/1024 )  || 'm;' cmd
from dba_data_files a,
( select file_id, max(block_id+blocks-1) hwm
  from dba_extents
  group by file_id ) b
where a.file_id = b.file_id(+)
and ceil( (nvl(hwm,1)*8192*1.2)/1024/1024 ) < ceil( blocks*8192/1024/1024)
and ceil( (nvl(hwm,1)*8192*1.2)/1024/1024 ) > 100

Lembrete
Veja que onde está 8192 no script acima, é referente ao tamanho do db_block_size do seu banco de dados, esse valor então poder ser 2048, 4096, 8192, 16384 e 32768.

O script acima irá gerar um resultado sobre espaço livre, tamanho atual, espaço que pode ser salvo, total de espaço que pode ser liberado por datafile do seu banco de dados, tudo isso gerado pelos cálculos sobre a marca d’água de cada datafile. Se atentem pois ele está pegando todas as tablespaces do banco de dados e isso para nós não é necessário, podemos excluir a tablespace SYSTEM e SYSAUX.

FILE_NAME SMALLEST CURRSIZE SAVINGS SMALLEST_SAFE SAVINGS_SAFE
———————————————————— ———- ———- ———- ————- ————
/u02/app/oracle/oradata/finp/fin_corp01.dbf 125 2000 1875 149 1851
/u02/app/oracle/oradata/finp/sysaux01.dbf 191 2000 1809 229 1771
/u02/app/oracle/oradata/finp/system01.dbf 264 2000 1736 316 1684
/u02/app/oracle/oradata/finp/fin_corp02.dbf 117 1500 1383 140 1360
/u01/app/oracle/oradata/finp/fin_cpag_idx04.DBF 643 2000 1357 771 1229
/u01/app/oracle/oradata/finp/fin_cpag_idx03.dbf 651 2000 1349 781 1219
/u01/app/oracle/oradata/finp/fin_cpag_idx02.dbf 692 2000 1308 830 1170
/u01/app/oracle/oradata/finp/fin_cpag_idx01.dbf 728 2000 1272 873 1127
/u01/app/oracle/oradata/finp/fin_corp_idx02.dbf 847 2000 1153 1016 984
/u01/app/oracle/oradata/finp/fin_corp_idx01.dbf 897 2000 1103 1076 924
/u02/app/oracle/oradata/finp/fin_crec09.dbf 1284 2000 716 1540 460
/u02/app/oracle/oradata/finp/fin_crec08.dbf 1288 2000 712 1545 455
/u02/app/oracle/oradata/finp/fin_crec07.dbf 1304 2000 696 1564 436
/u02/app/oracle/oradata/finp/fin_crec06.dbf 1314 2000 686 1576 424
/u02/app/oracle/oradata/finp/fin_crec05.dbf 1331 2000 669 1597 403
/u02/app/oracle/oradata/finp/fin_crec04.dbf 1334 2000 666 1600 400
/u02/app/oracle/oradata/finp/fin_crec01.dbf 1351 2000 649 1622 378
/u02/app/oracle/oradata/finp/fin_crec02.dbf 1351 2000 649 1621 379
/u02/app/oracle/oradata/finp/fin_crec03.dbf 1351 2000 649 1621 379
/u02/app/oracle/oradata/finp/users01.dbf 158 800 642 189 611
/u02/app/oracle/oradata/finp/fin_crec15.dbf 1427 2000 573 1712 288
/u02/app/oracle/oradata/finp/fin_crec14.dbf 1547 2000 453 1856 144
/u02/app/oracle/oradata/finp/fin_crec13.dbf 1549 2000 451 1858 142
/u02/app/oracle/oradata/finp/fin_crec12.dbf 1551 2000 449 1861 139
/u02/app/oracle/oradata/finp/fin_crec11.dbf 1603 2000 397 1923 77
/u01/app/oracle/oradata/finp/fin_corp_idx03.dbf 802 1000 198 962 38

26 linhas selecionadas.

CMD
——————————————————————————
alter database datafile ‘/u02/app/oracle/oradata/finp/system01.dbf’ resize 316m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec11.dbf’ resize 1923m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec02.dbf’ resize 1621m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec07.dbf’ resize 1564m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_corp02.dbf’ resize 140m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec05.dbf’ resize 1597m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec06.dbf’ resize 1576m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec03.dbf’ resize 1621m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec08.dbf’ resize 1545m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_corp_idx01.dbf’ resize 1076m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec01.dbf’ resize 1622m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec09.dbf’ resize 1540m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec12.dbf’ resize 1861m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec14.dbf’ resize 1856m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec15.dbf’ resize 1712m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_cpag_idx01.dbf’ resize 873m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_cpag_idx04.DBF’ resize 771m;
alter database datafile ‘/u02/app/oracle/oradata/finp/sysaux01.dbf’ resize 229m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec13.dbf’ resize 1858m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_crec04.dbf’ resize 1600m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_cpag_idx02.dbf’ resize 830m;
alter database datafile ‘/u02/app/oracle/oradata/finp/fin_corp01.dbf’ resize 149m;
alter database datafile ‘/u02/app/oracle/oradata/finp/users01.dbf’ resize 189m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_corp_idx02.dbf’ resize 1016m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_corp_idx03.dbf’ resize 962m;
alter database datafile ‘/u01/app/oracle/oradata/finp/fin_cpag_idx03.dbf’ resize 781m;

26 linhas selecionadas.

Uma coisa boa que essse script já fornece o comando de DDL para redimensionar o datafile da tablespace sem a perda de dados. Basta executar.

Após a execução dos scripts, vamos analisar os resultados gerados. Primeiramente, vamos ver agora o tamanho total e o espaço livre das tablespaces, depois verificar como ficou o espaço em disco no sistema operacional e saber o quanto ganhamos com isso.

Espaço total das tablespace

select tablespace_name, sum(bytes)/1024/1024 as "TAMANHO(MB)"
from dba_data_files
group by tablespace_name
order by sum(bytes);

TABLESPACE_NAME TAMANHO(MB)
——————– ———–
USERS 189
FIN_CORP 289
FIN_CPAG 400
FIN_CEXT_IDX 800
TOOLS 1500
SYSAUX 2000
SYSTEM 2000
FIN_CORP_IDX 3054
FIN_CPAG_IDX 3255
UNDOTBS 10000
FIN_CREC_IDX 12000
FIN_CREC 25496

12 linhas selecionadas.

Espaço livre nas tablespace

select tablespace_name, sum(bytes)/1024/1024 as "TAMANHO(MB)"
from dba_free_space
group by tablespace_name
order by sum(bytes);

TABLESPACE_NAME TAMANHO(MB)
———————– ———–
FIN_CREC_IDX 2,1875
USERS 31,5625
FIN_CORP 48,6875
FIN_CPAG 398,5625
FIN_CORP_IDX 510,4375
FIN_CPAG_IDX 544,375
FIN_CEXT_IDX 799,5625
TOOLS 1495,3125
SYSTEM 1737,3125
SYSAUX 1811,5
FIN_CREC 4121,125
UNDOTBS 9797,4375

12 linhas selecionadas.

Espaço no sistema operacional

[oracle@pelspos18 u01]$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 9.9G 3.2G 6.3G 34% /
/dev/sda1 190M 13M 168M 8% /boot
none 2.0G 0 2.0G 0% /dev/shm
/dev/sda5 2.0G 36M 1.9G 2% /tmp
/dev/sda6 114G 45G 64G 42% /u01
/dev/sdb1 134G 42G 86G 33% /u02

Conclusões

Perceba que algumas tablespace permaneceram do mesmo tamanho e algumas tiveram mais que 10% do seu tamanho reduzido, o melhor que podemos notar no sistema operacional que o FileSystem /u02 que antes tinha 78GB disponível, agora tem 86GB, uma diferença de 8GB, para o FileSystem /u01 que atens tinha 58GB disponível, agora tem 64GB, uma diferença de 6GB, que somando com o valor anterior, podemos reutilizar 14GB de espaço no sistema operacional.

O tamanho do nosso banco de dados fisicamente, também diminuiu, foi para 62GB. Antes era de 76GB, 14GB a menos, justamente o que nós não utilizamos mais.

O que pode nos ajudar a redução física do banco de dados?

Pode nos ajudar em N tarefas, como:

  • Não deixar o banco de dados travar por problemas de ARCHIVE ERROR;
  • Reaproveitamente de espaço em disco;
  • Diminuição de arquivos de backup gerados pelo RMAN em nível 0;
  • Ajuda na escabilidade do servidor;

Acho que isso já são boas razões para se pensar em fazer uma diminuição física do seu banco de dados.

Abraços,

  • Share/Bookmark
Leave a Comment :, , , , , , , , , , , , , , , , more...

Entendendo a Marca d’água e fragmentação de tabelas

by Rodrigo Almeida on jan.27, 2010, under Administração

Olá,

Uma dos principais conceitos sobre arquitetura física do Oracle, é a marca D’água, uma tradução de HWM  - High Water Mark, ele que indica o limite que uma tabela já ocupou de espaço físico no seu banco de dados. Mas, vamos um pouco mais a fundo.

O que é uma Marca D’água (HWM - High Water Mark)?

A marca d’água é o limite do número de blocos que uma tabela pode estar utilizando, resumindo para um conceito mais simples, toda vez que uma tabela recebe um INSERT (novos registros), essa marca na tabela aumenta dizendo ao Oracle Server a quantidade de blocos que a tabela está utilizando, automaticamente, a quantidade de blocos, multiplicado, pelo tamanho do db_block_size do banco de dados, diz o valor físico real que está sendo utilizado.

Mas, esse valor real não é o valor que o Oracle irá alocar, pois irá depender de alguns outros pontos, como:

  • Se a tabela está sendo gerenciada por sí própria ou pela tablespace.
  • Irá depender dos tamanhos dos extents, exemplo, INITIAL_EXTENT e NEXT_EXTENT.
  • Também, irá depender do tipo de gerenciamento, se é SEGMENT MANAGEMENT AUTO ou UNIFORM.
  • E a quantidade de blocos que um EXTENT pode suportar.

Vamos ver como funciona a marca d’água na prática, um alguns exemplos práticos.

Vou criar uma tabela simples, chamada TSTDBA.

create table TESTE (a varchar2(100) not null, b number(7) not null);

Tabela criada.

Agora, vamos analisar como está a estrutura para o Oracle, pois a tabela não possui nenhum valor e nenhuma estatística coletada.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
from dba_tables
where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA

Até o momento, tudo sem surpresas para nós.

Então, vamos popular essa tabela com alguns registros, veja o exemplo.

declare
     contador integer;
begin
     contador := 1;
     while contador <= 1000 loop
               insert into TSTDBA values ('TESTE',contador);
               contador := contador + 1;
       end loop;
       commit;
 end;

Procedimento PL/SQL concluído com sucesso.

exec dbms_stats.gather_table_stats (ownname=>'RODRIGO',tabname=>'TSTDBA',estimate_percent=>null,method_opt=>'FOR ALL COLUMNS SIZE AUTO',degree=>6);

Procedimento PL/SQL concluído com sucesso.

Verifiquem que fiz um pequeno bloco PL/SQL para inserir dados em minha tabela, cerca de 1.000 registros. Após isso, preciso dizer ao Oracle, como a tabela está, seu volume e outras coisas mais, então, fiz um analyze na tabela para atualizar as informações estruturais dela no dicionário Oracle, ao fazer o analyze com o DBMS_STATS, o resultado do SELECT acima, agora é esse.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
from dba_tables
where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                                  5            0       1000 06-10-2008 19:42:08

Veja, a nossa tabela está utilizando 5 blocos, o db_block_size do meu banco de dados é de 8KB, então, resumidamente, ele deveria estar utilizando cerca de 40KB, certo?

select 8192*5 from dual;

8192*5
———-
40960

Mas, se consultar o seu tamanho na dba_segments temos:

select segment_name, sum(bytes)/1024 from dba_segments where segment_name = 'TSTDBA' group by segment_name;

SEGMENT_NAME                                                                      SUM(BYTES)/1024
——————————————————————————— —————
TSTDBA                                                                                         64

O resultado para o tamanho da tabela TSTDBA é 64KB, porque, o INITIAL_EXTENT da tabela é de 64KB, e como os 1.000 registros ocuparam apenas 40KB, um único extent consegui suportar.

select initial_extent/1024, next_extent from dba_tables where table_name = 'TSTDBA';

INITIAL_EXTENT/1024 NEXT_EXTENT
——————- ———–
64

Pois bem! Rodrigo, e o tal do HWM, até onde está entrando nisso?

Vamos começar a brincar agora, veja que após o analyze, minha tabela TSTDBA está utilizando 5 blocos de dados, certo? Teoricamente, se eu fizer um TRUNCATE TABLE, eu não vou mais utilizar nenhum bloco, e minha marca d’água deveria baixar, mas, acontece isso:

truncate table TSTDBA;

Tabela truncada.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
  2  from dba_tables
  3  where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                                  5            0       1000 06-10-2008 19:44:18

A minha tabela continua com se estivesse com 5 blocos, o que isso pode nos prejudicar:

  • Esse exemplo é bem simples, mas para tabelas com milhares de registros, poderá influenciar os FULL-TABLES SCANS.
  • Ao realizar um INSERT convencional, ou seja, sem o hint /* + APPEND */, ele irá procurar por bocos livres e irá consumir CPU e demorar um tempo para sua execução.
  • Se minha marca d’água estiver muito alta, ou seja, estiver armazenando um alto valor de blocos utilizados, e você sabe, que ele não está utilizando tudo isso, você terá uma alocação de EXTENTS desnecessários no banco de dados, e isso irá ocupar espaço desnecessários.

Caso eu quisesse diminuir o tamanho do meu segmento de tabela, eu não iria conseguir, pois além da marca d’água é inferior aos meus 64KB, pois bem, tente realizar um insert agora de 2.000.000 de registros e vamos ver o que acontece.

declare
       contador integer;
    begin
       contador := 1;
       while contador <= 2000000 loop
               insert into TSTDBA values ('TESTE',contador);
               contador := contador + 1;
       end loop;
       commit;
   end;

Procedimento PL/SQL concluído com sucesso.

exec dbms_stats.gather_table_stats (ownname=>'RODRIGO',tabname=>'TSTDBA',estimate_percent=>null,method_opt=>'FOR ALL COLUMNS SIZE AUTO',degree=>6);

Procedimento PL/SQL concluído com sucesso.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
    from dba_tables
    where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                               4654            0    2000000 06-10-2008 22:37:24

show parameters db_block_size

NAME                                 TYPE        VALUE
———————————— ———– ——————————
db_block_size                        integer     8192

select (8192*4654)/1024/1024 as "Tamanho" from dual;

Tamanho
———-
36,359375

select segment_name, sum(bytes)/1024/1024 from dba_segments where segment_name = 'TSTDBA' group by segment_name;

SEGMENT_NAME                                                                      SUM(BYTES)/1024/1024
——————————————————————————— ——————–
TSTDBA                                                                                              37

Se quizer analisar melhor como ficou a distribuição, veja a dba_extents, abaixo vou mostrar apenas um pequeno resumo da quantidade de extents alocados e seus respectivo tamanho.

select segment_name, count(extent_id), sum(bytes)/1024/1024
    from dba_extents
    where segment_name = 'TSTDBA'
    group by segment_name;

SEGMENT_NAME         COUNT(EXTENT_ID) SUM(BYTES)/1024/1024
——————– —————- ——————–
TSTDBA                             52                   37

Bom, vimos que agora temos um valor legal de extents alocados, e mesmo após o TRUNCATE continuo com uma alocação de extents, que totaliza os 37MB da tabela, então, minha marca d’água está posicionado no 51° extent, que seria o limite do numeros de blocos alcançados.

Conseguimos entender como funciona a marca d’água, o que isso pode nos causar?

A chamada fragmentação de tabela, além da marca d’água elevar o número de extents no dicionário, prejudicando muitas vezes os planos de execução e os table full scans, vamos ter também perca de espaço físico para a tablespace, espaço que não poderam ser alocados por outro segmento. Vamos a uma demostração prática de como funciona a fragmentação.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
    from dba_tables
    where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                               4654            0    2000000 06-10-2008 22:37:24

select segment_name, count(extent_id), sum(bytes)/1024/1024
    from dba_extents
    where segment_name = 'TSTDBA'
    group by segment_name;

SEGMENT_NAME         COUNT(EXTENT_ID) SUM(BYTES)/1024/1024
——————– —————- ——————–
TSTDBA                             52                   37

A minha tabela TSTDBA continua com seus 2.000.000 de registros, após o analyze acima, vimos que está a atual estrutura da tabela, e se realizarmos diversos DELETES em grandes quantidades, o que poderemos ter?

delete from TSTDBA where b between 10000 and 20000;

10001 linhas deletadas.

delete from TSTDBA where b between 50000 and 200000;

150001 linhas deletadas.

delete from TSTDBA where b between 400000 and 700000;

300001 linhas deletadas.

delete from TSTDBA where b between 1000000 and 1300000;

300001 linhas deletadas.

commit;

Commit concluído.

select segment_name, count(extent_id), sum(bytes)/1024/1024
    from dba_extents
    where segment_name = 'TSTDBA'
    group by segment_name;

SEGMENT_NAME         COUNT(EXTENT_ID) SUM(BYTES)/1024/1024
——————– —————- ——————–
TSTDBA                             52                   37

Vamos passar um analyze para validar toda a estrutura da tabela.

exec dbms_stats.gather_table_stats (ownname=>'RODRIGO',tabname=>'TSTDBA',estimate_percent=>null,method_opt=>'FOR ALL COLUMNS SIZE AUTO',degree=>6);

Procedimento PL/SQL concluído com sucesso.

Veja o resultado para os novos valores.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
    from dba_tables
    where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                               4654            0    1239996 06-10-2008 23:09:01

A quantidade de extents não alterou depois de apagarmos diversos registros, isso causa a conhecida fragmentação do segmento, mesmo que após calcularmos a quantidade de registro exato da tabela.

select segment_name, count(extent_id), sum(bytes)/1024/1024
    from dba_extents
    where segment_name = 'TSTDBA'
    group by segment_name;

SEGMENT_NAME         COUNT(EXTENT_ID) SUM(BYTES)/1024/1024
——————– —————- ——————–
TSTDBA                             52                   37

Para resolvermos esse problema de fragmentação, bastamos reconstruir o mapa binário da tabela, para isso, apenas use um MOVE sem mencionar a tablespace que resolve nosso problema.

alter table TSTDBA move;

Tabela alterada.

select owner, table_name, blocks, empty_blocks, num_rows, to_char(last_analyzed,'DD-MM-RRRR HH24:MI:SS') as "ANALYZE"
    from dba_tables
    where table_name = 'TSTDBA';

OWNER      TABLE_NAME                         BLOCKS EMPTY_BLOCKS   NUM_ROWS ANALYZE
———- —————————— ———- ———— ———- ——————-
RODRIGO    TSTDBA                               4654            0    1239996 06-10-2008 23:09:01

select segment_name, count(extent_id), sum(bytes)/1024/1024
    from dba_extents
    where segment_name = 'TSTDBA'
    group by segment_name;

SEGMENT_NAME         COUNT(EXTENT_ID) SUM(BYTES)/1024/1024
——————– —————- ——————–
TSTDBA                             38                   23

PRONTO! Veja que após nosso “rebuild” na tabela, liberamos cerca de 15MB para a tablespace, fazendo apenas uma reconstrução dos extents da tabela.

Existem muitos outros conceitos envolvidos sobre a alocação de extents, sem mencionar os freelists, gerenciamento das tablespaces e diferenças entre os segmentos de tabela e índice, tudo isso foi apenas um modo de ilustrar os problemas que podem causar perda de performance em nossos ambientes.

Existe uma matéria que escrevi para a iMasters algum tempo atrás que explica com um pouco mais de detalhes como funciona a arquitetura de armazenamento lógico do banco de dados Oracle, o artigo Arquitetura de armazenamento lógico, que sanar algumas dúvidas.

A idéia principal do post foi iniciar desde o conceito de HWM (High Water Mark) até sua fragmentação, passando por várias fases, para fornecer um melhor entendimento de como a arquitetura Oracle funciona.

Abraços,

  • Share/Bookmark
3 Comments :, , , , , , , , , , , , , more...

FRM-10256 - E lá vai o DBA

by Rodrigo Almeida on dez.16, 2009, under Administração

Olá,

Recentemente, estou participando de uma migração de um banco de dados, Oracle 8i para Oracle 10g, da plataforma 32-bits para 64-bits e uma aplicação Forms/Reports 6i (Oracle Developer 6i), e se deparamos com um problema de Security após a criação e importação dos owners para o novo banco de dados.

Quando mandei o desenvolvedor conectar a aplicação no novo banco de dados, para fins de testes, conectividade e possíveis problemas do 10g (Pois é uma migração do 8i, e a aplicação está toda em REGRA), o Forms nos emitia um erro estranho, como mostra abaixo:

FRM-10256: User is not authorized to run Form Builder Menu

Logo de início, pensei que poderia ser problemas no owner da aplicação (no banco de dados), ou o menu da aplicação, que utiliza outro owner para validar e construir o menu. Fiz todos os checks necessários, como:

  • Analisar o “STATUS ACCOUNT” de todos os owners no banco de dados, que pode ser feito pela view dba_users;
  • Olhar qual perfil de banco de dados os owners estão usando, todos estavam com DEFAULT para início;
  • Analisar com a base de produção, objetos inválidos, views e qualquer outro objeto que tenha relação com a construção dos menus, e também nada.

Então, resolvi junto com o desenvolvedor, pesquisar sobre o assunto e esse erro específico, e encontramos a seguinte solução pelo Metalink.

Visão Geral

A segurança do Oracle Forms é baseada em roles (papéis) no banco de dados Oracle. Essas roles são um método de permitir o acesso as informações do banco de dados para os usuários, portanto, se nenhum usuário não tem acesso a qualquer coisa, essas roles podem ajudar a facilitar o acesso.

Desde que os usuários tenham essas roles definidas pelo DBA ou Administrador de aplicação, os módulos de MENU e ITENS DO MENU terão um controle de acesso feito internamento pelo menu da aplicação.

Solução

Para resolver esse problema, o DBA, conectado no banco de dados com o usuário SYS, deve executar um script de segurança que vêm junto com o Developer 6i, que é o script abaixo:

Para ambiente Windows

%ORACLE_HOME%\tools\dbtab\forms60\frm60sec.sql

Para ambiente Linux\Unix

$ORACLE_HOME/forms60/admin/sql/frm60sec.sql

Esse script é pertecente ao ORACLE_HOME do Developer 6i, não confunda com o ORACLE_HOME do banco de dados. Execute ele com o usuário SYS e seus problemas vão terminar.

Abaixo, segue o contéudo do script, caso, estejam com esse problema e não conseguem acessar o servidor de aplicação por motivo de segurança da empresa ou qualquer outro motivo.

FRM60sec.sql

create or replace view FRM50_ENABLED_ROLES as
select urp.granted_role role,
sum(distinct decode(rrp.granted_role,
'ORAFORMS$OSC',2,
'ORAFORMS$BGM',4,
'ORAFORMS$DBG',1,0)) flag
from sys.user_role_privs urp, role_role_privs rrp
where urp.granted_role = rrp.role (+)
and urp.granted_role not like 'ORAFORMS$%'
group by urp.granted_role;
create public synonym FRM50_ENABLED_ROLES for sys.FRM50_ENABLED_ROLES;
create role ORAFORMS$OSC;
create role ORAFORMS$DBG;
create role ORAFORMS$BGM;

PRONTO! Acho que agora vai resolver a vida, caso tenha problemas, dê os grants de SELECT do SYNONYM para os usuários que precisa acessar a aplicação.

Abraços,

  • Share/Bookmark
2 Comments :, , , , , , , , , , , , , more...

Transações pendentes em ambientes distribuídos

by Rodrigo Almeida on dez.08, 2009, under Administração

Olá,

Vamos tocar num assunto interessante, as transações pendentes quando se trabalhar com banco de dados em ambientes distribuídos. Essas transações é uma forma de comunicação entre bases de dados Oracle, atráves de DBLINKS, e trabalham com uma tecnologia de controle chamada TWO-PHASE Commit, traduzida, Comprometimento em duas fases, que server como garantia de integridade entre as bases oracle, tanto na base de origem e destino, permitindo que a transação seja segura e íntegra.

A tecnologia de TWO-PHASE Commit, basicamente surgiu para controlar e monitorar as atividades de commit e rollback das transações em ambientes de bases de dados distribuídos, que como dito acima, serve para garantir a consistência dos dados. Existe desde a versão 8i um processo de plano de fundo (background process) chamado RECO, que sua principal função no banco de dados é monitorar todas essas transações, a partir de um LOCAL_TRAN_ID (na base de origem) e um GLOBAL_TRAN_ID (na base de destino) e dizer ao banco de dados, qual é o estado das transações, e se tiver algum problema, tentar recuperar-las.

Junto a com tecnologia, o dicionário de dados ganhou duas visões, a primeira é a dba_2pc_pending, que tem como objetivo listar todas as transações que estão pendentes no banco de dados, que por algum motivo o RECO não fez a sua recuperação ou se a transação ainda está sendo efetivada ou não no banco de dados, e temos também a visão dba_2pc_neighbors, que lista todas as entradas e saídas das transações que estão pendentes, qual o banco de dados, usuário e etc.

O objetivo desse post não é aprensetar a tecnologia TWO-PHASE Commit que é velha, desde 1980 está implementado nos banco de dados Oracle, e sim, de como eliminar essas transações que ficam “pressas” em nossos banco de dados.

Abaixo, segue um exemplo de um ambiente real de como as duas visões acima podem nos auxiliar na eliminação das transações, veja:

select local_tran_id, global_tran_id, state, fail_time, force_time
from dba_2pc_pending;

LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE FAIL_TIM FORCE_TI
———————- —————————————- —————- ——– ——–
14.28.232339 PARA.WORLD.0964cc71.14.28.232339 collecting 30/07/08
4.26.229018 PARA.WORLD.0964cc71.4.26.229018 collecting 31/07/08
12.42.248854 PARA.WORLD.0964cc71.12.42.248854 collecting 11/08/08

select local_tran_id, in_out, database, dbuser_owner
from dba_2pc_neighbors;

LOCAL_TRAN_ID IN_ DATABASE DBUSER_OWNER
———————- — ——————– ——————————
14.28.232339 in ARA_VE_WANDERSON
14.28.232339 in PARA.WORLD DPD
4.26.229018 in ARA_VE_SANSAO
12.42.248854 in ARA_VE_MELQUESEDETE
14.28.232339 out PEL_DIST_ARA.WORLD DPD
14.28.232339 out PEL_DIST_GOI.WORLD DPD
4.26.229018 out PEL_DIST_GOI.WORLD DPD
12.42.248854 out PEL_DIST_GOI.WORLD DPD

Perceba que as duas visões podem nos fornecer ótimas informações sobre as pendências que estão no banco de dados, o que nós iremos precisar é apenas o LOCAL_TRAN_ID, que é a identificação da transação distribuída e a partir dessa transação, saber qual é o seu status, pela coluna STATE.

Observe que no primeiro SELECT na visão dba_2pc_pending, a transação de id 14.28.232339 está com seu status de COLLECTING (Coletando) e até agora está um zumbi dentro do banco de dados, pois basta observar pela data de FAIL_TIME (Data de Falha) que o processo RECO não conseguiu fazer sua recuperação até o momento. Então, devemos eliminar-la manualmente, habilitando no banco de dados, a opção de recuperação distribuída, deste modo:

sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on Seg Ago 11 14:21:50 2008
Copyright (c) 1982, 2005, Oracle. All rights reserved.

conn sys@pel_dist_ara as sysdba

Informe a senha:
Conectado.

alter system enable distributed recovery;

Sistema alterado.

select local_tran_id, global_tran_id, state, fail_time, force_time
from dba_2pc_pending;

LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE FAIL_TIM FORCE_TI
———————- —————————————- —————- ——– ——–
14.28.232339 PARA.WORLD.0964cc71.14.28.232339 collecting 30/07/08
4.26.229018 PARA.WORLD.0964cc71.4.26.229018 collecting 31/07/08
12.42.248854 PARA.WORLD.0964cc71.12.42.248854 collecting 11/08/08

exec dbms_transaction.purge_lost_db_entry ('14.28.232339');

Procedimento PL/SQL concluído com sucesso.

commit;

Commit concluído.

select local_tran_id, global_tran_id, state, fail_time, force_time
from dba_2pc_pending;

LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE FAIL_TIM FORCE_TI
———————- —————————————- —————- ——– ——–
4.26.229018 PARA.WORLD.0964cc71.4.26.229018 collecting 31/07/08
12.42.248854 PARA.WORLD.0964cc71.12.42.248854 collecting 11/08/08

Eu também utilizei o pacote DBMS_TRANSACTION, o seu procedimento PURGE_LOST_DB_ENTRY, que é utilizado nesses casos para a eliminação de transações pendentes sem nenhum comprometimento do ambiente oracle.

E sempre que for utilizar essa técnica para eliminar transação pendente, sempre se lembre de duas coisas:

  1. Sempre deverá executar as ações acima com um usuário com permissão de SYSDBA, ou com o usuário SYS, com a role SYSDBA.
  2. Para habilitar a recuperação de transação, podemos utilizar o seguinte comando:

    alter system enable distributed recovery;
  3. Para as versões 9i, que foi o começo dos segmentos de UNDO (nosso velho amigo rollback), devemos alterar o seguinte parâmetro da instância:
  4. alter system set "_smu_debug_mode"=4;

É um parâmetro não documentado do banco de dados, que é limpar as transações que estão utilizando os segmentos de UNDO, isso foi corrigido na versão 10g posteriormente.

Após a realização de todas as tarefas acima, poderá ver que o processo RECO não está gerando mais traces no diretório do BACKGROUND_DUMP_DEST das transações que não conseguiu recuperar.

Isso é uma técnica muito utilizada quando queremos eliminar essas transações para evitar lock-held ou incosistência nos dados, mas lembre-se, sempre veja a coluna FAIL_TIME para ver desde quando não está conseguindo efetuar a recuperação, pois a dba_2pc_pending também informa as transações que estão pendentes no dia. Tome cuidado.

Abraços,

  • Share/Bookmark
Leave a Comment :, , , , , , , , , , , , , , , , more...

DROP DATABASE - Esse funciona mesmo!

by Rodrigo Almeida on nov.29, 2009, under Administração

Olá,

Umas das new features mais bem-vindas do Oracle Database 10g, é a opção DROP DATABASE, antigamente, até a versão 9iR2, eliminar um banco de dados era uma coisa demorada e chata. Agora, com essa nova opção, apagar um banco de dados está igual a eliminar uma tabela ou qualquer outro objeto.

Ao invocar o comando DROP DATABASE, todos os seus control files, arquivos de redo logs, datafiles e seu arquivo de parâmetro (PFILE/SPFILE) são apagados do servidor, ou seja, todos os arquivos que são listados internamente no control file, onde estão localizados os arquivos para aquele determinado banco de dados, são eliminados.

Para utilizar o DROP DATABASE, existe algumas restrições, veja:

  • O banco de dados deve estar montado, ou seja, sem acesso aos usuários.
  • Ao montar o banco de dados, deve estar no modo exclusivo (Exclusive mode) e não compartilhado.
  • Quando for montar o banco de dados, a opção de RESTRICT deve ser utilizado. Significa que apenas usuários com opção de acesso restrito são permitidos.

Abaixo, vou passar um exemplo prático de como utilizar esse comando.

sqlplus "/ as sysdba"

SQL*Plus: Release 10.2.0.4.0 - Production on Fri Sep 5 11:40:44 2008 Copyright (c) 1982, 2007, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production With the Partitioning, Data Mining and Real Application Testing options

SQL> shutdown immediate;

Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount restrict pfile="/u01/app/oracle/admin/finp/pfile/initfinp.ora";

ORACLE instance started.
Total System Global Area 3221225472 bytes
Fixed Size 2087416 bytes
Variable Size 1543505416 bytes
Database Buffers 1593835520 bytes
Redo Buffers 81797120 bytes
Database mounted.

drop database;

Database dropped.
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Data Mining and Real Application Testing options

Atenção

Ao iniciar a instância em MOUNT RESTRICT, utilizei a opção de iniciar por um arquivo de parâmetro alternativo, pois, quando eu executar DROP DATABASE, eu não queria eliminar esse arquivo.

PRONTO! Banco de dados eliminado, é válido lembrar que arquivos como: archives, cópias de backup ou backupsets gerados por RMAN e traces gerados pelos serviços de background, não são apagados pelo DROP DATABASE, o DBA deverá apagar esses arquivos manualmente.

Abraços,

  • Share/Bookmark
3 Comments :, , , , , , , , , , , more...

Horário de verão - Os impactos no banco de dados Oracle

by Rodrigo Almeida on jul.30, 2009, under Administração

Olá,

Nesse final de semana (14/02/2009 - DST Brazil) estamos terminando o horário de verão, que vale somente para a região Sul, Sudeste e Centro-Oeste. Com o termíno, deveremos atrasar nossos relógios em 1 hora, e isso será um grande problema para os DBAs que tem banco de dados Oracle na produção da empresa, pois apenas atrasar o horário do servidor com o banco de dados no ar (online) pode causar grandes danos.

Problemas

Ao atrasar o horário do servidor em 1 hora, e não realizar os procedimentos corretos para efetuar essa atividade, pode trazer diversos impactos ao banco de dados Oracle. E esses impactos podemos listar abaixo:

  • Sobreescrita na geração dos Archived Logs;
  • Problemas de comunicação com o LISTENER do Oracle Server;
  • Problemas de novos registros incluídos atráves da aplicação ou processos de ETL, pois se esses registros trabalham com funções de data como SYSDATE, TIMESTAMP ou SYSTIMESTAMP, podem ser invalidadas por primarys keys e constraints de check no modelo e banco de dados;
  • Para ambientes RAC (Real Application Cluster), mudar o horário pode trazer diversos problemas, desde o CRS (Cluster Registry Services), LISTENER e InterConnect, pois podem ocorrer sobreescritas na gravação dos logs e sincronização dos nós;
  • Para ambientes DataGuard ou Stand-by, podem ocorrer problemas também com sobreescritas dos redo logs, onde pode causar problemas e até mesmo erros do kernel do Oracle Server gerando os ORA-600;
  • Problemas nas mensagens gravadas no alert.log;
  • Problemas no agendamento de JOBS no banco de dados, que seja feito por DBMS_JOB ou DBMS_SCHEDULER;
  • Se ocorre a sobreescrita dos archived logs, terá problemas com o Point-in-Time-Recovery do seu banco de dados, e com isso, uma simples troca do horário pode ser uma catástrofe em seu backup e recover;
  • Pode ocorrer problemas com o JVM do Oracle;

Todos os impactos citados acima, estão resumidos e que podem ser afetados de imediato, existem outros impactos que podem aparecer depois de 2 ou 3 dias e até mesmo semanas. E para não correr esse risco, existe um procedimento bem básico para os DBAs.

Procedimento

Antes de realizar a troca do horário do servidor e futuramente do banco de dados, siga os procedimentos abaixo:

  1. Realizar um backup full do banco de dados.
  2. Parar os serviços do Listener, exemplo: lsnrctl stop ou lsnrctl <nome_listener> stop;
  3. Parar o banco de dados, com shutdown immediate, normal ou transactional.;
  4. Para ambiente Windows: Depois que descer o banco de dados pelo SQL*PLUS, descer o serviço do windows, exemplo: net stop OracleService<nome_da_base>;
  5. Anotar o horário de STOP GERAL, para saber com exatidão o momento da parada de todos os serviços;
  6. Alterar o horário do servidor (Windows\Linux\Unix);
  7. Após a troca do horário no servidor, esperar 1 hora para subir os bancos. Exemplo, se meu STOP GERAL foi as 00:05AM (antes da troca), anoto esse valor e espero 1 hora, realizo a troca do horário e quando for 01:05AM, meu horário será atrasado para 00:05AM novamente (ajuste para o fim do horário de verão), e a partir desse horário posso subir todos os serviços novamente a partir do horário que desceu, deste modo não regresso no tempo.
  8. Subir todos os serviços novamento, pode ser pela ordem BANCO DE DADOS -> LISTENER -> APLICAÇÃO.

E pronto! Já estamos com nossos horários ajustados para o horário de Brasilia (Oficial Brasileiro).

Recomendação

Nunca deixem os servidores de banco de dados com o ajuste de horário de verão automático, pois a cada ano, as datas são de início e fim podem sofrer alterações e seja necessário patchs para os novos ajustes e fora que isso, pode trazer todos os problemas citados acima no banco de dados, então faça sempre manualmente.

Abraços,

  • Share/Bookmark
8 Comments :, , , , , , , , more...

Publicidade


Friend Connect