2013/12/6 José Mello Júnior <[email protected]>
> Vamos lá:
>
>
Por favor, evite o top-posting. Coloque suas repostas abaixo das dos
colegas, como faço a seguir. Ok?
> Tabela
>
> numero
> nome
> status
>
> Select * from tabela
> -------------------------
> 1 JAIR 1
> 2 Roberto 0
> 3 José 0
>
> Preciso que em uma consulta concomitante o terminal que pegar o registro 2
> passe para status 1 e o segundo terminal pegue o 3.
>
>
Bom, para isso não precisa do nível SERIALIZABLE, o READ COMMITED te
atenderá perfeitamente.
Para recuperar um registro e garantir que ninguém mais irá atualizá-lo
enquanto você "trabalha", você deve pode fazer da seguinte forma:
BEGIN;
SELECT numero, nome FROM tabela WHERE status = 0 ORDER BY numero LIMIT
1 FOR UPDATE;
-- trabalhar com o resultado
UPDATE tabela SET status = 1 WHERE numero = <numero recuperado>
COMMIT;
Dessa forma é garantido que cada processo concorrente irá recuperar apenas
o primeiro registro cujo `status = 0` (ou nenhum registro, caso não tenha).
Entretanto, se tiver várias transações executando essa mesma consulta
concomitantemente, apenas uma delas irá executar por vez, as demais ficarão
bloqueadas. Se isso for uma espécie de fila, onde as várias transações são
usadas para melhorar a performance (processamento paralelo) e não deveriam
ser bloqueadas, daí a coisa complica um pouco mais. Veja se o resultado
acima atende, se não, nos informe aqui, pois há soluções para o caso que
citei.
OBS: Quanto ao UPDATE, caso tenha muitos registros, seria melhor usar um
CURSOR e a cláusula WHERE CURRENT OF <cursor> no UPDATE.
Acho que é isso.
>
> Muito obrigado
>
>
> Em 6 de dezembro de 2013 10:52, Fabrízio de Royes Mello <
> [email protected]> escreveu:
>
> On 05-12-2013 16:04, José Mello Júnior wrote:
>>
>>> Preciso pegar um próximo registro antes de qualquer outro terminal como
>>> se fosse uma sequência. Qual o modo de isolamento mais recomendável?
>>>
>>> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
>>>
>>> Esse?
>>> Claro, depois dou um SELECT FOR UPDATE altero o status do registros e
>>> logo comito a transação.
>>>
>>>
>> Há algum tempo implementei o que vc necessita, veja em [1].
>>
>> Depois de vc rodar o "my_sequence.sql" em sua base de dados vc utiliza da
>> seguinte forma:
>>
>> fabrizio=# SELECT create_my_sequence('seq');
>> create_my_sequence
>> --------------------
>>
>> (1 row)
>>
>> fabrizio=# SELECT nextval_my_sequence('seq');
>> nextval_my_sequence
>> ---------------------
>> 1
>> (1 row)
>>
>> fabrizio=# SELECT nextval_my_sequence('seq');
>> nextval_my_sequence
>> ---------------------
>> 2
>> (1 row)
>>
>>
>> Vc pode testar em 2 sessoes abertas e executar dentro de uma transacao
>> para testar.
>>
>> Att,
>>
>>
>> [1] https://dl.dropboxusercontent.com/u/4342654/my_sequence.tar.bz2
>>
>> --
>> Fabrízio de Royes Mello Timbira - http://www.timbira.com.br/
>> PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
>> _______________________________________________
>> pgbr-geral mailing list
>> [email protected]
>> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>>
>
>
>
> --
> Mello Júnior
> 41.3252-3555
>
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
>
--
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral