Pergunta

Eu projetei tabelas de banco de dados (normalizadas, em um servidor MS SQL) e criei um front-end independente do Windows para um aplicativo que será usado por alguns usuários para adicionar e editar informações.Adicionaremos uma interface web para permitir pesquisas em nossa área de produção posteriormente.

Estou preocupado que se dois usuários começarem a editar o mesmo registro, o último a confirmar a atualização será o 'vencedor' e informações importantes poderão ser perdidas.Várias soluções vêm à mente, mas não tenho certeza se vou criar uma dor de cabeça maior.

  1. Não faça nada e espere que dois usuários nunca editem o mesmo registro ao mesmo tempo. - Pode nunca ter acontecido, mas e se acontecer?
  2. A rotina de edição pode armazenar uma cópia dos dados originais, bem como das atualizações, e então comparar quando o usuário terminar a edição.Se eles diferirem, mostre o usuário e confirme a atualização - Seria necessário armazenar duas cópias dos dados.
  3. Adicione a última coluna DATETIME atualizada e verifique se ela corresponde quando atualizamos, caso contrário, mostre as diferenças. - requer nova coluna em cada uma das tabelas relevantes.
  4. Crie uma tabela de edição que registre quando os usuários iniciam a edição de um registro que será verificado e evitará que outros usuários editem o mesmo registro. - exigiria uma reflexão cuidadosa sobre o fluxo do programa para evitar conflitos e registros bloqueados se um usuário saísse do programa.

Existem soluções melhores ou devo optar por uma delas?

Foi útil?

Solução

Se você espera colisões pouco frequentes, Simultaneidade otimista é provavelmente sua melhor aposta.

Scott Mitchell escreveu um tutorial abrangente sobre a implementação desse padrão:
Implementando simultaneidade otimista

Outras dicas

Uma abordagem clássica é a seguinte:

  • adicione um campo booleano, "bloqueado" para cada tabela.
  • defina isso como falso por padrão.
  • quando um usuário começa a editar, você faz o seguinte:

    • bloqueie a linha (ou a tabela inteira se você não conseguir bloquear a linha)
    • marque a bandeira na linha que você deseja editar
    • se a bandeira for verdadeira então
      • informar ao usuário que ele não pode editar essa linha no momento
    • outro
      • defina o sinalizador como verdadeiro
    • liberar o bloqueio

    • ao salvar o registro, defina o sinalizador novamente como falso

SELECT FOR UPDATE e equivalentes são bons, desde que você mantenha a trava por um período microscópico de tempo, mas por um período macroscópico (por exemplo,o usuário carregou os dados e não pressionou 'salvar', você deve usar simultaneidade otimista como acima.(O que eu sempre acho que é um nome errado - é mais pessimista do que 'o último escritor vence', que geralmente é a única outra alternativa considerada.)

@Mark Harrison:O SQL Server não oferece suporte a essa sintaxe (SELECT ... FOR UPDATE).

O equivalente do SQL Server é o SELECT dica de declaração UPDLOCK.

Ver Manuais on-line do SQL Server Para maiores informações.

-primeiro Criar arquivado (hora da atualização) para armazenar o último registro de atualização -Quando qualquer usuário selecionar gravar Salvar tempo Selecionar tempo, compare entre o tempo de seleção e a atualização do tempo se (hora de atualizar)> (selecionar tempo) que significa que outro usuário atualize esse registro após selecionar registro

Outra opção é testar se os valores no registro que você está alterando ainda são os mesmos de quando você começou:

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(exibe o campo customer_nm e o usuário o altera)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

Você não precisa adicionar uma nova coluna à sua tabela (e mantê-la atualizada), mas precisa criar instruções SQL mais detalhadas e passar novo e velho campos para o procedimento armazenado.

Também tem a vantagem de você não estar bloqueando os registros - porque todos sabemos que os registros acabarão ficando bloqueados quando não deveriam...

O banco de dados fará isso por você.Veja "selecionar ...for update", que foi projetado apenas para esse tipo de coisa.Isso lhe dará um bloqueio de gravação nas linhas selecionadas, que você poderá confirmar ou reverter.

Comigo, a melhor maneira de ter uma coluna lastupdate (tipo de dados timetamp).Quando selecionar e atualizar, basta comparar esse valor. Outro avanço desta solução é que você pode usar esta coluna para rastrear os dados do tempo que mudou.Eu acho que não é bom se você apenas criar uma coluna como isLock para atualização de verificação.

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