quinta-feira, 28 de maio de 2015

Tipos de backup do PostgreSQL

Diferentes maneiras de fazer backup dos bancos de dados do PostgreSQL.
O PostgreSQL possui varias formar de se fazer backup, podendo ser através de arquivos SQL, tar, ou customizado, além de poder fazer backup de apenas uma base ou todos de uma só vez, é para o caso de backups muito grandes a opção de dividir o arquivo em vários; vou mostrar as formas mais utilizadas de backup no PostgreSQL.

Backup de um único banco em formato SQL
pg_dump -U usuario -d banco > backup.sql

Backup de um único banco em formato tar
pg_dump -Ft -U usuario -d banco > backup.tar

Backup de um único banco em formato especifico do PostgreSQL
pg_dump -Fc -U usuario -d banco > backup

Por padrão o pg_dump não faz backup de objeto grandes dentro do banco, para ativar esta opção é necessário utilizar a opção "-b" como por exemplo.
Backup de um único banco em formato especifico e com objetos grandes
pg_dump -Fc -b -U usuario -d banco > backup

Backup de uma única tabela de único banco
pg_dump -Fc -b -U usuario -d banco -t nomedatabela > backup

Backup de todos os bancos do servidor 
pg_dumpall -Fc -b -U usuario > backup

Backup remoto de um banco
pg_dump -h hostremoto -d nomebanco | psql -h hostlocal -d banco

Backup em multivolumes (exemplo de volumes de 600MB)
pg_dump nomebanco | split -m 600 nomearquivo

OBS: m para 1Mega, k para 1K, b para 512bytes

Pessoalmente eu prefiro utilizar como backup o formato customizado com a opção dos blocos grandes ativados. "-Fc -b", esse tipo de backup é mais rápido tanto na hora de fazer como na hora de voltar além de sair em um tamanho bem reduzido em relação aos demais.

terça-feira, 12 de maio de 2015

Listando as 10 maiores tabelas no PostgreSQL

Para listar as maiores tabelas do seu banco de dados, utilize a consulta abaixo:

WITH table_stats AS (
  SELECT
    schemaname,
    tablename,
    pg_relation_size(schemaname || '.'|| tablename) as table_size,
    (pg_total_relation_size(schemaname || '.'|| tablename) - pg_relation_size(schemaname || '.'|| tablename)) as index_size,
    pg_total_relation_size(schemaname || '.'|| tablename) as total_size
  FROM
    pg_tables
)
SELECT
  table_stats.schemaname,
  table_stats.tablename,
  pg_size_pretty(table_stats.table_size) as table_size,
  pg_size_pretty(table_stats.index_size) as index_size,
  pg_size_pretty(table_stats.total_size) as total_size
FROM
  table_stats

WHERE
  -- ajuste o filtro conforme sua necessidade!
  table_stats.schemaname = 'public'
ORDER BY
  table_stats.total_size desc,
  table_stats.index_size desc,
  table_stats.table_size desc
LIMIT 10;

Tamanho das tabelas no PostgreSQL

Em muitos casos é preciso saber o espaço em que as tabelas do banco de dados estão utilizando em disco, para fins de monitoramento e decisão de estruturação de banco. Para tal tarefa no PostgreSQL o comando abaixo resolve o problema.


SELECT esquema, tabela,
       pg_size_pretty(pg_relation_size(esq_tab)) AS tamanho,
       pg_size_pretty(pg_total_relation_size(esq_tab)) AS tamanho_total
  FROM (SELECT tablename AS tabela,
               schemaname AS esquema,
               schemaname||'.'||tablename AS esq_tab
          FROM pg_catalog.pg_tables
         WHERE schemaname NOT
            IN ('pg_catalog', 'information_schema', 'pg_toast') ) AS x
 ORDER BY pg_total_relation_size(esq_tab) DESC;

A coluna tamanho mostra o tamanho que os registros (tuplas) da tabela está ocupando no disco, e a coluna tamanho_total inclui também os TOASTs e os índices associados à tabela.
Com essa consulta, é possível inclusive montar scripts (em shellscript, perl, python, groovy, etc..) de monitoramento do banco, por exemplo: caso a tabela tal, ou a soma de todas as tabelas chegar a X Mb, envie um email de alerta. Outra utilização seria de geração de indicadores para análise de tendência da expansão do banco.

segunda-feira, 11 de maio de 2015

Localizando e Excluindo Registros Duplicados


Evitar a ocorrência de registros duplicados garante a integridade de um banco de dados, pra isso, planejar e prever situações no ato da modelagem do banco são imprescindíveis para não ter dor de cabeça.

No entanto, é comum nos deparamos com bases de dados repletas de registros duplicados, o que pode ter ocorrido por conta de um mal planejamento ou, forçado devido a importação de dados externos.

Localizar e eliminar estes registros, será o que veremos neste artigo.

  • Simulando Registros Duplicados

A forma mais simples de localizar os duplicados é através dos comandos GROUP BY e HAVING. Vamos popular uma tabela de produtos a fim de duplicar registros:
 Create Table produto (  
  id_produto bigint not null,  
  descricao varchar (100),  
  estoque int not null default 0  
 ) ;
  Insert Into produto    
  Values   
  (1, "Produto A", 10),   
  (2, "Produto B", 10),   
  (3, "Produto C", 10),   
  (4, "Produto B", 12),   
  (5, "Produto C", 8),   
  (6, "Produto D", 10),   
  (7, "Produto E", 10),   
  (8, "Produto E", 10),   
  (9, "Produto F", 10);   

  • Identificando os Duplicados

Vejam que os produtos B, C e E estão duplicados, vamos então apresenta-los utilizando um simples select:
 select   
  *   
 from  
   produto   
 group by descricao   
 having count(descricao) > 1 ;  
 id_produto descricao estoque  
 ---------- --------- -------  
      2 Produto B    10  
      3 Produto C    10  
      7 Produto E    10  
Localizar os registros foi possível pois, agrupamos os diferentes produtos em um só (group by), após, adicionamos a condição para que somente os registros que contenham mais de uma ocorrência (having...) fossem apresentados. (Mais de uma ocorrência após agrupado). No exemplo, filtramos somente os registros com mais de uma ocorrência, mas você pode especificar a quantidade desejada.

Alterar Schema de Tabela no PostgreSQL

Em sua configuração original, quando criamos uma tabela (ou qualquer outro objeto) no PostgreSQL sem especificar o schema que ela deve ficar, automaticamente o PG irá cria-lá no schema public.


Caso você necessite alterar o schema de suas tabelas, você pode realizar um alter table, através da seguinte 
instrução SQL:

 ALTER TABLE SCHEMA.SUA_TABELA SET SCHEMA NOME_SCHEMA_DESTINO;  

No exemplo, aponto o schema qual a tabela esta atualmente, desta forma posso estar conectado a qualquer 
schema dentro do mesmo banco de dados que conseguirei realizar a mudança.

Como zerar um campo auto_increment no MySQL

Você pode redefinir o valor do campo auto increment de duas formas, vejamos:

1º - Através de Alter Table.

 ALTER TABLE tabela AUTO_INCREMENT = 1;  

2º - Através de Truncate Table (Cuidado com esta alternativa).

 TRUNCATE TABLE tabela;  

No primeiro caso os dados são mantidos em sua tabela, somente os valores do campo que você configurou como auto incremento serão atualizados, já no segundo caso toda sua tabela é apagada, por isso, somente execute este passo se realmente deseja reiniciar a numeração sem se importar com os dados, e o mais importante, não custa ter um backup da tabela.

quinta-feira, 7 de maio de 2015

Configurando Stream Replication No PostgreSQL 9

Esse tutorial explica como configurar 2 servidores PosgreSQL como master e slave com stream replication, é bem simples.
Cenário:
  • Master 192.168.1.200 (Debian 6 – PostgreSQL 9)
  • Slave 192.168.1.201 (Debian 6 – PostgreSQL 9)
Configuração do Master: 
No arquivo postgresql.conf, alterar as seguintes opções:
listen_address = ‘*’ # Reponderá por qualquer ip cadastrado no server
wal_level = hot_standby
max_wal_senders = 1 # Número maximo de servidores slave
wal_keep_segments = 32
No arquivo pg_hba.conf, adicione o servidor slave para replicação:
host    replication     postgres         192.168.1.201/32        trust
Configuração do Slave 
Criar o arquivo recovery.conf no mesmo diretório do arquivo postgresql.conf, com o seguinte conteúdo:
standby_mode = ‘on’
primary_conninfo = ‘host=192.168.1.200 port=5432 user=postgres’
trigger_file = ‘/tmp/pgsql.trigger’
Parar o PostgreSQL dos 2 servidores:
[postgres@server ~]$ /usr/local/pgsql/bin/pg_ctl stop -D /usr/local/pgsql/data/
[postgres@client ~]$ /usr/local/pgsql/bin/pg_ctl stop -D /usr/local/pgsql/data/
Agora você deverá copiar todo o conteúdo do data do master para o data do slaver:
[postgres@server ~]$ rsync -a -v -e ssh /usr/local/pgsql/data/ 192.168.1.201:/usr/local/pgsql/data/ –exclude postmaster.pid
E no arquivo postgresql.conf do slave, alterar as seguintes opções:
hot_standby = on
Agora você pode iniciar os 2 serviços do PostgreSQL:
[postgres@server ~]$ /usr/local/pgsql/bin/pg_ctl start -D /usr/local/pgsql/data/
[postgres@client ~]$ /usr/local/pgsql/bin/pg_ctl start -D /usr/local/pgsql/data/
Para verificar se a replicação está certa você pode ver assim:
No master:
[postgres@server ~]$ ps ax | grep sender
1573 ?        Ss     0:00 postgres: wal sender process postgres 192.168.1.201(53314) streaming 0/C0000D0
No slave:
[postgres@server ~]$ ps ax | grep receiver
3180 ?        Ss     0:00 postgres: wal receiver process   streaming 0/C0000D0
Testando a replicação:
No master crie uma tabela teste e popule:
postgres=# CREATE TABLE tabelaTeste (valor varchar(30));
postgres=# INSERT INTO tabelaTeste VALUES(‘teste1′);
postgres=# INSERT INTO tabelaTeste VALUES(‘teste2′);
Agora no server slave (stand by) veja se a tabela “tabelaTeste| foi criada:
postgres=# SELECT * FROM tabelaTeste;
Se o resultado for esse abaixo, está correto:
valor
—————
teste1
teste2
(2 rows)

terça-feira, 5 de maio de 2015

COMO RECUPERAR BANCO DO POSTGRES PELO DIRETÓRIO


Pode acontecer de você precisar recuperar um banco de dados Postgres, mas tendo a seu dispor apenas uma cópia de um HD como backup, e não um arquivo de backup gerado com o comando pg_dump

Neste caso, após algumas tentativas, consegui restaurar o banco e compartilho aqui o procedimento que funcionou comigo. Ou seja, recuperação do banco através dos diretórios. 

Antes de tudo, instale no servidor a versão do Postgres idêntica à versão instalada no backup. 

Depois, pare o serviço Postgres. No caso do Debian, onde a dica foi testada, executei: 


# sh /etc/init.d/postgresql stop 

Depois, copie do backup os seguintes diretórios, substituindo os mesmos diretórios no servidor atual. Por exemplo, usando o Postgres 9.3:
  • /var/lib/postgresql/9.3
  • /usr/share/postgresql/9.3
  • /etc/postgresql/9.3

Obs.: recomendo renomear os diretórios originais para "nome-backup", ao invés de simplesmente substituí-los. 

É necessário dar permissão para um diretório, após a cópia para o servidor: 

# chmod 700 /var/lib/postgresql/9.3 -R 

Inicialmente usei "777", mas o próprio sistema informou que era para mudar para 700, quando tentei iniciar o serviço. 

Depois inicie o serviço: 

# sh /etc/init.d/postgresql start 

Pronto! Se tiver o phpPgAdmin instalado, poderá acessá-lo para visualizar o banco, acessando: 

Talvez exista uma forma mais fácil, mas essa foi a que eu encontrei. 

Foi na base do comando find que encontrei os referidos diretórios e fui copiando para o servidor. 

Espero ajudar alguém na mesma situação.
Abraço! 

quinta-feira, 9 de abril de 2015

CRIAÇÃO DE 1° SUPER USUÁRIO NO POSTGRESQL


Depois de instalado seu SGBD postgres, como criar seu 1° usuário? Qual a senha de root? Qual a senha padrão? 

Esta dica é para iniciantes. 

Após a instalação dos seu PostgreSQL no Linux, como criar seu 1° usuário para administração do banco? 

Simples, na máquina com o banco instalado siga os seguintes passos. 

Logue-se como root, tecle "su root" ou "sudo -i" no Ubuntu (no terminal a mensagem padrão deve terminar com #). 

Entre como usuário postgres comando: 

# su postgres 

Conecte no banco comando: 

$ psql 

Agora deve aparecer a frase de boas vindas (Bem vindo ao psql...) e você está no terminal do posgres. 

Entre com o comando: 

CREATE USER nomedousuario SUPERUSER INHERIT CREATEDB CREATEROLE; 

e tecle enter. 

Depois entre com o comando: 

ALTER USER nomedousuario PASSWORD 'senha'; 

e tecle enter. 

Pronto! Usuário criado. 

Agora para este usuário acessar o banco de outras máquinas da rede devemos liberar se acesso no arquivo pg_hba.conf com o usuário root, siga os passos. 

A localização deste arquivo varia segundo a distribuição Linux, no SUSE está em ~postgres/data/pg_hba.conf, no Ubuntu está em/etc/postgres/8.4/pg_hba.conf. Adicione a linha: 

host    all         nomedousuario         0/0                   password

Para que seu usuário tenha acesso de qualquer máquina a todos os bancos de dados neste servidor. 

Feito isso reinicie o postgres ou recarregue como o comando: 

# /etc/init.d/posgresql restart 
ou 
# /etc/init.d/posgresql reload 

segunda-feira, 6 de abril de 2015

INSTALANDO O POSTGRES 9.4 NO RHEL 7

Recentemente precisei instalar um Postgres DB em uma VM RHEL 7 para testes. Aproveitei para compartilhar os passos seguidos aqui no Blog. Esse passo a passo deve funcionar em qualquer Distro RHEL-like: Fedora, Centos, Scientific Linux, OEL, etc.
A instalação é a mais básica possível, pois o propósito desse DB é apenas para testes e laboratórios. Nada de tuning ou personalização.
Instale os seguintes pacotes do repositório Postgresql.org oficial.
[rsoares@rhel7-server-1 ~]$ sudo yum install http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-redhat94-9.4-1.noarch.rpm
[rsoares@rhel7-server-1 ~]$ sudo yum groupinstall "PostgreSQL Database Server 9.4 PGDG"
Inicialize o Postgres DB.
sudo /usr/pgsql-9.4/bin/postgresql94-setup initdb
Habilite e teste o serviço do Postgres.
[rsoares@rhel7-server-1 ~]$ sudo systemctl enable postgresql-9.4.service
[rsoares@rhel7-server-1 ~]$ sudo systemctl start postgresql-9.4.service
[rsoares@rhel7-server-1 ~]$ sudo systemctl stop postgresql-9.4.service
Troque para o usuário de sistema do postgres.
[rsoares@rhel7-server-1 ~]$ sudo su - postgres
Altere o pg_hba.conf (espécie de “firewall” do Postgres) para permitir o acesso externo através da rede da VM.
-bash-4.2$ vim /var/lib/pgsql/9.4/data/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD

# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 ident
host all all 192.168.122.0/24 md5
Altere o binding do serviço para aceitar conexões em qualquer endereço IP da VM.
-bash-4.2$ vim /var/lib/pgsql/9.4/data/postgresql.conf
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

# - Connection Settings -

listen_addresses = '*' # what IP address(es) to listen on;
Logout do postgres user.
Ctrl + D no terminal
Reinicie o serviço postgres
[rsoares@rhel7-server-1 ~]$ sudo systemctl start postgresql-9.4.service
[rsoares@rhel7-server-1 ~]$ sudo systemctl status postgresql-9.4.service
postgresql-9.4.service - PostgreSQL 9.4 database server
Loaded: loaded (/usr/lib/systemd/system/postgresql-9.4.service; enabled)
Active: active (running) since Thu 2014-11-06 17:21:38 BRST; 1s ago
Process: 24832 ExecStop=/usr/pgsql-9.4/bin/pg_ctl stop -D ${PGDATA} -s -m fast (code=exited, status=0/SUCCESS)
Process: 25292 ExecStart=/usr/pgsql-9.4/bin/pg_ctl start -D ${PGDATA} -s -w -t 300 (code=exited, status=0/SUCCESS)
Process: 25286 ExecStartPre=/usr/pgsql-9.4/bin/postgresql94-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
Main PID: 25296 (postgres)
CGroup: /system.slice/postgresql-9.4.service
├─25296 /usr/pgsql-9.4/bin/postgres -D /var/lib/pgsql/9.4/data
├─25297 postgres: logger process
├─25299 postgres: checkpointer process
├─25300 postgres: writer process
├─25301 postgres: wal writer process
├─25302 postgres: autovacuum launcher process
└─25303 postgres: stats collector process
Confira o binding do serviço na porta TCP padrão so Postgres (5432)
[rsoares@rhel7-server-1 ~]$ netstat -tanp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:55970 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN -
tcp 0 0 192.168.122.65:22 192.168.122.1:39634 ESTABLISHED -
tcp6 0 0 ::1:25 :::* LISTEN -
tcp6 0 0 :::47021 :::* LISTEN -
tcp6 0 0 :::111 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 ::1:631 :::* LISTEN -
tcp6 0 0 :::5432 :::* LISTEN -
Crie um novo DB User
-bash-4.2$ createuser -d -l -P --interactive NEW_DB_USER
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
Crie um novo Data Base
-bash-4.2$ createdb -e -O NEW_DB_USER NEW_DB "New DataBase"
CREATE DATABASE "NEW_DB" OWNER "NEW_DB_USER";
COMMENT ON DATABASE "NEW_DB" IS 'New DataBase';

quinta-feira, 2 de abril de 2015

Paginando resultados com limit e offset

Neste post, veremos como utilizar o LIMIT e o OFFSET para paginar resultados de uma SQL.
A cláusula LIMIT é utilizada para limitar o número de resultados de uma SQL. Então, se sua SQL retornar 1000 linhas, mas você quer apenas as 10 primeiras, você deve executar uma instrução mais ou menos assim:
1
SELECT coluna FROM tabela LIMIT 10;
Agora, vamos supor que você quer somente os resultados de 11 a 20. Com a instrução OFFSET fica fácil, basta proceder da seguinte forma:
1
SELECT coluna FROM tabela LIMIT 10 OFFSET 10;
O comando OFFSET indica o início da leitura, e o LIMIT o máximo de registros a serem lidos. Para os registros de 61 a 75, por exemplo:
1
SELECT coluna FROM tabela LIMIT 15 OFFSET 60;
Com este recurso, fica fácil paginar os resultados de uma SQL e mostrar ao usuário apenas a página, ao invés de retornar todos os registros da tabela. Uma tabela com 2000 registros, por exemplo, fica muito melhor mostrar ao usuário de 10 em 10, por exemplo, e diminui a carga no banco de dados, melhorando a sua performance.