[firebase-br] Travar registro no BD
Escovador de Bits
escovadordebits em gmail.com
Sáb Jun 6 12:26:21 -03 2009
Bom dia/tarde Marcelo.
Grande Marcelo, aqui vai a minha humilde sugestão:
Cada instância da aplicação é um processo separado, independente de está
sendo executado em máquinas diferentes ou na mesma máquina.
O próprio sistema operacional gera um número de identificação de
processo (PID), como se fosse um CPF do processo, e dependendo da
linguagem de programação a ser utilizada, você tem como obter o número
do seu processo. E em último caso, a aplicação pode simplesmente gerar
um número aleatório.
Utilizando o número do próprio processo, ou um valor aleatório,
raramente o valor gerado por um processo coincidirá com o valor gerado
por outro processo.
Seguindo essa lógica, poderia executar os seguintes passos:
1 - Acrescente um campo de "identificação de processo", ou seja, algo como:
ALTER TABLE CAMPANHA_LANCAMENTO ADD IDENTIFICADOR INTEGER;
2 - Crie um índice para agilizar as pesquisas pelo novo campo:
CREATE INDEX IX_CAMP_LANC_IDENT ON CAMPANHA_LANCAMENTO (IDENTIFICADOR);
Acredito que você já tenha criado um índice para o campo ENVIADO.
3 - Inicie uma nova transação (com ReadCommited e Wait).
4 - Para reservar um dos registros, execute um comando SQL como o seguinte:
UPDATE CAMPANHA_LANCAMENTO CL SET
CL.IDENTIFICADOR = <número-do-processo>
WHERE
(EXISTS(SELECT C.ID_CAMPANHA FROM CAMPANHA C WHERE C.ID_CAMPANHA =
CL.ID_CAMPANHA))AND
(CL.ENVIADO = 'N')AND
(CL.IDENTIFICADOR IS NULL);
5 - Efetive (commit) a transação atual que é muito curta.
6 - Verifique se conseguiu reservar algum registro:
SELECT
*
FROM
CAMPANHA_LANCAMENTO
WHERE
IDENTIFICADOR = <número-do-processo>;
Normalmente, quando você configura uma transação para esperar por algum
tempo (wait), caso haja algum conflito de travas, o Firebird espera por
cerca de 10 segundos (padrão) até que o conflito seja resolvido.
Caso o conflito não seja resolvido nesse tempo (que é configurado na
própria transação quando ela é iniciada), apenas uma das transações
conflitantes é eleita para prosseguir, e as demais recebem o respectivo
erro de conflito.
Como os passos 3, 4 e 5 ocorrem muito rapidamente, dificilmente atingirá
o tempo limite de espera, e nesse caso, acredito que mesmo que vários
processos tentem alterar o mesmo registro, nenhum deles receberá a
mensagem de erro de conflito, e o último valor salvo no campo
IDENTIFICADOR permanecerá.
No passo 6, cada processo já terá reservado, ou não, algum registro, e
nesse passo não haverá conflito, pois cada processo acessará o registro
que terá o seu próprio identificador.
Dessa forma, após efetuar o processamento daquele registro, o processo
pode executar, sem problemas, o seguinte comando SQL:
UPDATE CAMPANHA_LANCAMENTO SET
IDENTIFICADOR = NULL,
ENVIADO = 'S'
WHERE
IDENTIFICADOR = <número-do-processo>;
De qualquer forama, é apenas uma sugestão de solução.
Espero ter ajudado mais que atrapalhado. :D
Marcelo Moreira escreveu:
> Pessoal,
> Boa tarde!
>
> Preciso que um determinado registro na tabela seja travado de modo que outro
> usuario nao tenha acesso ha ele. Vou tentar explicar a situação:
> O sistema vai fazer o envio de email e os cliente para quem ele deve mandar
> o emai vai ficar nesta tal tabela. o que acontece é que vao ser mais de um
> sistema aberto fazendo o envio destes email e o sql que estou usando para
> pegar sempre o ultimo registro que ainda nao foi enviado o email seria este:
>
>
> select
> first( 1 )
> CL.NUMERO,
> C.MENSAGEM
>
> from
> CAMPANHA_LANCAMENTO CL
>
> inner join CAMPANHA C on (CL.ID_CAMPANHA = C.ID_CAMPANHA)
>
> where
> CL.ENVIADO = 'N'
>
> ou seja nenhum outro sistema quando fizer o mesmo select nao pode ter acesso
> a este registro. e depois que o sistema fizer o envio do email eu altero o
> campo: CL.ENVIADO = 'S'
>
> Como eu poderia resolver isto.
>
> Obrigado pela atencao.
>
> Abraços
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
> Para saber como gerenciar/excluir seu cadastro na lista, use: http://www.firebase.com.br/fb/artigo.php?id=1107
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
>
Mais detalhes sobre a lista de discussão lista