quarta-feira, 27 de julho de 2011

Uso do SAVEPOINT no Oracle 11g



Olá pessoal!
Continuando a  nossa série de posts sobre a Prova de Certificação IZO-047 - Oracle SQL Expert iremos abordar mais um assunto.O uso do SAVEPOINT.

SAVEPOINTO Savepoint é uma declaração que faz parte do TCL(Transational Control Language) que suporta os comando ROLLBACK COMMIT.Ele estabelece demarcações de pontos dentro de uma transação, a fim de capacitar qualquer COMMIT seguinte ou ROLLBACK para subdividir os pontos em que os dados podem ser salvos ou a transação desfeita.


Não entrarei em detalhes sobre COMMIT e ROLLBACK porém essas transações sem o uso do SAVEPOINT, é tudo ou nada, não existe meio termo.Se for um bloco com varias instruções a serem executadas, a série inteira pode ser salva ou desfeita em grande grupos.
Vejamos um exemplo com dados reais.
SQL> select codigo,nome,tipo from fornecedor where codigo <=10;
    CODIGO NOME                                                          TIPO
---------- ------------------------------------------------------- ----------
         1 E A M TRANSPORTES E LOGISTICA LTDA                               2
         2 A G CALCADOS E COMPONENTES LTDA                                  1
         3 A P GALVANI                                                      1
         4 ABRASIVOS VINCI LTDA                                             2
         5 ACESSORIOS MINEIRAO LTDA.                                        8
         6 ACESSORIOS PALMARES LTDA                                         8
         7 ACOTUPY -IND.METALURGICAS LTDA.                                  1
        10 AMANCO BRASIL LTDA (PRODUTOS)                                    1


8 rows selected.
SQL> commit;
SQL> update fornecedor set tipo = 10 where codigo<=10;
8 rows updated.
SQL> savepoint sp_1;
Savepoint created.


Vejamos que posteriormente ao select na tabela fiz um UPDATE atualizando o campo tipo=10.E por fim o savepoint sp_1.Definimos o nome do como sp_1, mas nada importaria que fosse qualquer um outro nome.
Outro exemplo:
SQL> update fornecedor set tipo = 25 where codigo<=25;
22 rows updated.
SQL> savepoint sp_25;
Savepoint created.
SQL> update fornecedor set tipo =35 where codigo<=25;
22 rows updated.
SQL> savepoint sp_35;
Savepoint created.
SQL> update fornecedor set tipo =45 where codigo<=25;
22 rows updated.
SQL> rollback to sp_35;
Rollback complete.
SQL>  select codigo,nome,tipo from fornecedor where codigo<=25;
    CODIGO NOME                                                          TIPO
---------- ------------------------------------------------------- ----------
         1 E A M TRANSPORTES E LOGISTICA LTDA                              35
         2 A G CALCADOS E COMPONENTES LTDA                                 35
         3 A P GALVANI                                                     35
         4 ABRASIVOS VINCI LTDA                                            35
         5 ACESSORIOS MINEIRAO LTDA.                                       35
         6 ACESSORIOS PALMARES LTDA                                        35
         7 ACOTUPY -IND.METALURGICAS LTDA.                                 35
        10 AMANCO BRASIL LTDA (PRODUTOS)                                   35
        11 AKZO NOBEL LTDA (TINTAS YPIRANGA)                               35
        12 ALAGOAS DIESEL S/A                                              35
        13 ALAMO PRENSADOS DO BRASIL S.A.                                  35
        14 ALBA QUIMICA IND. E COM. LTDA                                   35
        15 ALCAN ALUMINIO DO BRASIL S/A.                                   35
        16 ALMAK INDUSTRIA E COMERCIO LTDA                                 35
        17 ALULEV ESCADA LTDA.                                             35
        18 ALUMA ALUMINIO COM.E REP.DE M.LTDA                              35
        20 AMBROSIO E JUNIOR " MOBI "                                      35
        21 AMIR-AGRO MADEIREIRA IND. RO LTDA                               35
        22 AMORIM SERGIPE TRANSPORTES LTDA                                 35
        23 ANCOL ANJOS ENGENHARIA IND COM LTDA                             35
        24 ANDREAZZA MADEIRAS S/A                                          35
        25 ANGELL-INDUSTRIA E COMERCIO LTDA                                35
22 rows selected.
SQL> commit;


Nesse outro caso, utilizei outras marcações, mais específicamente três, sp_25,sp_35 e sp_45 e por fim dei um rollback abortando abaixo do savepoint sp_35.Uma coisa a se notar é que ao efetuar o rollback da sp_35, é como se nada que foi escrito posteriormente.
As regras de utilização SAVEPOINT incluem o seguinte:


1 - Todas as declarações SAVEPOINT deve incluir um nome.
2 - Você não deve duplicar nomes SAVEPOINT dentro de uma única transação e lembre-se que uma transação é uma série de uma ou mais declarações SQL que termina com um evento de compromisso. Se você duplicar um nome, sei que você vai não receber um erro de sintaxe ou de execução. Em vez disso, o SAVEPOINT novo simplesmente substituir o SAVEPOINT anterior, efetivamente apagá-lo.
3 - Uma vez um evento de confirmação ocorre ou ainda um evento explícito ou implícito cometer todos os pontos de salvamento existentes são apagados da memória. Quaisquer referências a eles por declarações futuras TCL irá produzir um código de erro.


SQL> savepoint sp_35;
Savepoint created.
SQL> update fornecedor set tipo =45 where codigo<=25;
22 rows updated.
SQL> savepoint to sp_5;
Rollback complete.
SQL>commit;
SQL>  rollback to sp_25;

 rollback to sp_25
*
ERROR at line 1:
ORA-01086: savepoint 'SP_25' never established in this session or is invalid

No exemplo anterior, a instrução ROLLBACK na sp_25 é errado duas razões. Um, é logicamente irrelevante, uma vez que não há nada para reverter o COMMIT com tudo salvo permanentemente.
O SAVEPOINT é particularmente útil na gestão de uma grande série de transações em que a validação incremental deve ser exigido, no qual cada indivíduo validação requer uma série complexa de instruções DML que pode falhar, mas pode ser programaticamente corrigidos e validados antes de passar para o próximo incremento.

É isso ai pessoal, espero que tenham gostado.

Até a próxima.

Emerson Martins
DBA Jr

quinta-feira, 14 de julho de 2011

Criando Banco de Dados no PostgreSQL 9.0 com enconde Latin1.

Olá.

Vamos mostrar agora como criar uma base de dados no postgre 9.0.4 com o encode latin1.Alguns sistemas legados ainda utilizam esse tipo de encode.Então vamos aos passos.

Anteriormente tive erros após a instalação do postgres na criação do banco de dados:

postgres=# CREATE DATABASE teste

WITH ENCODING = 'LATIN1';
ERRO:  codificação LATIN1 não corresponde a configuração regional pt_BR.UTF-8
DETALHE:  A definição de LC_TYPE escolhida requer codificação UTF8.

Essa configuração requer algumas alterações no SO.

Nesse caso não vamos ter que recriar o cluster de dados do postgres então usaremos alguns parâmetros na criação do database;

1 -  Configurar o SO.


root@Debian01:~# /usr/sbin/dpkg-reconfigure locales



Marcar as seguinte opções:
  [*] en_US ISO-8859-1
  [*] pt_BR ISO-8859-1
  [*] pt_BR.UTF-8 UTF-8

2 - Criar o Bancos de Dados:

postgres=# CREATE DATABASE teste
WITH ENCODING = 'LATIN1'
TABLESPACE = pg_default
LC_COLLATE = 'pt_BR.iso88591'
LC_CTYPE = 'pt_BR.iso88591'
TEMPLATE template0;

postgres@Debian01:~$ /usr/local/pgsql/bin/psql -l
   Name    |  Owner   | Encoding |   Collation    |     Ctype      |   Access privileges
-----------+----------+----------+----------------+----------------+-----------------------
 teste     | postgres | LATIN1   | pt_BR.iso88591 | pt_BR.iso88591 |

Pronto!

O SO utilizado foi o Debian, mas pode ser realmente adaptada para outras distros do linux.

Abraços!

Emerson
Database Administrator.

terça-feira, 5 de julho de 2011

Alterando o Cluster de dados do Postgres para um Novo Disco

Olá caros colegas.

Desta vez vamos descrever uma situação que ainda não tinha feito anteriormente em ambiente de produção com Banco de Dados PostgreSQL, que é alterar o cluster de dados do Postgres para um novo disco.

Algumas informações que devemos saber sobre o cluster chamado PGDATA é diretório que contém vários subdiretórios  e arquivos de controle, além dos arquivos de configuração como postgresql.conf, pg_hba.conf e pg_ident.conf, embora podemos mante-los em outro local a partir da versão 8.0.

Após incluir o disco e monta-lo no nosso sistema de arquivos vamos ao que interessa.

Ambiente:
Máquina Virtual
SO: Slackware 13.1
BD: PostgreSQL 8.4.1



Passo 1 - Visualizando espaço em disco
root@serverpostgres:~# df -h
Sist. Arq.            Size  Used Avail Use% Montado em
/dev/root             7,7G  5,5G  1,9G  75% /
tmpfs                 247M     0  247M   0% /dev/shm
/dev/sdb            19,9G  151M  19,2G   2% /postgresql


Observe que o disco da partição do sistema encontra-se com espaço em disco e tamanho crítico de 75%, por essa razão precisamos colocar o cluster do banco em outro disco.

Passo 2 - Encontrar o diretório do cluster do banco
root@serverpostgres:~# ps -ef|grep -i postgres
postgres  1685     1 47 03:27 pts/0    00:00:00 /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data
postgres  1687  1685  0 03:27 ?        00:00:00 postgres: writer process
postgres  1688  1685  0 03:27 ?        00:00:00 postgres: wal writer process
postgres  1689  1685  1 03:27 ?        00:00:00 postgres: autovacuum launcher process
postgres  1690  1685  0 03:27 ?        00:00:00 postgres: archiver process   archiving 000000010000000000000007
postgres  1691  1685  0 03:27 ?        00:00:00 postgres: stats collector process
postgres  1692  1690 10 03:27 ?        00:00:00 cp pg_xlog/000000010000000000000007 /home/postgres/replication/000000010000000000000007
root      1694  1658  0 03:27 pts/0    00:00:00 grep -i postgres

Observe que o diretório que do cluster estar em /usr/local/pgsql/data.


Passo 3 - Tirar o banco de dados do ar.
root@serverpostgres:~# /etc/rc.d/rc.postgresql stop
Stopping PostgreSQL: ok
root@serverpostgres:~#

Passo 4 - Dar permissão no disco.
root@serverpostgres:/usr/local/pgsql# chown postgres:postgres /postgresql

Passo 5 - Mover o cluster
root@serverpostgres:/usr/local/pgsql# mv data /postgresql/
root@serverpostgres:/usr/local/pgsql#

Passo 6 -  Alterar o script de inicialização do postgres
root@serverpostgres:/usr/local/pgsql# vim /etc/rc.d/rc.postgresql

Script:
root@serverpostgres:/usr/local/pgsql# vim /etc/rc.d/rc.postgresql
# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.11 2010/02/23 22:15:35 momjian Exp $
## EDIT FROM HERE
# Installation prefix
prefix=/usr/local/pgsql
# Data directory
PGDATA="/postgresql/data"
# Who to run the postmaster as, usually "postgres".  (NOT "root")
PGUSER=postgres
# Where to keep a log file
-- VISUAL --                                                                    9         39,0-1        13%

Passo 7 - Reinicializar o Postgresql
root@serverpostgres:/usr/local/pgsql# ps -ef|grep -i postgres
postgres  1752     1  4 03:45 pts/0    00:00:00 /usr/local/pgsql/bin/postmaster -D /postgresql/data
postgres  1754  1752  0 03:45 ?        00:00:00 postgres: writer process
postgres  1755  1752  0 03:45 ?        00:00:00 postgres: wal writer process
postgres  1756  1752  0 03:45 ?        00:00:00 postgres: autovacuum launcher process
postgres  1757  1752  0 03:45 ?        00:00:00 postgres: archiver process
postgres  1758  1752  0 03:45 ?        00:00:00 postgres: stats collector process
root      1761  1658  0 03:45 pts/0    00:00:00 grep -i postgres
root@serverpostgres:/usr/local/pgsql#

Processo concluído!Veja que o cluster já encontra-se no novo disco montado na partição /postgresql.
O processo pode ser demorado, vai depender também do tamanho do banco, em ambientes de produção com bases maiores o processo pode demorar um pouco para que a base seja transferida com sucesso.


Espero que tenham gostado!
Abraços!

Emerson Martins