3 noites com Postgres

Setembro 11th, 2008

1ª noite: O flerte

Tudo começou com um

vacuuming of database “banco” failed: ERROR: invalid page header in block 17850 of relation “tabela”

Minha primeira reação foi de espanto quando vi aquilo no e-mail enviado pela Crontab. Aos poucos fui me acalmando e comecei a procurar as razões para aquele comportamento estranho. Olhei os logs do servidor, do banco de dados. Tentei algumas investidas com REINDEX TABLE e com VACUUM mas nada adiantou. Ah, se o Postgres tivesse REPAIR TABLE… A resposta era sempre de rejeição:

pg_dump: socket not open
pg_dump: SQL command to dump the contents of table “tabela” failed: PQendcopy() failed.
pg_dump: Error message from server: socket not open
pg_dump: The command was: COPY public.tabela (campo1, campo2, campo3, campo4, campo5) TO stdout;

Aquilo acendeu uma chama dentro de mim. Quanto mais difícil ficava, mais interesse eu tinha. Quando dei por mim, já estava envolvido demais para deixar de lado.

2ª noite: Preliminares

A conquista era agora uma questão de honra. Comecei a olhar em fóruns e listas de discussão por dicas de pessoas que já passaram pela mesma situação mas quem realmente me ajudou foi o Tom Lane (integrante do core team de desenvolvimento do Postgresql). Segundo ele, só havia um jeito de resolver:

That part sounds more like the table row is corrupted :-(. If you aren’t in a position to restore the whole table from backup, you’ll need to try to identify and wipe out the broken row. Usually zeroing its whole page is the easiest way to do this, though you’ll want to see what else is on that page first. Check the PG archives for discussions of recovering from corrupted-data scenarios.

E assim, me preparei para a grande noite.

3ª noite: O clímax

Para alguns, a descrição dos detalhes sórdidos do que aconteceu naquela noite pode ser traumática. Se você se impressiona facilmente, pare de ler por aqui.
Quando cheguei em casa, tratei logo de tirar a roupa. Fiquei só de cueca. Abri um terminal e comecei com um ssh no servidor. Seguindo dicas do pessoal do Pgsql-bugs, peguei o código fonte do pg_dumpfile e compilei. Para tal, precisei do código fonte do Postgres (postgresql-source) e dos headers (postgresql-devel) também. Tive que alterar o Makefile na mão porque não tinha o configure. Feito isso, tratei de verificar se o bloco danificado na página de dados tinha alguma informação crítica.

pg_dumpfile -i -d -R 17850 data/base/1777197/1777476

O primeiro parâmetro é o bloco com problema. O segundo é o arquivo de dados da tabela que pode ser encontrado com o comando:

oid2name -t tabela -d banco

Para a minha sorte, não havia nada que não pudesse ser apagado. Então parti para a ação, cortando o mal pela raiz:

dd if=/dev/zero of=data/base/1777197/1777476 bs=8k seek=17850 count=1

Rezei para que o postmaster não resolvesse escrever nessa tabela no mesmo instante que eu executava o dd, já que, em nenhum momento, parei o servidor postgres. Estava apreensivo com o resultado. Será que deu certo? Vamos fazer uma consulta…

SELECT * FROM tabela WHERE ctid=’(17850,1)’;

——-
(0 rows)

Uma resposta sem muita emoção mas que, definitivamente, comprovava a eficácia do método. Para ter certeza de que estava tudo bem, fiz um pg_dump na tabela e … funcionou sem problemas.

Naquela noite não consegui dormir direito. Uma mistura de excitação e sensação de dever cumprido.

P.S.: Em alguns casos, configurar a variável do Postgres zero_damaged_pages para on e fazer um vacuum ou um dump, resolve o problema de cabeçalho de página inválido. Cuidado! Isso pode causar perda de dados.

“P2P com NET Vírtua” ou “Alegria de pobre”

Abril 24th, 2007

Como já era esperado, as operadoras de telecomunicações não ficaram paradas por muito tempo vendo suas redes sendo degradadas pelo P2P. Há uns dois anos atrás houve um rebuliço na “comunidade” P2P quando as operadoras começaram a limitar tráfego de protocolos que não fossem os já bem conhecidos HTTP, FTP, HTTPS, etc. Mas a mente humana é fantástica quando se trata de desafiar regras e imposições e logo apareceu a criptografia dos cabeçalhos de pacotes P2P. Foi o suficiente para acalmar os ânimos dos “hard downloaders” (entre os quais eu me incluo).

Porém, já dizia a minha querida avó, que Deus a tenha: alegria de pobre dura pouco. Dessa vez até que durou um bom tempo e, então, na quarta-feira da semana passada começou o desespero novamente. Abri o µtorrent para conferir quantos episódios já tinham sido baixados e minha lista de downloads estava cheia, todos em 0% completado. Buscando uma explicação para o fato, descobri que o programa não estava conseguindo conectar com o tracker. Alguns testes depois, tive a certeza de que a Vírtua estava bloqueando minhas conexões de saída que não fossem para portas conhecidas, independente do protocolo utilizado. Isso quer dizer que nenhuma conexão HTTP em porta diferente da 80 podia ser estabelecida. Adeus bittorrent tracker, adeus CPanel, adeus Webmin. Indignado com a audácia desses provedores sem alma, liguei para o Atendimento ao Cliente, opção 2, 2, 8, 4, 6, 2, 3 digitei meu código de cliente de 12 algarismos, falei com 53 atendentes diferentes e finalmente consegui a confirmação da qual precisava: a NET Vírtua estava bloqueando as portas que não fossem HTTP, FTP, DNS, HTTPS, POP, SMTP. A atendente ainda disse que isso estava no contrato. E lá fui eu procurar no contrato algo que falasse sobre conexões. Achei a seguinte cláusula 08.08 do contrato do Novo Vírtua:

08.08 O NOVO VÍRTUA, nas modalidades RESIDENCIAL e CONDOMÍNIO, não permite a disponibilização do(s) terminal(is) de computador a ele conectado(s) como servidor(es) de dados de qualquer espécie, inclusive: servidores Web, FTP, SMTP, POP3, redes virtuais privadas e quaisquer conexões entrantes que caracterizem ofertas de serviços pelo ASSINANTE, sendo tais disponibilizações exclusivas da modalidade EMPRESA.

Como diz o contrato, a Vírtua se reserva o direito de bloquear as conexões entrantes mas em nenhum momento foram citadas restrições às conexões de saída. Assim sendo, peguei o número do protocolo de atendimento e fiz uma reclamação no site da Anatel. Com uma ajudinha de um amigo que trabalha lá (valeu Pontes!) o negócio andou. Finalmente, ontem, desbloquearam minhas conexões mas é claro que eles não iam entregar tudo de bandeja. As conexões são feitas sem problemas mas a taxa de transferência está lá em baixo. E olha que eu estou usando cabeçalhos criptografados. Provavelmente, agora estão dando prioridade ao tráfego Web e jogando todo o resto no melhor esforço. Resultado: Ou eu dou um jeito de encapsular o tráfego P2P em pacotes HTTP/HTTPS ou vou ter que contratar o Vírtua Empresa e morrer em 200 contos por mês.

Barra de favoritos com múltiplas linhas no Firefox

Janeiro 24th, 2007

Uma coisa que me incomodava no Firefox era sua barra de favoritos quando ficava cheia e aparecia uma setinha para mostrar os demais que não cabiam na tela. Cheguei até a aumentar a resolução do X para ver se cabiam todos em uma única linha. Por algum tempo isso foi suficiente mas na medida em que o número de sites interessantes e frequentemente visitados aumentava a setinha aperecia novamente. Agora, meus problemas acabaram! Encontrei na net uma dica para que a barra de favoritos possa ter múltiplas linhas e assim a setinha não aparece mais. Resumindo, basta editar um arquivo dentro da pasta chrome, dentro do diretório do seu profile (algo do tipo /home/user/.mozilla/firefox/dcrna2c8.default/chrome/). Abra o arquivo userChrome.css (crie-o se ele não existir) e insira as seguintes linhas:

/* Multi-row bookmarks toolbar */
#bookmarks-ptf {display:block}
#bookmarks-ptf toolbarseparator {display:inline}

Pronto. É só salvar e reiniciar o Firefox.

Intel, a verdadeira vilã do DRM

Janeiro 22nd, 2007

Nunca achei que fosse dizer isso mas considerando os ataques que a Microsoft vem sofrendo sobre a proteção de conteúdo digital embutida no seu sistema operacional recém-lançado, devo afirmar que ela não é a grande vilã da história. Existem muitas políticas adotadas pela Microsoft com as quais não concordo porém essa não é uma delas.

Pesquisando sobre restrições aplicadas a conteúdo digital (DRM) me deparei com o termo HDCP, o qual desconhecia completamente. HDCP é a sigla para High-Bandwidth Digital Content Protection que significa Proteção de Conteúdo Digital de Banda Larga (em aplicações audiovisuais, banda larga geralmente significa alta definição). Essa tecnologia foi desenvolvida pela Intel Corporation para controlar a transmissão de áudio e vídeo através de conexões digitais como o DVI (Digital Visual Interface) e o HDMI (High-Definition Multimedia Interface). Seu objetivo é não permitir que o conteúdo digital seja transmitido descriptografado e dessa forma garantir que apenas dispositivos compatíveis com o “padrão” HDCP possam receber conteúdo de alta definição. Para atingir este objetivo, três processos são utilizados:

- a autenticação só permite que dispositivos licenciados recebam conteúdo de alta definição (ficam de fora todos os equipamentos com recepção analógica ou com recepção digital sem suporte à HDCP)
- o conteúdo é transmitido criptografado através das conexões digitais impedindo sua interceptação (mais abaixo veremos que não é bem assim).
- um mecanismo de revogação de chaves permite que dispositivos que violem a licença possam ser facilmente banidos de receber conteúdo de alta definição.

Qualquer dispositivo que não esteja de acordo com esses procedimentos não estará autorizado a receber conteúdo de alta definição e , portanto, deverá recebê-lo em definição padrão (para vídeo digital isso significa que a resolução deverá passar de 1920×1080 para 960×540 , ou seja, um quarto da resolução original ).

Como você pode perceber, não é uma política que a Microsoft resolveu adotar para punir os usuários piratas e sim para se adequar à nova tecnologia, da mesma forma que todos os fabricantes de equipamentos de alta definição com conectores DVI e HDMI farão. Se temos que culpar alguém, que seja a Intel. Não estou defendendo a Microsoft muito menos seu sistema operacional bugado, apenas estou tentando mostrar que é simplista pensar que uma única empresa é inteiramente responsável pelas restrições de uso de conteúdos digitais.

Agora, vêm algumas boas notícias:

- Os grandes estúdios de cinema aparentemente fizeram um acordo para não implementar o ICT (Image Constraint Token), mecanismo que ativa a redução na definição do vídeo; pelo menos, em um futuro próximo.
- Pesquisadores da Carnegie Mellon University conseguiram quebrar a segurança do HDCP (detalhes podem ser encontrados aqui).
- As placas de vídeo fabricadas pela ATI e pela Nvidia não estão preparadas para transmitir vídeo de alta definição com HDCP mesmo tendo suporte à esta tecnologia porque as empresas não adquiriram as licenças da Intel (mascarada como Digital Content Protection LLC). Muitas pessoas vão ficar bravas.

A partir de hoje, começo a olhar essa revolução digital com outros olhos. Por um lado vivenciamos a experiência da imagem de alta definição e por outro ficamos cada vez mais presos a licenças e padrões ditados pelos grandes fabricantes.

Instalando e Configurando o APC

Janeiro 19th, 2007

Este é um pequeno tutorial de como instalar o APC (Alternative PHP Cache), uma extensão livre do PHP que faz cache do código intermediário reduzindo consideravelmente o tempo de resposta do servidor Web. Dando continuidade ao tutorial anterior de otimização do Apache, vamos otimizar o funcionamento do interpretador PHP.

Instale os pacotes de desenvolvimento do php e do apache. Em uma máquina rodando Debian (ou derivados), faça:

# aptitude update; aptitude install php-dev apache-dev

Esses pacotes contém alguns “programinhas” que facilitam a compilação de extensões para o php e para o apache (phpize, php-config, apxs).

Baixe a última versão do APC ou , se você utiliza uma versão do PHP muito antiga, aquela que for mais adequada. Execute:

# tar xvzf APC-3.0.x.tgz
# cd APC-3.0.X
# phpize
# ./configure –enable-apc-mmap –with-apxs –with-php-config=/usr/bin/php-config –prefix=/usr
# make
# make install

Agora, basta colocar as linhas abaixo no arquivo php.ini (o meu está em /etc/php4/apache/php.ini). Se você estiver utilizando php5 não utilize o php.ini, crie um arquivo chamado apc.ini no diretório /etc/php5/conf.d com as mesmas linhas:

extension=apc.so
apc.enabled=1
apc.shm_segments=1
apc.optimization=0
apc.shm_size=128
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask=/tmp/apc.XXXXXX

Simples, não? E o ganho de performance é bastante considerável. Em alguns casos a resposta pode ser até 10 vezes mais rápida, porém o ganho médio é de 5 vezes.
Maiores informações sobre como configurar o APC e explicações detalhadas sobre os parâmetros de configuração estão disponíveis aqui.

Tunando o Apache 1.3.x ou 2.x(prefork)

Janeiro 13th, 2007

Depois de apanhar muito de servidores web lotados com centenas de requisições simultâneas resolvi dar uma pesquisada na net para entender os motivos da baixa performance e solucionar definitivamente o problema. O intuito não era criar um cluster com vários servidores respondendo pelo mesmo nome mas aproveitar ao máximo os recursos de um servidor. Vou relatar aqui as configurações que considero mais importantes, ou seja, as que produziram melhorias perceptíveis. Não vou entrar na discussão de qual o interpretador é mais eficiente (php , python, perl ou afins). Use ao seu gosto.

Um fator de extrema importância para um servidor web é a frequência com que ele utiliza swap. Devido à natureza do serviço espera-se sempre uma resposta rápida do servidor e o processo de swap é um fator altamente degradante para o tempo de resposta. Quando a memória física (RAM) se esgota, o sistema operacional salva algumas informações pouco acessadas da memória no disco rígido, em um processo denominado troca ou swap. Esse processo apesar de necessário não deve ser utilizado com frequência pois a leitura e a escrita no disco são de 10 a 100 vezes mais lentas do que na RAM, dependendo da máquina. Por isso devemos dimensionar o servidor web baseado exclusivamente na quantidade de memória RAM.

Façamos a seguinte conta:

Quantidade de memória RAM total - (menos) Quantidade de memória ocupada por programas quando o servidor web está desligado.
Agora vamos dividir o resultado pela quantidade média de memória ocupada por um processo filho do Apache (em torno 3M quando utiliza-se html puro, sem nenhuma linguagem interpretada e em torno de 20M para html+php) - você pode utilizar o top para descobrir esse valor.

O resultado obtido da divisão anterior deve ser o número máximo de clientes que seu host pode atender simultaneamente sem utilizar swap. Não se espante se o número for baixo (20, 30, 50,..). Mais adiante vamos fazer algumas contas que vão mostrar quantas requisições o seu servidor pode atender por minuto. Coloque este número como o valor MaxClients do Apache.

Se o seu host trabalha sempre perto da capacidade máxima configure o valor do StartServers, MinSpareServers e MaxSpareServers próximo ao valor do MaxClients (ex:80%), se não você pode trabalhar com um valor perto de 50% ou menos. Perceba que não há razão para utilizar valores de StartServers e MinSpareServers diferentes já que o serviço vai iniciar com o número de processos igual a StartServers e vai aumentar até atingir o número de MinSpareServers em poucos segundos. Diferenciar MinSpareServers e MaxSpareServers só fará sentido se seu servidor alterna entre períodos de grande e pequena demanda.

Vejamos agora um pouco do conceito de KeepAlive. Este recurso do Apache permite que um cliente faça várias requisições utilizando uma mesma conexão TCP. Isso economiza tempo e processamento evitando que novos sockets e novos processos sejam criados. A conexão TCP é terminada quando o cliente passa um tempo sem fazer requisições (KeepAliveTimeout) ou quando o processo responsável pela conexão atender o número de requisições igual a MaxKeepAliveRequests. Portanto utilizar este recurso é bom mas devemos tomar cuidado para não ocupar um processo por muito tempo evitando que novos clientes sejam atendidos. Valores que têm se mostrado razoáveis para o KeepAliveTimeout estão entre 1 e 5 segundos (é claro que utilizar um ou outro valor é uma decisão que você deve tomar baseado na quantidade de usuários e na qualidade do serviço que você quer prestar - valores mais baixos proporcionam maior rotatividade e valores mais altos maior qualidade no serviço do usuário que está sendo atendido. É como um médico cuja consulta dura 10 minutos e outro que dura 50). O mesmo conceito se aplica para o MaxKeepAliveRequests. Quanto maior esse número, mais requisições um mesmo usuário poderá fazer antes de liberar a conexão para outro. Valores típicos estão entre 100 e 500 (0 significa que não há limite).

Agora vamos fazer mais algumas contas. Supondo que, pelos cálculos anteriores, você possa atender 20 clientes simultaneamente e que você escolha 1 segundo para o KeepAliveTimeout. Na melhor das hipóteses e em uma situação ideal o servidor seria capaz de atender 1200 novas conexões por minuto. É claro que esse valor não representa 1200 usuários simultâneos porque um mesmo usuário pode abrir novas conexões à medida que vai navegando pelo site. Perceba que limitar o número de conexões simultâneas à um número pequeno não significa necessariamente que você só poderá atender poucos usuários.

A título de exemplo, vamos considerar um servidor com 512M de RAM que serve páginas web dinâmicas feitas em PHP e que os processos residentes, desconsiderando o Apache, ocupam 100M da memória RAM. Então,

512 - 100 = 412
412 / 20 = 20 e uns quebrados

Uma configuração que provavelmente otimizaria o seu Apache seria:

KeepAlive On
KeepAliveTimeout 1
MaxKeepAliveRequests 100

StartServers 15
MinSpareServers 15
MaxSpareServers 15
MaxClients 20
MaxRequestsPerChild 0

O valor de MaxRequestsPerChild representa o número de requisições que um processo filho do Apache pode atender antes de ser forçado a terminar. Isso era muito utilizado em sistemas operacionais com problemas de vazamento de memória (ex:Solaris). Se você utiliza Linux ou BSD é seguro utilizar 0 (infinito). Caso você note que depois de alguns dias a quantidade de memória utilizada por um processo está crescendo de forma anormal, mude esse valor para um valor finito porém grande (entre 5000 e 50000).

Além disso, se as aplicações que você hospeda demandam PHP considere utilizar uma extensão que faça cache do código intermediário (APC , Turck MMCache ,…). Essas extensões podem tornar o acesso até 5 vezes mais rápido.

referências:
http://httpd.apache.org/docs/2.0/misc/perf-tuning.html
http://www.xs4all.nl/~thomas/apachecon/PerformanceTuning.html
http://phplens.com/phpeverywhere/tuning-apache-php

E não é que eles bloquearam mesmo…

Janeiro 7th, 2007

Quando tentei acessar o YouTube hoje de manhã para ver o vídeo do Stallman falando sobre Locked BIOS, quase não acreditei. Não é que os malditos (leia-se BrasilTelecom) tiraram o YouTube do ar! Mas é claro que eu não fiquei parado. Primeiro fui tentar entender o que tinha acontecido. Logo percebi que não estava conseguindo resolver o nome youtube.com. A tentativa foi boa mas nada que a ferramenta dig na web não resolva. Peguei o primeiro IP (208.65.153.253) do youtube.com e coloquei no meu /etc/hosts. Bom, agora vamos ver se pinga……espera….espera…….nada. É… tão bloqueando o IP também :( . Então, o jeito é utilizar um proxy mesmo. Agora, fico me perguntando se eles vão bloquear também o GoogleVideos, o Porkolt, o DailyMotion.

Moral da história: os brasileiros aparecem novamente para o mundo como um bando de índios que não se enquadram no mundo globalizado.

Pergunta: Se o TJ-SP nega que a liminar tenha por objetivo bloquear o site inteiro, porque permite que tal atitude seja mantida, já que milhões de brasileiros que usam o YouTube para bons propósitos estão impossibilitados de acessá-lo? Se você pensa que estou brincando, conheço várias professores que hospedam video-aulas no YouTube e alunos que guardam lá seus trabalhos de publicidade, marketing, jornalismo… A meu ver, essa atitude pune milhões de brasileiros que nada tem a ver com um vídeo publicado (pela primeira vez) por um espanhol em um site americano.

LG anuncia Blu-Ray/HD-DVD player

Janeiro 5th, 2007

A gigante LG anunciou que vai fabricar um combo player capaz de tocar mídias no formato Blu-Ray da Sony e no formato HD-DVD da Toshiba. Acho que estou tendo um “déjà vu”.

Alguém duvidava que isso fosse acontecer?

bad, bad server, no donut for you

Janeiro 4th, 2007

Depois que a justiça do Rio de Janeiro determinou que o Google teria de fornecer os dados cadastrais dos “bebuns” do Orkut foi a vez do tribunal de justiça de São Paulo dar trabalho à megacorporação da Web 2.0 que recentemente adquiriu o site de vídeos mais famoso do mundo. O TJ-SP quer tirar o YouTube do ar por não ter cumprido a determinação anterior de apagar as cópias de um vídeo amador mostrando a apresentadora Daniella Cicarelli em cenas tórridas de amor com seu namorado em uma praia espanhola. Como a justiça brasileira não pode tirar o servidor do ar, a intenção é fazer com que os provedores brasileiros bloqueem o acesso à ele. Nada que um proxy no exterior não resolva.
No entanto, a decisão me parece um tanto quanto inconstitucional. A verdade é que a punição está sendo aos brasileiros e não ao YouTube. Seremos nós que teremos nossa liberdade cerceada enquanto todos os outros países do mundo continuarão a ver a performance espetacular da exibida mulher brasileira.

Romances disponíveis para download

Dezembro 8th, 2006

Cory Doctorow é um famoso escritor de ficção científica. De acordo com seu artigo na Forbes, distribuir gratuitamente seus romances pela internet foi um dos fatores essenciais para o sucesso de seus livros. Ele liberou três de seus romances e uma pequena coleção de histórias sob uma licença Creative Commons . O primeiro deles alcançou a marca de 30.000 downloads em um único dia. O sucesso foi tão grande que o livro foi traduzido para idiomas que ele mesmo desconhece.

Segundo Doctorow, a maioria das pessoas que faz o download do livro não compra a versão impressa mas como elas não iriam comprar o livro de qualquer maneira ele não perdeu nenhuma venda, apenas atingiu um público maior. Uma pequena parcela lê a versão eletrônica como substituta da versão impressa, esses sim, representam perda de vendas. Uma parcela um pouco maior do que essa lê alguns trechos do livro em formato eletrônico antes de comprar a versão impressa, esses representam um ganho nas vendas. Enquanto esse ganho superar as vendas perdidas ele garante que vai continuar distribuindo seus livros gratuitamente. Além disso, distribuir quase um milhão de cópias do seu livro não lhe custou nada.

Não existe (ainda) um estudo para comprovar que a distribuição da versão eletrônica acarretou um aumento nas vendas mas a editora dos livros afirma que as vendas superaram as expectativas. Outro fato curioso é que seus livros têm vendido mais do que de outros autores do mesmo gênero em estágios similares ao de sua carreira.

Ótima iniciativa do escritor Cory Doctorow tentando mostrar que quem gosta de livros não vai deixar de comprá-los só porque existe uma versão eletrônica gratuita.