PGBR2011

PGBR 2011 - Conferência Brasileira PostgreSQL

Para quem não sabe, o PGBR2011 (nome novo para o PGCon Brasil) está à pleno vapor e em sua 4ª edição estamos novamente dando um bom salto de qualidade. Vejamos algumas novidades:

5 Palestrantes internacionais Confirmados

Todos eles são desenvolvedores do PostgreSQL e tem grandes contribuições para a comunidade.

O evento será realizado no conforto do Hotel Century Paulista, em São Paulo

Os detalhes do local já estão acertados. A decisão de fazer o evento num hotel deverá ajudar bastante quem vem de longe. Você poderá se hospedar no mesmo local do evento. Assim as pessoas gastam menos com deslocamento e perdem menos tempo. Para quem for se hospedar, confira os preços especiais para quem for participar do evento. Recomendo fazer a sua reserva o quanto antes para evitar surpresas na última hora.

Para quem mora em São Paulo, também será uma grande vantagem, o local fica a apenas algumas quadras da estação Brigadeiro do metrô. Se você preferir vir de carro até o local, há um estacionamento com preço fechado para participantes do evento.

Serão 3 salas simultâneas que juntas comportam 470 pessoas, uma sala de apoio, um salão de exposições e um local para o famoso coffee break à tarde. Estamos esperando um público de 400 pessoas nos 2 dias do evento, que cairão numa 5ª e 6ª feira, diferente das edições anteriores. Notem que na 4ª, haverá um feriado.

Participe

Você pode ajudar:

  1. Venha ao evento. Sua presença é o mais importante para nós. As inscrições deverão abrir em agosto. Como sempre, quem se inscrever com antecedência, vai poder aproveitar um preço especial.
  2. Mande uma proposta de palestra. A chamada de trabalhos será aberta em meados de junho ou julho, fique atento.
  3. Divulgue o evento:
    • Se você tem um blog, um site, pode divulgar um banner do evento ou falar sobre ele.
    • Se você utiliza o Twitter, fale sobre o evento e utilize a hash tag #PGBR2011.
    • Se você participa de alguma lista de discussão por e-mail, informe as pessoas sobre o evento. Não esqueça das boas maneiras e coloque um [off-topic] no assunto.
    • Se você estuda numa faculdade, estaremos fazendo alguns cartazes sobre o evento que você poderá afixar no mural.
  4. Se você trabalha numa empresa de TI ou utiliza muito o PostgreSQL no seu trabalho, considere a possibilidade da sua empresa patrocinar o evento.
  5. Se você gostaria de dar sugestões ou ajudar na organização do evento, entre na lista da comunidade.

O guro Oracle Thomas Kyte mostra os argumentos para usar o PostgreSQL

Sim, é verdade! Estava lendo uma thread no blog do respeitável Thomas Kyte sobre comparações do Oracle com outros bancos de dados aqui.  Claro, o Thomas não cita o PostgreSQL em momento algum, ele cita apenas o Informix, Ingres, Sybase, DB2 e o MS SQL Server.

Bom, vale a pena ler o artigo. Você verá que nos comentários o PostgreSQL começa a aparecer, e com boas avaliações. Mais interessante ainda é que o Thomas ignora ao máximo o PostgreSQL nos comentários. Claro, ele não é estúpido, não seria inteligente nem diplomático da parte dele. O máximo que ele chega a citar é que a Oracle tem o XE, que quem conhece sabe que é algo limitado e certamente foi lançado (a exemplo do que fez a MicroSoft e IBM) para retardar o avanço dos bancos de dados livres.

O post é de 2001 e os comentários perduram até 2010. De qualquer forma, fica claro, que os mesmos argumentos que ele utiliza para mostrar a superioridade do Oracle, serviriam para o PostgreSQL…. vale a pena ler.

Comparison between Oracle and Others

SQL para DBAs

Quem me conhece, sabe que eu sempre implico com os vícios dos DBAs que iniciam a sua carreira no desenvolvimento. Mas os DBAs que começam como sysadmin também tem seus vícios. Um dos pontos fracos costuma ser a baixa familiaridade com o SQL.

Bom, vou mostrar aqui um alguns exemplos de SQLs que tive que desenvolver recentemente. Alguns foram feitos para ajudar a equipe de desenvolvimento, outros para resolverem problemas de performance e tem um que foi feito por solicitação dos  sysadmins. Na verdade, eu deveria mesmo é organizar estes scripts de uma forma lógica, mas são coisas realmente simples para merecerem tanto coidado…

Então chega de blá, blá, blá e vamos a eles:

  • Conversão de NOT IN em NOT EXISTS numa carga de dados. É muito comum você precisar carregar periodicamente uma tabela com os dados de uma outra. Isso ocorre muito na integração entre sistemas. Eu sei, eu sei, usar visões materializadas pode ser um processo bem mais inteligente. Infelizmente nem sempre estas decisões estão na nossa mão. Vejamos o caso:
INSERT INTO tabela2
    SELECT * FROM tabela1 t1
        WHERE campo_pk NOT IN(SELECT campo_pk FROM tabela_origem);

Você tem de carregar a tabela2, com os dados da tabela1 sem repetir os dados que já estejam lá. Utilizar o NOT IN é bem intuitivo, mas quando a tabela2 é grande, se torna um pesadelo, pois a subconsulta uma vez para cada registro na tabela1 e não consegue utilizar índices para isso. Um verdadeiro pesadelo. Então vamos a solução clássica:

INSERT INTO tabela2
    SELECT * FROM tabela1 t1
        WHERE NOT EXISTS (SELECT NULL FROM tabela2 t2 WHERE t2.campo_pk = t1.campo_pk );
  • Pegar apenas o primeiro e o último nome de um campo com nome completo:
SELECT
        SUBSTR(nome,0,INSTR(TRIM(nome),' ')) primeiro_nome
        SUBSTR(nome,INSTR(TRIM(nome),' ',-1) + 1) ultimo_nome,
    FROM tabela_cadastro;
  • Limpar caracteres inválidos de telefones. Sim, tem muita gente que gosta de armazenar telefones, CEP, RG, CPF com caracteres não numéricos. Não é o correto, mas muita gente faz. Então, para fazer uma limpeza, vamos utilizar um pouco de expressões regulares, que são pouco exploradas por muitos DBAs e até mesmo desenvolvedores:
SELECT SUBSTR(LTRIM(regexp_replace(telefone,'[^0-9]'),0),0,10) fone_tratado
    FROM tabela_cadastro;
  • Selecionar apenas e-mails válidos. Eu sei, a validação deveria ser feita na carga dos dados, mas nem sempre acontece. Aqui, mais um caso clássico de uso de expressões regulares:
SELECT TRIM(email) email
    FROM tabela_cadastro
    WHERE REGEXP_LIKE (TRIM(email),'^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$','i');
  • Agora uma forma de saber se o número de sessões num nó do Oracle RAC estão relativamente bem balanceadas. Aqui estou utilizando funções de janelas (que já abordamos aqui antes, mas com o Postgres), algo muito bacana, utilizado exaustivamente em consultas complexas com BI:
SELECT
        i.instance_name,
        l.sessions_current,
        ROUND(l.sessions_current * COUNT(l.inst_id) OVER () / SUM(l.sessions_current) OVER (),2) var
    FROM gv$license l, gv$instance i
    WHERE l.inst_id = i.inst_id;

Aqui, um valor entre digamos 0,9 e 1,1 para o campo VAR significa que o nó está relativamente bem balanceado. Esta consulta foi utilizada para uma ferramenta de monitoramento do Oracle RAC.

OBS: Os scripts aqui foram escritos e testados em Oracle 10g e 11g, sorry.

Rodando scrips de um usuário específico com segurança

A história é recorrente: o desenvolvedor mandou para você  um mega script (ou um pacote com dezenas deles) para rodar no banco de dados Oracle. Em 99% dos casos o desenvolvedor vai dizer que o script precisa ser executado com você conectado no banco de dados utilizando o usuário XYZ, que é o dono dos objetos que vão ser criados/alterados/apagados.

Aí o que o DBA faz? Pega a senha do usuário numa listinha “cuidadosamente” guardada e roda o script em questão. Então, pare e pense: qual é o problema nisso?

  • Você tem que guardar a senha dos usuários da base. Isso vai lhe levar a uma das seguintes situações:
    • Você vai colocar senhas fáceis (como o mesmo nome do usuário ou a mesma senha para todos usuários), o que representa uma brecha de segurança;
    • Você vai anotar num papel, txt ou algo do tipo todas as senhas. E esse papel, txt, etc não vai estar guardado num cofre, pois você precisa disso com frequência. Nova falha de segurança.
    • Você vai criar um banco de dados para guardar as senhas… e ter mais uma base para administrar, gênio.
    • Você vai deixar o próprio desenvolvedor/fornecedor rodar o script para você. Tá louco? Jamais faça isso num ambiente de produção!!!
  • Você vai ter que conceder permissões para este usuário além do necessário. Se precisa criar uma tabela, precisa conceder permissão de CREATE TABLE. Precisa criar uma sequência? CREATE VIEW. E por aí vai. Não é raro o DBA usar logo uma daquelas mega permissões como DBA, RESOURCE, etc. Afinal, perder tempo com segurança é coisa de DBA chato, certo?

Ok, você é um DBA esperto… muitos anos de praia, já sabe que existem outras alternativas:

  • Rodar o script como DBA, mas antes abrir o script num editor e sair colocando o nome do esquema antes do nome do objeto. Isso dá certo, mas dá muito trabalho. Não é algo que se possa automatizar sem cometer alguns erros. Acredite, há casos em que isso pode levar horas e está sujeito a muitos erros.
  • Você pode pegar a senha criptografada em DBA_USERS, alterar a senha do usuário, rodar o script e depois voltar a senha original. É também uma forma de bloquear o acesso deste usuário enquanto você está atualizando os objetos. Claro que idealmente um usuário dono de objetos não deveria nunca ser utilizado para acesso pela aplicação… mas não é o que os desenvolvedores tem a mania de fazer. Por mim esse usuário não deveria sequer ter permissão para se conectar na base. Eu realmente não acho esta uma solução elegante, e você precisa manter o usuário com um monte de privilégios desnecessários da mesma forma que antes. Já vi também pessoas colocando permissões de DBA enquanto rodam o script e depois que terminam removem a permissão. Não, não é uma boa idéia. Você também tem de anotar com cuidado a senha criptografada para alterar a senha de volta para a original qualquer caracter bizarro que você erre, já era. Por fim você  tem conhecer o impacto de alterar a senha, mesmo que provisóriamente. Experimenta por exemplo trocar a senha do usuário APPS no EBS para ver o que acontece…

Então qual é o procedimento que 10 entre 10 DBAs experientes utilizam? Simples:

ALTER SESSION SET current_schema=foo;

Simples assim. O esquema padrão passa a ser foo. Todos os objetos criados, alterados e apagados serão neste esquema.

Mas calma, existem alguns problemas sim: alguns comandos não trabalham bem com outro CURRENT_SCHEMA. Um deles é a criação de DB Links. Não é possível criar um DB Link para outro esquema, você tem de estar realmente conectado com o usuário em questão para criar este DB Link. Claro que você não cria DB Links no ambiente de produção com frequência (pela sua sanidade mental, eu espero que não). DB Links públicos não tem esse problema, é claro. Outro problema é a criação de JOBs com o DBMS_JOB. Você pode utilizar o DBMS_IJOB, para contornar este problema ou pelo bem da humanidade migrar para o Scheduler.

Bom, de qualquer forma é sempre obrigação do DBA revisar os scripts, verificar os parâmetros de Storage, etc.

OBS: Este post é dedicado a um DBA velho de guerra que ainda guarda velhos hábitos dos tempos que era desenvolvedor e insiste em me trazer mais problemas do que soluções.

OBS2: No PostgreSQL existe uma não conformidade com o padrão SQL (você pode trabalhar no padrão se quiser, mas não vejo vantagem) que permite que os usuários e os esquemas não sejam diretamente relacionados.  Então esta cultura ruim do Oracle não é tão comum entre os desenvolvedores/DBAs do PostgreSQL. Além disso o PostgreSQL tem o SEARCH_PATH que é mais refinado que o CURRENT_SCHEMA, e os comandos DDL permitem a troca do dono de qualquer objeto (que não seja um objeto de sistema, claro).

  • ATUALIZAÇÃO (em 16/02/2011):

Para aqueles que ainda precisam utilizar o DBMS_JOB e precisam criar JOBs para outro usuário, segue uma dica de como fazer, utilizando o DBMS_IJOB.SUBMIT. O DBMS_IJOB.REMOVE é fácil de utilizar, mas para criar um novo JOB, você vai precisar passar todos os parâmetros, como em:

DECLARE
    job_num NUMBER;
    nlsvar varchar2(4000);
    envvar raw(32);
BEGIN
    SELECT nls_env,misc_env
        INTO nlsvar,envvar
        FROM dba_jobs
        WHERE
            rownum<2 AND
            nls_env IS NOT NULL AND
            misc_env IS NOT NULL;
    SELECT MAX(job)+1
        INTO job_num
        FROM dba_jobs;
    sys.dbms_ijob.submit(         job=>job_num,
        luser=>'MEU_USUARIO',
        puser=>'MEU_USUARIO',
        cuser=>'MEU_USUARIO',
        what=>'meu_usuario.roda_procedure_xyz;',
        next_date=>TRUNC(SYSDATE),
        INTERVAL=>'TRUNC(SYSDATE) + 1',
        broken=>FALSE,
        nlsenv=>nlsvar,
        env=>envvar);
    dbms_output.put_line(job_num);
END;
/
COMMIT;

Já aqueles que desejam criar um DB LINK privado, a única alternativa é recorrer ao DBMS_SYS_SQL, que assim como o DBMS_IJOB não está na documentação oficial:

DECLARE
    uid NUMBER;
    sqltext varchar2(1000) := 'CREATE DATABASE LINK test_dblink
CONNECT TO dblink_user IDENTIFIED BY dblink_user_password
USING ''nome_da_base_no_tnsnames''';
    myint INTEGER;
BEGIN
    SELECT user_id INTO uid FROM all_users WHERE username LIKE 'SCOTT';
    myint:=sys.dbms_sys_sql.open_cursor();
    sys.dbms_sys_sql.parse_as_user(myint,sqltext,dbms_sql.native,UID);
    sys.dbms_sys_sql.close_cursor(myint);
END;
/

Note que você pode utilizar o DBMS_SYS_SQL para rodar qualquer comando SQL como outro usuário. No exemplo, estamos utilizando o usuário SCOTT.

Janeiro

Janeiro é um mês estranho.

  • Depois da maratona de amigo-secreto, amigo-da-onça, amigo-ladrão e outras invenções para ajudar os donos de lojas de R$1,99;
  • Depois de todas a comemorações e bebemorações com os amigos, das festas promovidas pelo patrão, jantares formais e informais;
  • Depois de rever a família, relembrar todas as intrigas que os parentes conseguem carregar por meses a fio esperando aquele momento em que todos estão lá reunidos e bêbados esperando o momento da lavagem de roupa suja e das revelações perturbadoras;
  • Depois de desejar felicidades, fazer votos solidários, mandar o KIT FELICIDADES, entupir as caixas de mensagens com spans para amigos, inimigos, desconhecidos;
  • Depois de contabilizar todas as gafes, promessas não cumpridas, dívidas não pagas, amores perdidos, oportunidades que escorregaram e frustrações acumuladas;
  • Depois de aturar zilhões de especiais de natal, shows do Roberto Carlos, Xuxa e outras bizarrices que as TVs, Internet e e camelôs insistem em irradiar pelo spectro, cabo, DVDs, Blue-Ray, pen-drive e o que mais inventarem
  • Depois de torrar até o último centavo do 13º (para quem ainda sabe o que é isso), bonus, cartão de crédito, cheque especial, agiotas e tudo o mais que lhe permita fazer um monte de parcelas em lojas entupidas de gente;
  • Depois de fazer promessas, traçar planos e estabelecer metas para o ano seguinte;
  • Depois de se matar no trampo para gastar todo o orçamento que seu chefe esqueceu de gastar no ano inteiro;
  • Depois de fazer todas as migrações, implantar todos os sistemas e tudo o mais que é necessário para que os outros consigam atingir suas metas que eles deixaram para lá durante 11 meses;
  • Depois de enfrentar um trânsito descomunal, filas intermináveis para comprar um simples perú e chuvas torrenciais na hora do rush;
  • Depois de se penitenciar/congratular/regozijar, pelo nascimento/morte/chegada/foo_event de alguma figura proeminente de alguma religião bar, lembrar e ser lembrado por todos à sua volta disso;

Bom depois de sobreviver a tantas provações, excessos e eventos cataclísmicos, tudo isso, chega o porre homérico do ano novo. Janeiro chega enfim como uma bonança há tempos esperada.

Enquanto muitos lotam as praias, hoteis, pousadas, castelos europeus, campings e outras acomodações, muitos continuam a trabalhar, mas não normalmente:

  • O trânsito se torna suportável, mesmo após as chuvas torrencias de verão;
  • Ninguém quer fazer migrações, implantações ou grandes mudanças nesta época;
  • O número de usuários cai incrivelmente, pois a maioria está lotando as praias, hotéis….
  • Os restaurantes estão mais vazios, as filas nos bancos e lotéricas estão menores;
  • A banda da Internet (pelo menos no trabalho) está uma maravilha!
  • Os radares continuam multando normalmente e aqueles que se empolgam com a diminuição nos engarrafamentos e não se lembrar que existem limites de velocidade…
  • O tédio toma conta dos filhos que não foram viajar e atazanam a vida dos pais que mesmo com pouco trabalho e com pouco trânsito continuam chegando cansados do trabalho pensando naquela cerveja na praia…
  • A televisão começa a parar de passar retrospectivas, especiais de natal, reprises e coisa e tal e volta a exibir o mesmo lixo habitual;

Então janeiro é este mês mágico onde a insanidade de dezembro se encerra sem que no entanto as promessas de ano-novo se iniciem, uma vez que isso só passa a valer depois do carnaval. É aquele período mágico onde a tendinite acumulada em dezembro ainda o assombra, mas já permite que você abra a porta de casa sem arder infernalmente. É uma época em que alguns pais corajosos se aventuram a levar seus filhos em parques de diversões abarrotados de crianças com insolação e encharcadas de chuva ao mesmo tempo, lutando para conseguir ir em mais de um brinquedo no mesmo dia. Ok, eu confesso, levei meus filhos no tal do Hopi Hari tempos atrás e descobri que isso é tão idiota quanto querer levar a namorada/esposa/amante/secretária no motel no dia dos namorados/secretária sem reserva.

E cá estamos nós, tirando poeira do blog em pleno horário de expediente, lendo os quadrinhos excepcionais do André Dahmer na internet, lendo mais um livro do Douglas Adams na hora do almoço, marcando todos os seus Feeds/mails/tarefas de 2010/whatever como lidos e mergulhando naquela sensação pinkfloydiana de “Confortably Numb“.

Não é a euforia que poderia ser numa praia tomando todas com os amigos. Não é a calma de estar em casa assistindo uma eterna sessão da tarde. Nem tão refivigorante como um retiro nas cachoeiras de Lumiar. Mas é esse momento de suspensão onde nos permitimos um pouco de ócio produtivo, um pouco de delírio, um pouco de calma e um monte de dívidas para pagar.

Janeiro para mim é isso. De longe o pior mês do ano para se tirar férias, pelo simples motivo de todos quererem justamente isso. O melhor mês para implantar coisas que seu chefe boicota há tempos (afinal ele está de férias…). O melhor mês para ler coisas diferentes e ver filmes bizarros. E deixem janeiro passar sem pressa, como um domingo preguiçoso sem louça para lavar.