Lidando com erros não reprodutíveis

70

Suponha que sua equipe escreva um sistema de software que esteja funcionando bem.

Um dia, um dos engenheiros executa, por engano, algumas consultas SQL que alteram alguns dos dados do banco de dados e, em seguida, se esquecem disso.

Depois de algum tempo você descobre os dados corrompidos / errados e todo mundo coça a cabeça sobre qual parte do código causou isso e por que, sem sucesso. Enquanto isso, o gerente de projeto insiste em encontrar a parte do código que causou isso.

Como você lida com isso?

    
por Nik Kyriakides 25.10.2018 / 21:39
fonte

9 respostas

130

É óbvio que nenhum gerente de projeto investirá uma quantidade infinita de tempo em tal problema. Eles querem impedir que a mesma situação aconteça novamente.

Para atingir esse objetivo, mesmo que não seja possível encontrar a causa raiz de tal falha, muitas vezes é possível tomar algumas medidas para

  • Detectar essas falhas anteriormente, caso ocorram novamente
  • Torne menos provável que a mesma falha aconteça novamente
  • Torne o sistema mais robusto em relação ao tipo específico de inconsistência

Por exemplo, um registro mais detalhado, um tratamento de erros mais refinado ou uma sinalização de erro imediata podem ajudar a evitar que o mesmo erro ocorra novamente ou a encontrar a causa raiz. Se o seu sistema permitir adicionar acionadores de banco de dados, talvez seja possível adicionar um acionador que proíba a inconsistência sendo introduzida em primeiro lugar.

Pense em qual tipo de ação apropriada pode estar em sua situação e sugira isso para a equipe; Tenho certeza de que seu gerente de projetos ficará satisfeito.

One day one of the engineers mistakenly runs some SQL queries that change some of the DB data, then forgets about it.

Como mencionado por outros, também é uma boa idéia proibir tal procedimento (se você tiver influência sobre como o sistema é operado). Ninguém deve ter permissão para executar consultas ad-hoc não documentadas que alteram o conteúdo do banco de dados. Se houver necessidade de tal consulta, verifique se há uma política para armazenar a consulta junto com sua data de execução, o nome da pessoa que a executou e o motivo pelo qual ela foi usada, em um local documentado.

    
por 25.10.2018 / 22:20
fonte
47

Isso não é um bug

Pelo menos não no seu código. É um bug no seu processo . Seu gerente de projetos deve estar muito mais preocupado com seu processo do que com seu código.

How do you deal with this?

Simplesmente, não permitindo que engenheiros mudem a produção ou compartilhem bancos de dados de desenvolvimento .

Supondo que este é um banco de dados de desenvolvimento compartilhado:

Idealmente, se for possível, evite ter um banco de dados compartilhado em primeiro lugar . Em vez disso, ter bancos de dados por desenvolvedor que são de curta duração. Isso deve ser automatizado com scripts, caso contrário, o custo para testar se tornará muito grande, e há um incentivo para não testar as coisas. Você pode ter esses bancos de dados na estação de trabalho do desenvolvedor ou em um servidor central.

Se, por alguma razão, você absolutamente DEVERÁ ter um banco de dados compartilhado, você deve usar equipamentos - essencialmente, algo que define o banco de dados para um estado em bom estado toda vez que você precisar usá-lo. Isso evita que os desenvolvedores sejam mordidos pelas alterações de outras pessoas.

Se você precisar aplicar alterações permanentes ao banco de dados, você deve submetê-las ao seu controle de origem . Configure seu banco de dados de tal forma que os desenvolvedores não tenham permissão para escrever diretamente nele e tenha um programa que extraia alterações do controle de origem e as aplique.

Por fim, da sua descrição sobre como você depura as coisas, parece que você não está usando o IC . Use CI . É um pouco difícil configurar, mas vai economizar muito tempo a longo prazo, para não mencionar que você não se preocupe com bugs de banco de dados não reproduzíveis. Você só precisa se preocupar com heisenbugs agora!

Supondo que este é um banco de dados de produção:

Se seus desenvolvedores estão alterando bancos de dados de produção, muitas coisas deram muito errado, mesmo que as alterações estejam absolutamente corretas.

Os desenvolvedores nunca devem acessar bancos de dados de produção . Não há absolutamente nenhuma razão para isso, e tantas coisas que podem se tornar muito muito erradas.

Se você precisar corrigir algo em um banco de dados de produção, primeiro faça backup, restaure esse backup em uma instância diferente (desenvolvimento) e brincar com esse banco de dados de desenvolvimento. Uma vez que você acha que tem uma correção pronta (no controle de origem!), Você refaz a restauração, aplica a correção e vê o resultado. Então, depois de fazer o backup novamente (e, idealmente, impedir atualizações simultâneas), você conserta a instância de produção, de preferência através de um patch de software.

Se você precisar testar algo em um banco de dados de produção ... não, você não precisa. Quaisquer testes que você precise fazer, você deve fazer em uma instância de desenvolvimento. Se você precisar de alguns dados para fazer os testes, você obtém os dados lá.

    
por 26.10.2018 / 02:43
fonte
13

Um banco de dados de produção deve ter registros de acesso total e controles de acesso baseados em função. Assim, você deve ter provas concretas de que a OMS fez o que, ao banco de dados, transferiu a atenção do código para uma segurança operacional precária.

    
por 25.10.2018 / 22:48
fonte
6

Neste caso, você acabou descobrindo a causa, mas considerando a sua hipotética que você não ...

Primeiro, analise o que mudou. Se o sistema estava funcionando bem antes, uma olhada cuidadosa em tudo que foi feito recentemente pode revelar a mudança que causou o bug. Revise sistematicamente seu controle de versão, sistemas de IC / implantação e controle de configuração para ver se algo mudou. Execute git bisect ou um mecanismo equivalente para executar uma pesquisa binária. Verifique os registros. Procure por logs que você não sabia que tinha. Converse com todos com acesso ao sistema para ver se eles fizeram algo recentemente. Para o seu problema, se você for aprofundado o suficiente neste processo, isso deve revelar as consultas SQL esquecidas.

Segundo, instrumentação. Se você não puder encontrar diretamente a causa de um bug, adicione instrumentação ao redor para coletar dados sobre o problema. Pergunte a si mesmo "se eu pudesse reproduzir esse bug no comando, o que eu gostaria de ver no depurador" e registre isso. Repita conforme necessário até ter uma melhor compreensão do problema. Como sugerido por Doc Brown, adicione registros para os estados relevantes para o bug. Adicione asserções que detectem dados corrompidos. Por exemplo, se o seu erro for uma falha de aplicativo, adicione um mecanismo de registro de falhas. Se você já tiver uma, ótimo, adicione anotações aos registros de falhas para registrar o estado potencialmente relevante para a falha. Considere se os problemas de simultaneidade podem estar envolvidos e teste para realizar a segurança dos segmentos .

Em terceiro lugar, a resiliência. Bugs são inevitáveis, então pergunte a si mesmo como você pode melhorar seus sistemas para serem mais resilientes, para que a recuperação do bug seja mais fácil. Seus backups podem ser melhorados (ou existentes)? Melhor monitoramento, failover e alertas? Mais redundância? Melhor tratamento de erros? Desassociar os serviços dependentes uns dos outros? Você pode melhorar seus processos em torno do acesso ao banco de dados e consultas manuais? Na melhor das hipóteses, essas coisas farão com que as conseqüências de seu bug sejam menos severas e, na pior das hipóteses, provavelmente sejam boas coisas para fazer de qualquer maneira.

    
por 26.10.2018 / 09:33
fonte
4
  1. Explique ao seu gerente de projeto que você acha que a causa mais provável é o acesso manual ao banco de dados.
  2. Se eles ainda quiserem que você procure o código que causou isso, vá e dê outra olhada no código.
  3. Volte em algumas horas (ou em algum outro momento apropriado) e diga que não é possível encontrar nenhum código que possa ter causado isso, portanto, você ainda acredita que a causa mais provável seja o acesso manual ao banco de dados.
  4. Se eles ainda quiserem que você procure o código, pergunte quanto tempo eles gostariam que você gastasse com isso. Subtilmente, lembre-os de que você não estará trabalhando no recurso X, no bug Y ou no aprimoramento Z enquanto estiver fazendo isso.
  5. Gastar o tempo que eles pedem. Se você ainda acha que a causa mais provável é o acesso manual ao banco de dados, informe isso.
  6. Se eles ainda quiserem que você procure pelo código, aumente o problema, pois isso se tornou claramente um uso improdutivo do tempo da sua equipe.

Você também pode querer considerar se deve adicionar um processo extra para reduzir a probabilidade de acesso manual ao banco de dados, causando esse tipo de problema no futuro.

    
por 25.10.2018 / 22:04
fonte
3

Da minha experiência, o que seu chefe quer é uma garantia de que isso não voltará a ocorrer. Se for o caso que nenhum código foi a causa, porque isso é assegurado pelo teste de unidade, portanto, supondo que você já tenha cobertura de teste em sua base de código, a solução deve estar adicionando "testes" ao seu banco de dados. Vou citar Don Gilman, porque ele pregou lá:

A production database should have full access logging and role based access controls. Thus you should have hard evidence as to WHO did WHAT WHEN to the database thus moving the attention from the code to poor operational security.

Mas também, você deve ter o Procedimento Operacional Padrão para alterar dados em produção. Por exemplo, nenhum DBA deve alterar dados, nenhum desenvolvedor deve executar a alteração e eles devem, conforme definido no SOP, exigir um ao outro formalmente a alteração por correspondência ou ticket.

Deve haver uma citação como essa em algum lugar, se você não puder me citar:

There is a perfectly good reason for chefs not being the ones responsible for cleaning toilets.

    
por 26.10.2018 / 02:47
fonte
2

Eu estava trabalhando na equipe de desenvolvimento de um produto de banco de dados de mainframe quando um cliente relatou que tinha um banco de dados corrompido. Uma corrupção no sentido de que o estado interno dos bits no disco significava que o banco de dados não era legível por meio do software de banco de dados. No mundo do mainframe, os clientes estão pagando milhões de dólares e você precisa levar isso a sério. Foi isso que fizemos:

Passo 0: ajude o cliente a voltar a funcionar, reparando a base de dados.

Passo 1: examinando o arquivo no disco no nível hexadecimal, determinamos que a corrupção era sistemática: havia muitos casos da mesma corrupção. Por isso, foi definitivamente causado ao nível do software de banco de dados. De fato, foi suficientemente sistemático que sentimos que poderíamos descartar problemas multi-threading.

Após eliminar muitas outras teorias, nós nos hospedamos em um utilitário que poderia ser usado para reorganização física do banco de dados. Parecia ser o único código que tinha acesso aos dados no nível certo. Descobrimos então uma maneira de executar esse utilitário, com opções cuidadosamente selecionadas, que reproduziam o problema. O cliente não pôde confirmar ou negar que isso era o que eles haviam feito, mas como essa era a única explicação que podíamos sugerir, decidimos que essa era a causa provável, e eles tinham pouca escolha a não ser aceitar nosso diagnóstico. .

Etapa 2: Fizemos duas alterações no software: (a) tornou mais difícil causar esse efeito acidentalmente por meio de uma interface de usuário "sim, eu sei o que estou fazendo" e (b) a introdução de um novo arquivo de log para que, se isso acontecesse novamente, tivéssemos um registro das ações do usuário.

Então, basicamente (a) conserte o dano e restaure a corrida ao vivo, (b) encontre a causa raiz, (c) faça o que for necessário para evitar que isso aconteça novamente ou para facilitar o diagnóstico, se ocorrer novamente.

    
por 29.10.2018 / 15:54
fonte
1

Existem várias coisas que devem ser feitas com erros não reprodutíveis.

  1. Crie um ticket para ele

Crie um ticket e registre tudo que puder imaginar no ticket. Além disso, verifique se esse "bug" foi registrado antes e vincule os tickets juntos. Eventualmente você pode obter ingressos suficientes para estabelecer um padrão de como reproduzir o bug. Isso inclui o trabalho usado para tentar evitá-lo. Mesmo se este for o único caso, se houver uma primeira vez, haverá eventualmente a segunda vez. Quando você encontrar a causa, feche o ticket com uma explicação de qual foi a causa, para que você tenha uma strong ideia do que aconteceu se isso acontecer novamente (consertar perdido em má fusão)

  1. Faça uma análise de endurecimento

Veja o sistema, o que falhou e como ele falhou. Tente encontrar a área do código que pode ser atualizada para tornar a falha menos provável. Alguns exemplos ...

  • Substitua o código ad-hoc por uma chamada dedicada (como execute(<query>) with executeMyStoredProcedure(<params>)
  • Executar scripts de verificação noturna para verificar a integridade dos dados (para que isso possa ser detectado em 24 horas da próxima vez)
  • Adicionar / melhorar registro e arquivamento (backup).
  • Alterar limites de segurança impróprios (por exemplo, pessoas / programas que apenas leem dados não têm permissão de gravação; não permitem que desenvolvedores responsáveis pela produção façam logon nos servidores de produção)
  • Adicionar verificação / saneamento de dados em falta

Isso pode não corrigir o bug, mas, mesmo que isso não aconteça, o sistema agora está mais estável / seguro, por isso ainda vale a pena.

  1. Adicione alertas do sistema

Meio que parte de 2, mas algo aconteceu, e você precisa saber quando isso acontece novamente. Você deve criar alguns scripts / programas de verificação de integridade para monitorar o sistema, para que os administradores possam ser alertados dentro de 24 horas do resurfacing do bug (quanto menos atraso, melhor, dentro do razoável). Isso facilitará muito a limpeza. (Observe que, além dos logs dos bancos de dados, o sistema operacional também deve registrar as pessoas que efetuam login e as ações não lidas que realizam. No mínimo, deve haver logs de tráfego de rede para essa máquina)

    
por 26.10.2018 / 23:01
fonte
0

Seu problema não foi causado por uma falha em seu software, mas por alguém que está mexendo no banco de dados. Se você chamar as coisas de erradas de um "bug", então o seu bug é facilmente reproduzível: As coisas sempre vão mal quando alguém faz coisas estúpidas no banco de dados. E existem maneiras de evitar esse "bug", não permitindo que o banco de dados seja modificado manualmente ou usando software não testado, e controlando estritamente quem pode modificar o banco de dados.

Se você apenas invoca falhas no seu banco de dados como um "bug", então você não tem um bug irreproduzível, você não tem nenhum bug. Você pode ter um relatório de bug, mas você também tem evidências de que o problema não foi causado por um bug. Então você pode fechar o relatório de bug, não como "irreproduzível", mas algo como "banco de dados danificado". Não é incomum ter relatórios de bugs onde a investigação mostra que não há bug, mas um usuário usou o software errado, as expectativas do usuário estavam erradas etc.

Nesse caso, você ainda sabe que há um problema com o qual você não deseja ser repetido, portanto, você realiza a mesma ação do primeiro caso.

    
por 27.10.2018 / 10:26
fonte