Josh Berkus hoje no Boteco 4linux

abril 15, 2008 3 comentários

Josh Berkus, que faz parte da equipe Core do PostgreSQL desde 2002, falará sobre as principais características da nova versão 8.3, lançada no último mês de fevereiro. Entre as novas features que fazem parte do PostgreSQL 8.3 estão: suporte a XML, log em CSV (Comma Separated Values), Tsearch integrado, melhor monitoramento e HOT (Heap Only Tuples).

Para maiores informações acesse o site:
www.4linux.com.br

-Leo

Dia PostgreSQL na Unicamp

abril 10, 2008 Deixe um comentário




Maiores informações clique aqui.

Recordar é viver …

abril 10, 2008 1 comentário

É antigo, mas somente pra descontrair:

http://www.dbdebunk.com/page/page/1477865.htm

pgfouine e log_line_prefix hacking

abril 1, 2008 1 comentário

A ferramenta de análise de logs pgfouine é sem dúvida nenhuma uma ferramenta indispensável para qualquer DBA no quesito de análise de logs.

Confesso que fui utilizador assíduo do PQA (antecessor falecido do pgfouine) e quando conheci o pgfouine foi amor à primeira vista e acabei largando um pouco o ruby em troca de um php bem escrito ;-).

Deixarei um pouco a paixão de lado pra falar de uma funcionalidade caracterizada como deficiente no pgfouine, IMHO.

A questão é que para funcionamento correto, o pgfouine exige um formato padrão da variável de configuração log_line_prefix (‘%t [%p]: [%l-1]), e diga-se de passagem é bem conciso, mas muitas vezes não aceitável.

Quem já precisou alterar uma variável de um servidor que não pode ser reiniciado vai entender de que estou falando; ou pior ainda, quem precisa manter um formato consistente com normas internas porque existe uma política na empresa para arquivamento de logs também vai perceber.

Então, antes que tudo se desabe e voce no 5o. andar de seu prédio saia de maneira inconsolável de sua mesa em direção a janela mais próxima, eis que surgem as expressões regulares. Sim, sim elas!
Basta entender a forma como o parser do pgfouine trabalha para alterar nada mais de que (com sorte) uma única linha do núcleo desta ferramenta.

Deixemos de enrolação e vamos realmente ao que interessa:

O programa pgfouine.php inicializa o percurso que os trechos de log deverão seguir até o parser. Esta parte do fluxo tem por objetivo fazer algumas validações e configurações iniciais (informações de banco, opções escolhidas, &ca) e por fim carregar a classe GenericLogReader que baseada nas opções do usuário invoca o acumulador (Acummulator) de logs específico. A função do acumulador é avaliar o eventType de listener e armazenar o resultado em um stream para análise futura pelo parser mais adequado. Basicamente existem duas classes (tipos) maiores de eventType: uma de erro e outra de instruções SQL. Os detalhes sobre os event listeners podem ser localizados em $PGFHOME/include/listeners. A próxima etapa (e a que mais nos interessa), é a fase de parser os logs.
O pgfouine ainda não foi internacionalizado (i18n) portanto pode ser necessário alterar as expressões regulares em $PGFHOME/include/postgresql/PostgreSQLRegexps.lib.php. Basta ver qual o formato de seu arquivo de log e literalmente substituir as strings desse arquivo pelas correspondentes nos logs. Agora os arquivos responsáveis por gerar a informação que o pgfouine “confia” para criação dos gráficos, estatísticas e demais recursos visualizados no produto final, são os arquivos StderrPostgreSQLParser.class.php e SyslogPostgreSQLParser.class.php localizados em $PGFHOME/include/postgresql/parsers e estão na última etapa do percurso da conversão log -> documento. As classes StderrPostgreSQLParser e
SyslogPostgreSQLParser fazem a análise de stderr e syslog respectivamente como é óbviamente notado. Ambas possuem em seus construtores uma propriedade inicializando um objeto do tipo RegExp que é o assunto principal desse post e deve ser alterado para “casar” com o formato de seu log_line_prefix. Em nosso caso estava bem simples e foi apenas alterar o caracter especial de início de linha para “casar” com o formato do log, mas conhecendo um pouquinho de expressões regulares voce será capaz de combinar qualquer formato da linha de seus logs com o pgfouine sem a alteração da variável de configuração log_line_prefix e sem reiniciar o servidor de banco de dados.

-Leo

CategoriasHacking, PostgreSQL

patch retira autovaccum do backend

abril 1, 2008 2 comentários

Pessoal,

Conforme prometido no último pgcon e com apoio financeiro da BEA Systems, é com orgulho que envio o patch que tem como objetivo retirar o autovaccum do backend.

A principal idéia responsável por esse avanço foi a criação de uma ferramenta chamada autoclean.

O componente autoclean atua como um processo filho de postmaster e toda vez que uma página é alterada, o autoclean detecta quais páginas estão disponíveis para armazenar e em seguida mover para áreas disponíveis em VacPageData. Para isso free_space_pages deve estar configurado corretamente.

Outra função do autoclean é detectar páginas sujas e enviá-las para uma área reservada de reciclagem (C:\Meu Computador\Desktop\Lixeira) aliviando a carga do background writer.

Existe ainda a possibilidade de uma página, já reciclada, estar “parcialmente” suja e o autoclean avaliar de acordo com heurísticas uma chamada para a rotina void AutoCleanDirtyClothes(Page *page) que irá causar uma limpeza total daquela página e coloca-la em VacPageListData.

TransactionId wraparound

Com a implementação do autoclean foi criado também um novo tipo para a variável TransactionId para suprir a necessidade de “zerar” o contador de transações, o uint128, um novo tipo com suporte para 128 bits (o segredo aqui foi a geração de um algoritmo de ponto flutuante para suporte ao tipo em servidores de 32 e 64 bits). Dessa forma XID agora foi tipado com uint128.

Outra novidade é que transações já nascem marcadas como XID=2 (Frozen), então o MVCC não precisa mais “adivinhar” qual é a transação mais recente e … Espera aí!! Mas então porque precisamos tipar XID com 128 bits uma vez que usa apenas 1 ??? Hmm, hora de volta à prancheta …

Gente, quanta besteira!!!

Só pra não esquecer que hoje é 1º. de abril.

Abraço!

-Leo

CategoriasPostgreSQL

plpgsql profiling

março 14, 2008 1 comentário

Um profiler é uma ferramenta para análise de performance de chamadas e procedures internas de sua aplicação.

Desde a versão 8.2 do postgres está disponível no pgfoundry o pldebugger, uma ferramenta de análise de plpgsql e depuração desenvolvida pela enterprisedb.

O modo de instalação é semelhante a qualquer outro módulo do contrib:

- colocar o pldebugger.tgz na raiz do código fonte do postgres;
– tar -zxvf pldebugger.tgz;
– cd pldebugger && make && make install;
– psql -c “LOAD ‘`pg_config –pkglibdir`/plugins/plugin_profiler'”; // ou adicione no postgresql.conf

Após carregar a biblioteca do profiler no banco são criadas novas variáveis de configuração runtime no postgres: plpgsql.profiler_tablename e profiler_filename.

O pldebugger possibilita encaminhar os resultados de uma sessão do profiler em arquivos no formato XML ou armazenar em uma tabela do banco.

Inicialmente vamos verificar como ficam os resultados em uma tabela.

Criar uma função para analisar (espero que tenham problemas mais complexos para profiling…):

-- Comment: Sem inspiração: Desculpe mas não estava inspirado pra arrumar outra forma de gravar no disco ...
  1 CREATE OR REPLACE FUNCTION itera(OUT x NAME, OUT y OID)
  2 RETURNS SETOF record
  3 LANGUAGE 'plpgsql' VOLATILE
  4 COST 100
  5 ROWS 240
  6 SET plpgsql.profiler_tablename TO profiler_itera
  7 AS
  8 $_$
  9 DECLARE
 10   i RECORD;
 11   j RECORD;
 12 BEGIN
 13   DROP TABLE IF EXISTS foobar;
 14   CREATE TEMP TABLE foobar(a OID,b NAME);
 15   FOR i IN SELECT OID,relname
 16                   FROM pg_class
 17            GROUP BY 1,2
 18            ORDER BY 2,1
 19   LOOP
 20     FOR j IN SELECT attrelid,attname FROM pg_attribute
 21               WHERE attrelid = i.OID
 22            GROUP BY 2,1
 23            ORDER BY 1,2
 24     LOOP
 25         x := j.attname;
 26         y := j.attrelid;
 27         INSERT INTO foobar VALUES (y,x);
 28     END LOOP;
 29     RETURN NEXT;
 30   END LOOP;
 31   RETURN;
 32 END;
 33 $_$;

De acordo com a definição de nossa funcão, na linha seis, configuramos a variável profiler_tablename com o valor profilter_itera. Isto quer dizer que os resultados serão armazenados em uma tabela dentro da base atual com a seguinte definição:

          Table "public.profiler_itera"
+-----------------+------------------+-----------+
|     Column      |       Type       | Modifiers |
+-----------------+------------------+-----------+
| sourcecode      | text             |           |
| func_oid        | oid              |           |
| line_number     | integer          |           |
| exec_count      | bigint           |           |
| tuples_returned | bigint           |           |
| time_total      | double precision |           |
| time_longest    | double precision |           |
| num_scans       | bigint           |           |
| tuples_fetched  | bigint           |           |
| tuples_inserted | bigint           |           |
| tuples_updated  | bigint           |           |
| tuples_deleted  | bigint           |           |
| blocks_fetched  | bigint           |           |
| blocks_hit      | bigint           |           |
+-----------------+------------------+-----------+

Cada linha desta tabela traz a informação relevante a um deteminado ponto de execução da função. Então para esta função que possue dezessete linhas de código fonte (contando quebras e identação), essa tabela possuirá 17 tuplas (registros/linhas) com informações pertencentes a execução da função itera() óbviamente não estimando o custo computacional de uma quebra de linha.

A saída é algo parecido com:

                                        "Saida de profiling"
+----------------------------------------------------------+------------+------------+--------------+
|                        sourcecode                        | exec_count | time_total | time_longest |
+----------------------------------------------------------+------------+------------+--------------+
|                                                          |          0 |          0 |            0 |
|    DECLARE                                               |          0 |          0 |            0 |
|     i RECORD;                                            |          0 |          0 |            0 |
|     j RECORD;                                            |          0 |          0 |            0 |
|   BEGIN                                                  |          0 |          0 |            0 |
|     DROP TABLE IF EXISTS foobar;                         |          2 |   0.004682 |     0.004682 |
|     CREATE TEMP TABLE foobar(a OID,b NAME);              |          2 |   0.041431 |     0.041431 |
|     FOR i IN SELECT OID,relname                          |          2 |   0.521529 |     0.521529 |
|                     FROM pg_class                        |          0 |          0 |            0 |
|              GROUP BY 2,1                                |          0 |          0 |            0 |
|              ORDER BY 1,2                                |          0 |          0 |            0 |
|     LOOP                                                 |          0 |          0 |            0 |
|       FOR j IN SELECT attrelid,attname FROM pg_attribute |        468 |   0.348036 |     0.054492 |
|                 WHERE attrelid = i.OID                   |          0 |          0 |            0 |
|              GROUP BY 1,2                                |          0 |          0 |            0 |
|              ORDER BY 2,1                                |          0 |          0 |            0 |
|       LOOP                                               |          0 |          0 |            0 |
|           x := j.attname;                                |       3659 |   0.058126 |     0.017285 |
|           y := j.attrelid;                               |       3659 |   0.005371 |     0.000207 |
|           INSERT INTO foobar VALUES (y,x);               |       3659 |   0.143374 |         0.03 |
|       END LOOP;                                          |          0 |          0 |            0 |
|       RETURN NEXT;                                       |        468 |   0.011699 |     0.010148 |
|     END LOOP;                                            |          0 |          0 |            0 |
|     RETURN;                                              |          2 |   0.000002 |     0.000002 |
|   END;                                                   |          0 |          0 |            0 |
+----------------------------------------------------------+------------+------------+--------------+

Para os usuários de versões < 8.3, é possível utilizar um arquivo externo no formato de XML com o profiler. Basta configurar a diretira plpgsql.profiler_filename para um arquivo: SET plpgsql.profiler_filename TO ‘/home/leo/path_to_xml.xml’

O plugin traz ainda estatísticas mais detalhadas utilizando-se do módulo pgstattuple e um depurador de stored procedures que veremos no próximo blog.

Abraço!

-Leo

Categorias1

psql com extensao SQL

fevereiro 20, 2008 1 comentário

Todo mundo sabe o quão poderoso é o console interativo do psql.

Sinceramente não conheço nenhuma ferramenta que se iguale em qualquer plataforma em relação a funcionalidades (é lógico que os consoles irb1.8 e python também chegam bem próximo, mas para propósitos distintos).

A parte chata é quando voce digita linhas e linhas de consulta e toda vez que precisa alterar com o meta comando “\e” voce se depara com a necessidade de digitar :se syn=sql (vim). Lembro que vimrc não adianta por que ele considera a extensão do arquivo.

Não consegui fazer o vim (ou outro editor) converter o número do final do arquivo temporario do psql (tmp/psql.edit.9999) para syntax=sql e mesmo que conseguisse precisaria ainda assim fazer set de todos os plugins assistentes que são carregados em tempo de execução a partir da extensão .sql (diga-se de passagem, eu tenho vários plugins).

Então precisei alterar apenas uma linha do source do psql para incluir o sufixo .sql no nome do arquivo temporário. Imagino que se for para propor um patch para o PGDG, deveria ser criado uma variavel \pset para especificar qual a extensão do arquivo, mas aí a história já é outra…

Segue o patch:

Index: command.c
===================================================================
RCS file: /home/leo/pgrepo/pgsql/src/bin/psql/command.c,v
retrieving revision 1.186
diff -c -r1.186 command.c
*** command.c 1 Jan 2008 19:45:55 -0000 1.186
--- command.c 20 Feb 2008 20:37:40 -0000
***************
*** 1362,1371 ****
*/
#endif
#ifndef WIN32
! snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
"/", (int) getpid());
#else
! snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
"" /* trailing separator already present */ , (int) getpid());
#endif

— 1362,1371 —-
*/
#endif
#ifndef WIN32
! snprintf(fnametmp, sizeof(fnametmp), “%s%spsql.edit.%d.sql”, tmpdir,
“/”, (int) getpid());
#else
! snprintf(fnametmp, sizeof(fnametmp), “%s%spsql.edit.%d.sql”, tmpdir,
“” /* trailing separator already present */ , (int) getpid());
#endif

CategoriasNúcleo
Seguir

Obtenha todo post novo entregue na sua caixa de entrada.