sexta-feira, 15 de julho de 2011

PostgreSQL - Tunando seu shmmax e shmall

   Simples programa em shell para tunar estes parâmetros de Kernel:


#!/bin/bash

page_size=`getconf PAGE_SIZE`
phys_pages=`getconf _PHYS_PAGES`
shmall=`expr $phys_pages / 2`
shmmax=`expr $shmall \* $page_size`
sysctl -w kernel.shmmax = $shmmax
sysctl -w kernel.shmall = $shmall
echo kernel.shmmax = $shmmax
echo kernel.shmall = $shmall

   Após executar o código em um .sh da vida você terá o retorno dos parâmetros de kernel aplicados e indicados pela documentação do PostgreSQL.

sexta-feira, 1 de julho de 2011

PostgreSQL - Corrigindo tabela corrompida

Situação: Tabela com linhas corrompidas. 
Como identificar: Erro ao realizar o dump, select, delete na tabela. 


O problema é que quando isto ocorre o PostgreSQL informa que existe um erro e referencia o 'toast value', o que não é nada concreto para uma remoção por DELETE convencional. 


Exemplo:


ERROR: missing chunk number 0 for toast value 16983210 in pg_toast_939217
1532317



Então primeiro temos que identificar quais linhas desta tabela estão corrompidas, dai se utiliza o comando na console:


for ((i=0; i<TOTALROWS; i++ )); do psql -U postgres mydb -c "SELECT * FROM public.mytable LIMIT 1 offset $i" >/dev/null || echo $i; done


TOTALROWS: Altere o TOTALROWS pelo número total de linhas da tabelas depois de executar um ANALYZE. 
postgres: Role que executará a query, no caso o 'postgres' 
mydb: Sua database
mytable: A tabela alvo


Este comando varrerá a tabela linha a linha e pelo retorno você saberá quais linhas estão danificadas, segue exemplo de saída:


ERROR:  missing chunk number 0 for toast value 1269808 in pg_toast_93917
162558
ERROR:  missing chunk number 0 for toast value 1269810 in pg_toast_93917
162559


No caso acima sabemos agora que as linhas 162558 e 162559 estão corrompidas. 


Um DELETE não funcionará, não se iluda. Primeiro é necessário obter o CTID das linhas, pra quem quer ai vai a explicação do que é o CTID: http://www.postgresql.org/docs/8.4/static/datatype-oid.html


Então o próximo passo é obter este valor para ai sim fazer o DELETE, mas sugiro antes fazer um backup da tabela sem as linhas corrompidas:


CREATE TABLE mytable_bkp1 AS SELECT * FROM mytable LIMIT 162558;
CREATE TABLE mytable_bkp2 AS SELECT * FROM mytable OFFSET 162559;


Agora vamos ao CID:


SELECT CTID FROM mytable LIMIT 2 OFFSET 162558;


Agora sim, vamos remover as crianças e salvar o mundo:


DELETE FROM mytable WHERE CTID IN(SELECT CTID FROM mytable LIMIT 2 OFFSET 162558);


Tabela salva, todo mundo feliz. E sim, você perdeu as linhas deletadas!