Arquivo de outubro, 2012

Scrum e menos de 10 miinutos

Publicado: outubro 25, 2012 em Scrum

Cursor no MYSQL

Publicado: outubro 24, 2012 em MYSQL

Cursor é um recurso bastante interessante em bancos de dados pois permite que seus códigos SQL façam uma varredura de uma tabela ou consulta linha-por-linha, realizando mais de uma operação se for o caso.

Na maioria das vezes, um simples SELECT exibe na tela esta varredura, trazendo todos os registros da consulta em questão. A vantagem de usar um cursor é quando, além da exibição dos dados, queremos realizar algumas operações sobre os registros. Se o volume de operações for grande, fica muito mais fácil, limpo e prático escrever o código utilizando cursor, do que uma consulta SQL.

Por exemplo: É muito mais vantajoso criar um cursor que faça a análise de cada produto de estoque, conferindo seu histórico, calculando sua previsão de vendas para o próximo mês, capturando o melhor cliente que já o comprou, etc, do que criar um SELECT absurdamente grande que talvez não consiga ainda todas as informações de forma simples.

Para utilizar um cursor, analise o código-fonte a seguir, onde são mostrados e comentados passo-a-passo a criação de um cursor e sua chamada. O objetivo do cursor apresentado a seguir é de somar a kilometragem atual de todos os veículos de um banco de dados fictício.

IMPORTANTE: O exemplo a seguir é meramente didático, seu resultado poderia ser obtido com um SELECT simples de soma (função SUM()).

Se desejar executar este código em seu MySQL, copie-o e cole-o em um arquivo do tipo ‘.sql’, e execute-o no terminal desta forma: mysql> source <caminho do arquivo>;

Código fonte

  CREATE DATABASE TUTORIAL_CURSOR;
  USE TUTORIAL_CURSOR;

  CREATE TABLE VEICULOS(
  VEICULO varchar(32) NOT NULL,
  KILOMETRAGEM int NOT NULL
  );

  INSERT INTO VEICULOS (VEICULO, KILOMETRAGEM) VALUES ('Carro 1',  '5230');
  INSERT INTO VEICULOS (VEICULO, KILOMETRAGEM) VALUES ('Carro 2',  '7800');
  INSERT INTO VEICULOS (VEICULO, KILOMETRAGEM) VALUES ('Carro 3', '16540');
  INSERT INTO VEICULOS (VEICULO, KILOMETRAGEM) VALUES ('Carro 4', '32230');

  DROP PROCEDURE IF EXISTS TUTORIAL_CURSOR.SomaKilometragem;

  DELIMITER $$
  CREATE PROCEDURE TUTORIAL_CURSOR.SomaKilometragem (OUT resultado INT)
  BEGIN

  -- Definição de variáveis utilizadas na Procedure
  DECLARE existe_mais_linhas INT DEFAULT 0;
  DECLARE kilometros INT DEFAULT 0;
  DECLARE total_de_kilometros INT DEFAULT 0;

  -- Definição do cursor
  DECLARE meuCursor CURSOR FOR SELECT KILOMETRAGEM FROM VEICULOS;

  -- Definição da variável de controle de looping do cursor
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET existe_mais_linhas=1;

  -- Abertura do cursor
  OPEN meuCursor;

  -- Looping de execução do cursor
  meuLoop: LOOP
  FETCH meuCursor INTO kilometros;

  -- Controle de existir mais registros na tabela
  IF existe_mais_linhas = 1 THEN
  LEAVE meuLoop;
  END IF;

  -- Soma a kilometragem do registro atual com o total acumulado
  SET total_de_kilometros = total_de_kilometros + kilometros;

  -- Retorna para a primeira linha do loop
  END LOOP meuLoop;

  -- Setando a variável com o resultado final
  SET resultado = total_de_kilometros;

  END $$

  DELIMITER ;

  CALL SomaKilometragem(@variavel_temporaria);
  SELECT @variavel_temporaria;

O resultado final para este cursor é o seguinte:

  +----------------------+
  | @variavel_temporaria |
  +----------------------+
  | 61800                |
  +----------------------+

O Planning Poker é uma técnica estimativa bastante utilizada em projetos ágeis que usam o framework do Scrum. Eu pessoalmente sou um usuário número #1 e recomendo fortemente a todos os meus amigos e clientes. A ideia principal por traz do Planning Poker é permitir que todos os membros do time de desenvolvimento que estão comprometidos na implementação do Sprint participem colocando a sua visão de complexidade para que juntos possam chegar a um indicador de complexidade comum para o time.

 

O uso do Planning Poker reforça fortemente o conceito de colaboração e comprometimento. Em um projeto tradicional alguém estima para você usando os entendimentos dele e passa a atividade para você e um prazo. Você mesmo sabendo que não vai conseguir fazer pega a atividade e inicia o ciclo do mundo de Alice. A mesma historinha do filme onde todos acreditam em um conto sabendo que nada daquilo vai se tornar real. Nos projetos ágeis a cultura é diferente e o Planning Poker faz com que todos votem na complexidade e não somente uma pessoa. Com esse espírito de união e colaboração chega-se a uma complexidade que seja o consenso do grupo.

 

A escala de complexidade é baseada na sequência de  Fibonacci (0, 1, 2, 3, 5, 8, 13) e cada participante do time que estiver comprometido recebe um conjunto de cartas sendo cada uma com o número de complexidade. O grupe se reúne geralmente na reunião Sprint Planning e esclarece as estórias com o PO (Product Owner) para depois estimar uma a uma. Seguindo a ordem de sequencia das às estórias já priorizadas pelo PO. Então o time conta até três e cada um apresenta uma das cartas ao mesmo tempo. Esse é um momento importante, pois nenhum membro pode influenciar o outro na hora de mostrar as cartas.

Após apresentada as cartas confere-se os números das mesmas para ver se deu tudo igual ou ocorreu divergências. Em caso de divergência cada membro pode argumentar o que o levou a pensar diferente dos demais e nesse momento pode usar os argumentos que justifique aquele item ser mais complexo ou mais simples. Com o tempo você vai observar opiniões do tipo “Eu já implementei uma rotina parecida em um projeto anterior” que trazem a tona o grande valor dessa técnica que é justamente fazer as pessoas serem ouvidas.

 

Após a apresentação dos argumentos cada pessoa que ficou na dúvida pode propor uma nova votação e mudar o seu voto para mais ou para menos conforme o novo entendimento da questão. Por isso um item que estava complexo pode ser finalizado com mais simples ou vice-versa prevalecendo o entendimento do time sobre a questão.

A primeira vista você pode está se perguntando como as pessoas estão ali chutando. O grande diferencial é que não tem ninguém de fora interferindo, pois só participa quem realmente vai codificar a funcionalidade e com isso cada pessoa usa a sua experiência pessoal como implementações em projetos anteriores ou conhecimento da tecnologia em questão e isso faz com que ela se comprometa, pois é ela que está falando o quando é complexo aquele item. É uma forma simples de se estimar indo direto ao ponto e principalmente provoca uma colaboração natural entre os membros do time resultando em grandes ganhos para o projeto.

 

Com o passar dos Sprints o time multidisciplinar que usa o framework do Scrum vai aprendendo e se adaptando a chegar em uma velocidade que chamamos de cruzeiro para implementação das funcionalidades principalmente pelas lições aprendidas que são sempre base para estimativas futuras uma vez que cada pessoa antes de estimar pode comparar mentalmente essa nova atividade com uma anterior similar e ter um embasamento próximo a realidade desejada.

 

No Scrum é o time que captura as atividades do backlog para implementação em um Sprint e essa quantidade é justamente definida por uma quantidade de pontos de complexidade capturados em Sprints anteriores e implementados. Supondo que estamos falando de 4 atividades de 3 pontos em média cada nós teríamos um total de 12 pontos. Com esse número o time se organiza para saber quantos pontos consegue assumir em cada Sprint permitindo pegar um número qualquer de atividades até o valor máximo de x pontos que é até onde vocês conseguem se comprometer.

 

Já faz alguns anos que venho acompanhando de perto o uso de Planning Poker e me impressiono muito como ele ajuda as pessoas a participarem e exporem suas opiniões gerando um crescimento rico e incremental na qualidade das estimativas conquistando a confiança de todos no projeto e dos patrocinadores que no fundo querem um resultado que atenda a sua expectativa e que realmente aconteça diferente dos outros modelos em cascata onde vira um eterno mundo de replanejamentos.

 

Se você ainda não teve a oportunidade esse é o momento de fazer algo diferente em seu projeto de desenvolvimento. Faça o teste e depois comente por aqui os resultados.

Encerrando sessões LOCKED no Oracle

Publicado: outubro 11, 2012 em Oracle

Sessões travadas no Oracle são comuns quando há acesso concorrente no banco. Ou seja, em 99% dos casos. Muitas vezes por falha do usuário, falha de equipamento ou no próprio transacional do bd,  a sessões travam determinado objeto e podem permanecer assim por muito tempo. O problema é que até uma intervenção externa, o objeto fica inacessível para operações.

Sintomas deste problema:

  • Você tentou comitar uma transação pendente e obteve uma mensagem de erro no Oracle: ORA-00054: resource busy and acquire with NOWAIT specified;
  • Mesmo ao tentar realizar um SELECT simples em uma tabela, o oracle demora e retorna erro de timeout;
  • O usuário não consegue salvar dados no banco.

Ocorre que durante a execução de comandos DML (insert,delete,update e select for update) o banco bloqueia o objeto para que nada seja concorrente enquanto a sessão não for comitada / descartada. Este erro geralmente aparece quando outro usuário tenta executar DML’s na mesma estrutura de dados.

Na maioria das vezes, basta validar o comando com COMMIT ou descartar com ROLLBACK na sessão que gerou o problema, mas às vezes a sessão é fechada sem a finalização da transação, ou o terminal é reiniciado abruptamente, entre outros.

Seja qual for o motivo, neste caso, é preciso descobrir qual sessão está gerando o problema e finalizá-la manualmente – a view v$locked_object registra as sessões travadas no banco. Consultaremos as views v$locked_object, v$session b e dba_objects (necessário privilégio DBA).

 

SQL> select c.owner, c.object_name, c.object_type,b.sid, b.serial#, b.status, b.osuser, b.machine
2      from v$locked_object a , v$session b, dba_objects c
3      where b.sid = a.session_id
4      and a.object_id = c.object_id;

OWNER          OBJECT_NAME          OBJECT_TYPE   SID          SERIAL#    STATUS          OSUSER       MACHINE
————— ————————  ——————- ———- ———— —————- ————- ————–
PRODUCAO  TB_CADASTRO           TABLE                     142          57504          INACTIVE    amoreira      ADMIN-PC

PRODUCAO  TB_USUARIO              TABLE                      99           21909           INACTIVE    fsilva              INFO01-PC

HOMOLOG    TB_CADASTRO           TABLE                      78          25373           INACTIVE    ddgoes           INFO08-PC

 

Feito isso, temos listadas as sessões e podemos indentificar a geradora do problema. O próximo passo é finalizá-la manualmente.
Sintaxe:

alter system kill session ‘session_identifier, serial_indentifier’ [MODE];

Exemplo:

SQL>  alter system kill session ’78, 25373′ IMMEDIATE;

System altered.

 

O modo de fechamento pode ser IMMEDIATE (imediato) ou POST TRANSACTION (ao término da transação corrente). Como a própria transação que está gerando o problema, não faz sentido esperar a sua finalização, por isso o fechamento é imediato.

Problema resolvido. Podemos também estender essa solução para o seguinte cenário: imagine que você administra o banco e precisa realizar uma manutenção, ou é preciso alterar alguma estrutura de dados. O ideal é que nehuma sessão esteja ativa durante estes procedimentos.

É claro que na melhor hipótese, nenhuma sessão deveria ser derrubada manualmente, mas se esta medida for necessária, você pode exterminá-las de uma só vez.
Exemplo:

SQL> declare
2    va_sql varchar2(256);
3  begin
4    for reg in(
5              select c.owner, c.object_name, c.object_type,b.sid, b.serial#, b.status, b.osuser,b.machine
6              from v$locked_object a , v$session b, dba_objects c
7              where b.sid = a.session_id
8              and a.object_id = c.object_id
9              )loop
10        va_sql := ‘alter system kill session”’ || reg.sid || ‘, ‘|| reg.serial# || ”’ IMMEDIATE‘;
11        execute immediate va_sql;
12      end loop;
13    end;
14  /

PL/SQL procedure successfully completed.

É isso aí. Um abraço a todos!