Pergunta

Eu tenho 2 programas em lotes, 1 é um programa que envia e-mail e um outro envia fax. Ambos acesso uma tabela chamada QUEUE.

No programa de e-mail do remetente, este é o que acontece em relação ao QUEUE. Para cada registro em QUEUE que os critérios satisfaz:

  1. recorde Locks 1 na tabela QUEUE:
    select 1 from QUEUE with (UPDLOCK) where id = 1
  2. Processo de envio de e-mail
  3. Excluir registro 1 na tabela FILA:
    delete from QUEUE where id = 1
  4. confirmar a transação (transação não é auto-commit)

No programa fax remetente, medidas semelhantes também acontecem, exceto que no passo 2, enviamos fax (é claro).

O problema é que às vezes a exclusão de QUEUE lança uma exceção que ele está bloqueado. Assim, re-envio dos e-mails / fax acontece. Estou certo de que o grupo de registros processados ??por esses programas não se cruzam.

Parece que tentativas de exclusão para obter um bloqueio Update (U) em outros registros na tabela, embora apenas um registro deve ser excluído. Então exceção acontece quando outras transações têm bloqueios em outros registros na mesma tabela.

Com isso, eu preciso saber se há uma opção para fazer "delete" operação não fechaduras adquirir por outros do que para o registro vai excluir registros. Porque parece que o problema é com os "delete" Levando fechaduras de operação em outros registros na tabela.

A propósito, aqui estão algumas informações sobre o banco de dados (não tenho certeza se eles vão ajudá):

  • Read Committed Snapshot está ligado
  • Snapshot Isolation Estado está em
Foi útil?

Solução

Você já tentou usar a dica COM ROWLOCK ou COM NOLOCK na instrução de exclusão?

Você já leu este artigo ? ele sugere que você usa (UPDLOCK, READPAST) para evitar o problema seu Encontrando

Outras dicas

Às vezes um bloqueio escaladas de travar uma única linha na travando uma seção de uma mesa ou bloqueando uma tabela inteira. Isso é mais provável porque você está recebendo bloqueios em registros que você não está realmente usando na transação.

Em vez de usar uma transação para bloquear os registros, você poderia usar um campo de status para sinalizar os registros que são processados.

Exemplo:

Bloqueio de alguns registros, em seguida, obter o registro que foi bloqueado com êxito:

update queue set status = 'email_processing' where status is null and id = 1
select email, message from queue where status = 'email_processing'

Quando você não estiver usando explicitamente uma transação cada consulta é executada em sua própria transação, assim que a consulta de actualização pode mudar com segurança o status como é verificar o status atual na mesma consulta.

Quando terminar de enviar, excluir os registros:

delete from queue where status = 'email_processing'

O remetente fax seria, naturalmente, utilizar um status diferente (como 'fax_processing'), de modo que os registros sinalizadas são isolados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top