2012/5/31 Marco Aurélio V. da Silva <[email protected]>:
> Caros,
>
> A lógica que desenvolvi é o seguinte, uma função (vb.net+npgsql) que pega
> uma determinada tabela e busca qual o maior codigo dela ai a função soma
> mais 1 e adiciona o novo registro, logo a função é composta por dois
> comandos um select para pegar o ultimo codigo, e um insert para inserir a
> nova numeração.
>
Como já dito pelo Matheus, essa abordagem não funcionará, este é um
típico caso de race condition [1]. Você não pode utilizar o SELECT ...
FOR UPDATE, pois o mesmo não pode ser usado em conjunto com funções de
agregação [2]. Como não pode haver furos na numeração, não recomendo a
utilização de sequences. Primeiro, independente de a transação ser
efetivada, o valor da sequence será incrementado. Segundo, se o banco
sofrer uma paralisação abrupta, você poderá perder um intervalo de
valores, como já apontando em [3].
Quando me deparei com este cenário, eu criei uma outra tabela para
armazenar o maior código, depois criei uma trigger para incrementar e
retornar o código num único UPDATE, ex:
CREATE FUNCTION "fun_t1_codigo" (
)
RETURNS trigger AS
$body$
BEGIN
UPDATE codigos
SET codigoatual = codigoatual + 1
RETURNING codigoatual INTO new.codigo;
RETURN new;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
CREATE TRIGGER "trg_t1_codigo" BEFORE INSERT
ON "t1" FOR EACH ROW
EXECUTE PROCEDURE "fun_t1_codigo"();
Se a transação não for efetivada, o codigoatual na tabela codigos não
será incrementado. Duas transações nunca pegarão o mesmo código, pois
a primeira que chegar conseguirá o acesso exclusivo à tabela de
códigos, mantendo até ser finalizada.
Essa solução pode ser boa para transações rápidas, como, no caso, um
cadastro simples, mas para transações mais demoradas, a contenção
feita na tabela de códigos poderia ser proibitiva.
[1] https://en.wikipedia.org/wiki/Race_condition
[2]
http://www.postgresql.org/docs/9.1/static/sql-select.html#SQL-FOR-UPDATE-SHARE
[3] http://listas.postgresql.org.br/pipermail/pgbr-geral/2010-April/020601.html
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral